文件上传React Native,Node JS,MongoDB,Multer,Grid FS

时间:2019-07-04 17:04:04

标签: node.js mongodb react-native multer multer-gridfs-storage

我对React Native开发非常陌生。我从过去的两天开始努力用React Native将文件/图像上传到MongoDB(Grid FS)。我从字面上看过所有相关的论坛,但是没有运气。我读了几个论坛,他们举了一个例子,但是我没有成功。这是我编写的示例代码。

客户端JS(React Native):

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;

下面是服务器JS文件,该文件用于通过Multer将文件存储在MongoDB中。

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。

我捕获了来自本地响应调试器的Sample请求和响应。

enter image description here

此外,这是来自服务器的请求失败日志(来自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 }

如果我们观察到两个请求的 file 对象作为单独的部分通过POSTMAN发出,但使用react native的情况不是这样。有人可以帮我吗?为什么它不能与React-Native一起使用?我留在这里。请帮我。?

感谢与问候, Amar.T

0 个答案:

没有答案