Загрузка файла React Native, Node JS, MongoDB, Multer, Grid FS - PullRequest
0 голосов
/ 04 июля 2019

Я очень новичок в разработке React Native. В последние 2 дня я пытаюсь взломать файл / изображение с помощью 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-файл сервера, с помощью которого можно сохранить файл в MongoDB с помощью Multer.

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. Похоже, Малтер не берет файл из запроса. Код моего сервера работает, когда я тестирую с POSTMAN , но не работает с React Native.

Я получил образец запроса и ответа от собственного отладчика реагирования.

enter image description here

Кроме того, вот журналы с сервера для сбоя запроса (От реагировать на собственный).

 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.? Я застрял здесь. Пожалуйста, помогите мне в этом .?

Спасибо и С уважением, Amar.T

...