as title says, I am trying to upload picture using expo-image-picker and express.js backend
Expo code:
const openImagePickerAsync = async () => {
let permissionResult = await ImagePicker.requestMediaLibraryPermissionsAsync();
if (permissionResult.granted === false) {
alert("Permission to access camera roll is required!");
return;
}
let pickerResult = await ImagePicker.launchImageLibraryAsync();
const dataa = Object.values(pickerResult);
var data = new FormData();
data.append('image', {
path: dataa[2], //image uri
originalname: "profilePic" userId ".jpg",
type: "image/jpg",
fieldname: "demo_image"
})
console.log(data)
const uploadImage = await axios.post(`http://localhost:8000/api/upload/picture/` userId, data); }
Express code: Router:
var multer = require("multer")
var storage = multer.diskStorage({
destination: function(req, file, cb) {
console.log(file)
cb(null, './controllers/assets/profilePic/');
},
filename: function (req, file, cb) {
console.log(file)
cb(null , file.originalname);
}
});
var upload = multer({ storage: storage }).single("demo_image");
router.route("/upload/picture/:userId").post(upload, UserController.updatePhoto)
updatePhoto function:
static updateGamePhoto = async (req, res) => {
try {
const query = await GamMdl.find({game_id: req.params.gameId})
console.log(req.file)
if(query.length > 0){
//get file route
//get route to db
const queryy = await GamMdl.updateOne({game_id: req.params.gameId}, {picture: req.file.originalname})
console.log(queryy)
res.send("1")
}
else
{
//vymaz file
fs.unlinkSync(req.file.path)
res.send("0")
}
}
catch (error) {
console.log(error)
}
}
The error I am getting is
2022-04-10T18:17:29.165105 00:00 app[web.1]: undefined
2022-04-10T18:17:29.165435 00:00 app[web.1]: TypeError: Cannot read properties of undefined (reading 'originalname')
2022-04-10T18:17:29.165436 00:00 app[web.1]: at updatePhoto (/app/controllers/userController.js:166:119)
2022-04-10T18:17:29.165436 00:00 app[web.1]: at runMicrotasks (<anonymous>)
2022-04-10T18:17:29.165439 00:00 app[web.1]: at processTicksAndRejections (node:internal/process/task_queues:96:5)
Which most likely means, that object is not being passed or is unable to be parsed correctly.
When I test uploading image only with backend using Postman all works well. Postman preset:
How to fix this?
CodePudding user response:
Don't use axios for file upload because you need to read the image from the native filesystem. You can use uploadAsync()
from the FileSystem
module from Expo. Documentation Here
In your case the function call would be:
const openImagePickerAsync = async () => {
let permissionResult = await ImagePicker.requestMediaLibraryPermissionsAsync();
if (permissionResult.granted === false) {
alert("Permission to access camera roll is required!");
return;
}
let pickerResult = await ImagePicker.launchImageLibraryAsync();
if (!pickerResult.cancelled) {
const uploadResult = await FileSystem.uploadAsync('http://localhost:8000/upload/picture/1', pickerResult.uri, {
httpMethod: 'POST',
uploadType: FileSystemUploadType.MULTIPART,
fieldName: 'demo_image'
});
}
}
By the way, avoid using localhost since the app may run on a device or emulator, and localhost would be the device itself instead of your webserver. Pass the API endpoint via environment variables. More info here. Use something like dotenv
to load variables during development.