我对 React Native 开发非常陌生。从过去的两天开始,我一直在努力破解使用 React Native 到 MongoDB(Grid FS)的文件/图像上传。我从字面上阅读了所有相关的论坛,但没有运气。我阅读了几个论坛,他们给出了一个示例,但我没有成功。这是我编写的示例代码。
客户端 JS(反应原生):
import React, { Component } from "react";
import { View, Text, Image, Button, Platform } from "react-native";
import ImagePicker from "react-native-image-picker";
class ImagePickerComponent extends Component {
state = {
photo: null
};
handleChoosePhoto = () => {
const options = {
noData: true
};
ImagePicker.launchImageLibrary(options, response => {
if (response.uri) {
this.setState({ photo: response });
}
});
};
handleUploadPhoto = () => {
const { photo } = this.state;
const bodyJson = { userId: "123" };
console.log("PHOTO");
console.log(photo);
const data = new FormData();
data.append("name", "avatar");
data.append("file", {
uri: photo.uri,
type: photo.type,
name: photo.fileName
});
const config = {
method: "POST",
headers: {
Accept: "application/json"
// "Content-Type": "multipart/form-data"
},
body: data
};
fetch("http://localhost:3900/api/uploadFiles/upload", config)
.then(checkStatusAndGetJSONResponse => {
console.log("checkStatusAndGetJSONResponse");
console.log(checkStatusAndGetJSONResponse);
})
.catch(err => {
console.log(err);
});
};
createFormData = (photo, body) => {
console.log("PHOTO");
console.log(photo);
const data = new FormData();
data.append("photo", {
name: photo.fileName,
type: photo.type,
uri:
Platform.OS === "android" ? photo.uri : photo.uri.replace("file://", "")
});
Object.keys(body).forEach(key => {
data.append(key, body[key]);
});
return data;
};
render() {
const { photo } = this.state;
return (
<View style={{ flex: 1, alignItems: "center", justifyContent: "center" }}>
{photo && (
<React.Fragment>
<Image
source={{ uri: photo.uri }}
style={{ width: 300, height: 300 }}
/>
<Button title="Upload" onPress={this.handleUploadPhoto} />
</React.Fragment>
)}
<Button title="Choose Photo" onPress={this.handleChoosePhoto} />
</View>
);
}
}
export default ImagePickerComponent;
下面是使用 Multer 处理将文件存储在 MongoDB 中的服务器 JS 文件。
const express = require("express");
const router = express();
const multer = require("multer");
const GridFsStorage = require("multer-gridfs-storage");
const path = require("path");
const crypto = require("crypto");
// Create storage engine
const storage = new GridFsStorage({
url: "mongodb://localhost/vidly",
file: (req, file) => {
console.log("In Storage: ");
console.log(file);
return new Promise((resolve, reject) => {
crypto.randomBytes(16, (err, buf) => {
if (err) {
return reject(err);
}
const filename = buf.toString("hex") + path.extname(file.originalname);
const fileInfo = {
filename: filename,
bucketName: "uploads"
};
console.log("fileInfo");
console.log(fileInfo);
resolve(fileInfo);
});
});
}
});
const upload = multer({ storage }).single("file");
// @route POST /upload
// @desc Uploads file to DB
//upload.single("file"),
// router.post("/upload", upload.single("file"), (req, res) => {
// console.log("In Upload Function");
// console.log(req);
// res.json({ file: req.file });
// // res.redirect("/");
// });
router.post("/upload", upload, (req, res) => {
console.log(req);
console.log("file", req.file);
console.log("body", req.body);
res.status(200).json({
message: "success!"
});
});
router.get("/me", (req, res) => {
res.json("Hello!");
});
module.exports = router;
此外,这是我正在使用的服务器 package.json 文件。
"dependencies": {
"@hapi/joi": "^15.0.3",
"body-parser": "^1.19.0",
"config": "^3.1.0",
"cors": "^2.8.5",
"express": "^4.17.1",
"express-async-errors": "^3.1.1",
"express-multipart-file-parser": "^0.1.2",
"gridfs-stream": "^1.1.1",
"mongoose": "^5.5.11",
"multer": "^1.4.1",
"multer-gridfs-storage": "^3.2.3",
"winston": "^3.2.1"
}
我没有得到任何异常,但文件没有存储到 mongoDB 中。看起来 Multer 没有从请求中提取文件。当我使用 POSTMAN 进行测试时,我的服务器代码正在运行,但它不适用于 React Native。
我从反应原生调试器中捕获了示例请求和响应。
此外,这是来自服务器的失败请求日志(来自 react Native)。
route:
Route {
path: '/single',
stack:
[ Layer {
handle: [Function: multerMiddleware],
name: 'multerMiddleware',
params: undefined,
path: undefined,
keys: [],
regexp: /^\/?$/i,
method: 'post' },
Layer {
handle: [Function],
name: '<anonymous>',
params: undefined,
path: undefined,
keys: [],
regexp: /^\/?$/i,
method: 'post' } ],
methods: { post: true } },
**body:** [Object: null prototype] { photo: '[object Object]' },
__onFinished: null }
**undefined**
如果我们观察请求正文,我们将得到一个对象。
这是通过 POSTMAN 捕获的服务器请求(它是一个成功的请求)。
body: [Object: null prototype] {},
route:
Route {
path: '/upload',
stack:
[ Layer {
handle: [Function: multerMiddleware],
name: 'multerMiddleware',
params: undefined,
path: undefined,
keys: [],
regexp: { /^\/?$/i fast_star: false, fast_slash: false },
method: 'post' },
Layer {
handle: [Function],
name: '<anonymous>',
params: undefined,
path: undefined,
keys: [],
regexp: { /^\/?$/i fast_star: false, fast_slash: false },
method: 'post' } ],
methods: { post: true } },
file:
{ fieldname: 'file',
originalname: 'testAlert.html',
encoding: '7bit',
mimetype: 'text/html',
id: 5d1e3084e3aa4de0b8320773,
filename: 'e7d2080ddbe2cbf2ac7167d79b8ff0f2.html',
metadata: null,
bucketName: 'uploads',
chunkSize: 261120,
size: 148961,
md5: '4e68af2f75a34d2d7371f21544fe9b58',
uploadDate: 2019-07-04T16:59:48.602Z,
contentType: 'text/html' },
__onFinished: null }
如果我们观察到两个请求文件对象都作为一个单独的部分通过 POSTMAN 出现,而不是 react native 的情况。谁能帮我解决这个问题。?为什么它不能与 React-Native 一起使用。?我卡在这里。请帮我解决这个问题。?
谢谢和问候, Amar.T