Problem with upload file in expo react native - node.js

Hi i tried to upload file with expo:
the console.log give me this error "Streaming file uploads via req.file() are only available over HTTP with Skipper" but when i tried it with postman it's workd.I use sailsJs for my back-end
this is my code for my expo react
const[imageUri, setImageUri]=useState()
const[imageUpload, setImageUpload]=useState()
const selectImage = async()=>{
try {
const result = await ImagePicker.launchImageLibraryAsync();
if(!result.cancelled)
setImageUri(result.uri)
setImageUpload(result)
} catch (error) {
console.log('Error running on image')
}
}
const handleSubmit = async () => {
const dataDemande = {
projectTitle: titre,
material: materiel,
description: description,
projectType: checked,
lieuRendezvous: value_3,
idClient: props.route.params.id,
model: imageUpload
};
console.log(dataDemande);
var res = await demandeClient(dataDemande);
console.log(res);
props.navigation.navigate("Tableau de bord - Client");
};
and this is the code from the back-end
findCouturierAndCreateDemande: async function (req, res) {
var recherche = req.body
req.file('model').upload({
adapter: require('skipper-gridfs'),
uri: 'mongodb://localhost:27017/image'
}, async function (err, filesUploaded) {
if (err) return res.serverError(err);
console.log(filesUploaded[0].fd)
var couturier = await Client.find({
where: {
isCouturier: true,
ville: { contains: recherche.ville },
adresse: { contains: recherche.adresse },
rue: { contains: recherche.rue },
},
})
var img = await Image.create(_.omit(filesUploaded[0], ['status', 'field', 'extra'])).fetch()
var newDemande = await Demande.create({
titre: recherche.projectTitle,
materiel: recherche.material,
description: recherche.description,
service: recherche.projectType,
positionActivity: recherche.lieuRendezvous,
client: recherche.idClient,
modelImage: img.id
}).fetch()
console.log(img)
return res.ok({couturier, newDemande})
});
}

Related

Getting a not found error when trying to retrieve my audio files from mongoDB

When trying to retrieve my audio file from the backend server and then display it on the front I keep getting an error stating that GET http://localhost:4004/audio/song.m4a 404 (Not Found). I am using GridFS and multer to store the audio files inside of mongoDB. I was able to successfully send my audio file inside of the database but unable to retrieve the audio file and display it on the front end.
here is my front end code
import React, { useState, useEffect } from 'react';
function AudioUpload() {
const [audioFiles, setAudioFiles] = useState([]);
useEffect(() => {
async function fetchData() {
try {
const response = await fetch('http://localhost:4004/audio');
const data = await response.json();
console.log(data);
if (data.length > 0) {
setAudioFiles(data);
}
} catch (error) {
console.error(error);
}
}
fetchData();
}, []);
return (
<div>
{audioFiles.map((audio, index) => (
<div key={index}>
<audio src={`http://localhost:4004/audio/${audio.filename}`} controls>
Your browser does not support the audio element.
</audio>
</div>
))}
</div>
);
}
export default AudioUpload;
and here is my backend code:
const express = require('express');
const mongoose = require('mongoose');
const multer = require('multer');
const Grid = require('gridfs-stream');
const { GridFsStorage } = require('multer-gridfs-storage');
const cors = require("cors");
const app = express();
app.use(cors());
const conn = mongoose.createConnection('mongodb+srv://jordandeeds31:Jd400089#cluster0.iwva5ci.mongodb.net/grid2?retryWrites=true&w=majority', {
useNewUrlParser: true,
useUnifiedTopology: true,
});
let gfs;
conn.once('open', () => {
gfs = Grid(conn.db, mongoose.mongo);
gfs.collection('audioFiles');
console.log("connected to db");
});
const storage = new GridFsStorage({
url: 'mongodb+srv://jordandeeds31:Jd400089#cluster0.iwva5ci.mongodb.net/grid2?retryWrites=true&w=majority',
file: (req, file) => {
return {
filename: file.originalname,
bucketName: 'audioFiles',
};
},
});
const upload = multer({ storage: storage });
const audioSchema = new mongoose.Schema({
filename: { type: String, required: true },
contentType: { type: String, required: true },
fileId: { type: mongoose.Schema.Types.ObjectId, required: true },
});
const Audio = conn.model('Audio', audioSchema);
app.post('/upload', upload.single('audio'), async (req, res) => {
try {
const { originalname, mimetype } = req.file;
const fileId = req.file.id;
const audio = new Audio({
filename: originalname,
contentType: mimetype,
fileId,
});
await audio.save();
res.status(200).json({ message: 'File uploaded successfully' });
} catch (err) {
console.error(err);
res.status(500).json({ message: 'Error uploading file' });
}
});
app.get('/audio', async (req, res) => {
try {
const audioList = await Audio.find();
console.log(audioList)
if (!audioList) {
return res.status(404).json({ message: 'No audio files found' });
}
res.json(audioList);
} catch (err) {
console.error(err);
res.status(500).json({ message: 'Error retrieving files' });
}
});
app.listen(4004, () => {
console.log('Server listening on port 4004');
});

No able to send array from front end (reactJs) to the backend (nodejs)

This is the code for on my front end
When the object vendor is sent to the backend, the array key, value pair businessImages is empty [I came to this conclusion when nothing got console logged when I tried logging businessImages in the backend]
When I console log the vendor object, from the front end, it clearly shows that businessImages is populated. I have no idea what's going on.
Frontend code (reactjs)
const handleSubmit = async (e) => {
e.preventDefault();
if (businessImages.length > 15) {
alert("You've selected too many images for your business");
setBusinessImages([]);
} else {
const formDataBusinessImages = new FormData();
const formDataProfilePicture = new FormData();
vendor = {
name: name.current.value,
email: email.current.value,
mobileNumber: mobileNumber.current.value,
businessAddress: businessAddress.current.value,
mainService: selectedService,
subServive: selectedSubService,
businessImages: [],
aboutBusiness: aboutBusiness.current.value,
minPrice: minPrice.current.value,
maxPrice: maxPrice.current.value,
featured: featured,
};
formDataProfilePicture.append("file", profilePicture);
formDataProfilePicture.append(
"upload_preset",
process.env.REACT_APP_CLOUDINARY_KEY
);
try {
await axios
.post(
"https://api.cloudinary.com/v1_1/devign/image/upload",
formDataProfilePicture
)
.then((res) => {
console.log("Profile pic uploaded");
vendor.profilePicture = res.data.secure_url;
});
} catch (err) {
console.log(err);
}
businessImages.map(async (image) => {
formDataBusinessImages.append("file", image);
formDataBusinessImages.append("upload_preset", process.env.REACT_APP_CLOUDINARY_KEY);
try {
await axios
.post(
"https://api.cloudinary.com/v1_1/devign/image/upload",
formDataBusinessImages
)
.then((res) => {
vendor.businessImages.push(res.data.secure_url);
});
} catch (err) {
console.log(err);
}
});
handleUpload(vendor);
}
};
const handleUpload = async (uploadData) => {
try {
// console.log(businessImagesUrl);
// console.log(uploadData);
await axios.post("/auth/register", uploadData);
} catch (err) {
console.log(err);
}
};
Backend code (nodejs)
router.post("/register", async (req, res) => {
const newVendor = new Vendor({
name: req.body.name,
email: req.body.email,
mobileNumber: req.body.mobileNumber,
businessAddress: req.body.businessAddress,
mainService: req.body.mainService,
subService: req.body.subService,
profilePicture: req.body.profilePicture,
businessImages: [],
minPrice: req.body.minPrice,
maxPrice: req.body.maxPrice,
featured: req.body.featured,
});
try {
newVendor.businessImages.push(req.body.businessImages);
console.log(req.body.businessImages, req.body.profilePicture);
const vendor = await newVendor.save();
res.status(200).json("Successfully registered");
} catch (err) {
console.log(err);
}
});

My Chat List in isnt ordered according to newest chat

I am new to websockets and socket.io. I have a few challenges>
I have developed the application with react and nodejs using socket.io.
useEffect(() => {
const getAllChats = async (token) => {
try {
setLoading(true)
const res = await getChats(token)
if (res) {
setChats(res)
setLoading(false)
}
} catch (err) {
console.log(err)
setLoading(false)
}
}
getAllChats(user.token)
}, [])
export const getChats = (token) => {
return request(`/api/v1/chats`, {
token,
method: 'GET',
})
}
The above code is used to fetch the chat from the backend.
At the backend, I have the code:
exports.getAllChats = catchAsync(async (req, res, next) => {
const user = await Chat.findOne({ user: req.user._id }).populate(
'chats.messagesWith'
)
let chatsToBeSent = []
if (user.chats.length > 0) {
chatsToBeSent = await user.chats.map((chat) => ({
messagesWith: chat.messagesWith._id,
firstName: chat.messagesWith.firstName,
lastName: chat.messagesWith.lastName,
profilePicUrl: chat.messagesWith.profilePicUrl,
lastMessage: chat.messages[chat.messages.length - 1].msg,
date: chat.messages[chat.messages.length - 1].date,
}))
}
return res.json(chatsToBeSent)
})
How can I make new messages remain at the top of the list? Presently, It is always ordered by created date

API Only sends 1 chunk of metadata when called

I have a problem with my API that sends metadata when called from my smart contract of website. Its NFT tokens and my database is postgres and API is node.js
The problem is when I mint 1 NFT metadata works perfect, but if I mint 2 or more it will only ever send 1 chunk of data? So only 1 NFT will mint properly and the rest with no data?
Do I need to set a loop function or delay? Does anyone have any experience with this?
Any help would be much appreciated.
Below is the code from the "controller" folder labeled "nft.js"
const models = require("../../models/index");
const path = require("path");
const fs = require("fs");
module.exports = {
create_nft: async (req, res, next) => {
try {
const dir = path.resolve(__dirname + `../../../data/traitsfinal.json`);
const readCards = fs.readFileSync(dir, "utf8");
const parsed = JSON.parse(readCards);
console.log("ya data ha final ??", parsed);
parsed.forEach(async (item) => {
// return res.json(item)
let newNft = await models.NFT.create({
name: item.Name,
description: item.Description,
background: item.Background,
body: item.Body,
mouth: item.Mouth,
eyes: item.Eyes,
head_gear: item.Head_Gear,
tokenId: item.tokenId,
image: item.imagesIPFS,
});
});
return res.json({
data: "nft created",
error: null,
success: true,
});
} catch (error) {
console.log("server error", error.message);
next(error);
}
},
get_nft: async (req, res, next) => {
try {
const { id } = req.params;
// console.log("id ?????????",id)
// console.log("type of ",typeof(id))
// const n=Number(id)
// console.log("type of ",typeof(id))
const nft = await models.NFT.findByPk(id);
if (!nft) {
throw new Error("Token ID invalid");
}
if (!nft.isMinted) {
throw new Error("Token not minted");
}
console.log(nft);
// }
const resObj = {
name: nft.name,
description: nft.description,
image: `https://gateway.pinata.cloud/ipfs/${nft.image}`,
attributes: [
{ trait_type: "background", value: `${nft.background}` },
{ trait_type: "body", value: `${nft.body}` },
{ trait_type: "mouth", value: `${nft.mouth}` },
{ trait_type: "eyes", value: `${nft.eyes}` },
{ trait_type: "tokenId", value: `${nft.tokenId}` },
{
display_type: "number",
trait_type: "Serial No.",
value: id,
max_value: 1000,
},
],
};
return res.json(resObj);
} catch (error) {
console.log("server error", error.message);
next(error);
}
},
get_nft_all: async (req, res, next) => {
try {
// console.log("id ?????????",id)
// console.log("type of ",typeof(id))
// const n=Number(id)
// console.log("type of ",typeof(id))
const nft = await models.NFT.findAndCountAll({
limit: 10
});
// console.log(nft);
if (!nft) {
throw new Error("Token ID invalid");
}
// if (nft.isMinted) {
// throw new Error("Token not minted");
// }
// console.log(nft);
// }
var resObjarr = [];
for (var i = 0; i < nft.rows.length; i++) {
resObj = {
name: nft.rows[i].name,
description: nft.rows[i].description,
image: `https://gateway.pinata.cloud/ipfs/${nft.rows[i].image}`,
attributes: [
{ trait_type: "background", value: `${nft.rows[i].background}` },
{ trait_type: "body", value: `${nft.rows[i].body}` },
{ trait_type: "mouth", value: `${nft.rows[i].mouth}` },
{ trait_type: "eyes", value: `${nft.rows[i].eyes}` },
{ trait_type: "tokenId", value: `${nft.rows[i].tokenId}` },
{
display_type: "number",
trait_type: "Serial No.",
value: nft.rows[i].id,
max_value: 1000,
},
],
};
resObjarr.push(resObj);
}
console.log(JSON.stringify(resObjarr))
return res.json(resObjarr);
} catch (error) {
console.log("server error", error.message);
next(error);
}
},
mint: async (req, res, next) => {
try {
const { id } = req.params;
const updated = await models.NFT.findByPk(id);
if (!updated) {
throw new Error("NFT ID invalid");
}
if (updated.isMinted) {
throw new Error("NFT Already minted");
}
updated.isMinted = true;
updated.save();
return res.json({
data: "Token minted successfully",
error: null,
success: true,
});
} catch (error) {
console.log("server error", error.message);
next(error);
}
},
};
Below is from the routes folder.
const router = require("express").Router();
const auth=require("../middleware/auth")
const {
create_nft,
get_nft,
get_nft_all,
mint
} = require("../controller/nft");
router.post(
"/create",
create_nft
);
router.get(
"/metadata/:id",
get_nft
);
router.get(
"/metadata",
get_nft_all
);
router.put(
"/mint/:id",
mint
);
module.exports = router;
Looking your code,you may having some kind of asyncrhonous issue in this part:
parsed.forEach(async (item) => {
// return res.json(item)
let newNft = await models.NFT.create({
name: item.Name,
description: item.Description,
background: item.Background,
body: item.Body,
mouth: item.Mouth,
eyes: item.Eyes,
head_gear: item.Head_Gear,
tokenId: item.tokenId,
image: item.imagesIPFS,
});
});
Because .forEach is a function to be used in synchronous context and NFT.create returns a promise (that is async). So things happens out of order.
So one approach is to process the data first and then perform a batch operation using Promise.all.
const data = parsed.map(item => {
return models.NFT.create({
name: item.Name,
description: item.Description,
background: item.Background,
body: item.Body,
mouth: item.Mouth,
eyes: item.Eyes,
head_gear: item.Head_Gear,
tokenId: item.tokenId,
image: item.imagesIPFS,
})
})
const results = await Promise.all(data)
The main difference here is Promise.all resolves the N promises NFT.create in an async context in paralell. But if you are careful about the number of concurrent metadata that data may be too big to process in parallel, then you can use an async iteration provided by bluebird's Promise.map library.
const Promise = require('bluebird')
const data = await Promise.map(parsed, item => {
return models.NFT.create({
name: item.Name,
description: item.Description,
background: item.Background,
body: item.Body,
mouth: item.Mouth,
eyes: item.Eyes,
head_gear: item.Head_Gear,
tokenId: item.tokenId,
image: item.imagesIPFS,
})
})
return data

Unable to upload image/video files from react-native to nodejs

I am using expo-image-picker in react-native to pick image/video files and multer in nodejs as middleware to download files in directory /public/upload. When i am uploading file along with other parameters from react-native, multer is unable to detect a file present in req.body and hence not downloading any file.
Here is my react-native code using axios
pickImage = async () => {
try {
let options = {
mediaTypes: ImagePicker.MediaTypeOptions.Images,
quality: 1,
// base64:true
}
let result = await ImagePicker.launchImageLibraryAsync(options)
if (!result.cancelled) {
this.setState({ content: result })
}
} catch (E) {
console.log("error in picking image:", E)
}
}
createFormData = (response) => {
const photo = {
uri: response.uri,
type: response.type,
name: "my-img.jpg",
};
const form = new FormData();
form.append('acivityFile',photo);
return form;
};
handleSubmit = async () => {
if (this.state.content) {
const formData = this.createFormData(this.state.content)
console.log("form data:", formData)
try {
const res = await axios.post('http://393ad751391b.ngrok.io/activities',
{
title: "This is the title",
description: "This is a description",
eventType: "LOST & FOUND",
file: formData
},
{
headers: {
'Accept': 'application/json',
'Content-Type': 'multipart/form-data'
},
},
)
console.log("res:", res.data);
} catch (err) {
console.log("err in post axios:",err)
}
}
}
Here is my route file handling http requests in server-side
const express = require('express');
const Upload = require('./../utils/multerSetup');
const activityController = require('../Controllers/activityController');
const router = express.Router();
router
.route('/')
.get(activityController.getAllActivities)
.post(
Upload.single('activityFile'),
activityController.addActivity
);
Here is my multerSetup.js file in server-side
const multer = require('multer');
const storage = multer.diskStorage({
destination: function (req, file, cb) {
cb(null, 'public/uploads/');
},
filename: function (req, file, cb) {
const ext = file.mimetype.split('/')[1];
cb(null, file.fieldname + '-' + Date.now() + '.' + ext);
},
});
const upload = multer({ storage });
module.exports = upload;
Here is my activityController.js file in server-side
const Activity = require('./../modals/activityModel');
const User = require('./../modals/user');
exports.getActivity = async (req, res, next) => {
console.log('here');
const activity = await Activity.findById(req.params.id);
res.status(200).json({
status: 'success',
data: {
activity,
},
});
};
exports.addActivity = async (req, res, next) => {
if (req.file) {
let file = {
Ftype: req.file.mimetype.split('/')[0],
name: req.file.filename,
};
req.body.file = file;
}
if (!req.body.location) {
req.body.location = {
coordinates: ['77.206612', '28.524578'],
};
}
if (req.body.votes) {
req.body.votes.diff = req.body.votes.up - req.body.votes.down;
}
req.body.creator = "12345" || "req.userId";
const activity = await Activity.create(req.body);
res.status(201).json({
status: 'success',
data: {
activity,
},
});
};
Also when Content-type:'multipart/form-data, then server console throws Error: Multipart:Boundary not found. When i use Content-type:'application/json', then multer does not work.
I just want to know what is the correct way of uploading files with additional parameters from react-native to nodejs multer. Any suggestions would be a great help!

Resources