如何将 react-native 图片从 expo-image-picker 上传到使用 multer 的 Express.js 后端
How to upload react-native image from expo-image-picker to Express.js backend that is using multer
正如标题所说,我正在尝试使用 expo-image-picker 和 express.js 后端上传图片
展会代码:
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);
}
快递编码
路由器:
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)
更新照片功能:
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)
}
}
我得到的错误是
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)
这很可能意味着 object 未被传递或无法正确解析。
当我测试使用 Postman 仅通过后端上传图片时一切正常。
邮递员预设:
如何解决这个问题?
不要使用 axios 进行文件上传,因为您需要从本机文件系统读取图像。您可以使用 Expo 的 FileSystem
模块中的 uploadAsync()
。 Documentation Here
在您的情况下,函数调用将是:
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'
});
}
}
顺便说一句,请避免使用 localhost,因为该应用可能 运行 在设备或模拟器上运行,而 localhost 将是设备本身,而不是您的网络服务器。通过环境变量传递 API 端点。更多信息 here。在开发过程中使用 dotenv
之类的东西来加载变量。
正如标题所说,我正在尝试使用 expo-image-picker 和 express.js 后端上传图片
展会代码:
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);
}
快递编码
路由器:
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)
更新照片功能:
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)
}
}
我得到的错误是
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)
这很可能意味着 object 未被传递或无法正确解析。
当我测试使用 Postman 仅通过后端上传图片时一切正常。 邮递员预设:
如何解决这个问题?
不要使用 axios 进行文件上传,因为您需要从本机文件系统读取图像。您可以使用 Expo 的 FileSystem
模块中的 uploadAsync()
。 Documentation Here
在您的情况下,函数调用将是:
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'
});
}
}
顺便说一句,请避免使用 localhost,因为该应用可能 运行 在设备或模拟器上运行,而 localhost 将是设备本身,而不是您的网络服务器。通过环境变量传递 API 端点。更多信息 here。在开发过程中使用 dotenv
之类的东西来加载变量。