Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/xpath/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Javascript FormData不';部署Redux和AXIOS时,不要在React项目中上载文件_Javascript_Node.js_File_Multipartform Data_Form Data - Fatal编程技术网

Javascript FormData不';部署Redux和AXIOS时,不要在React项目中上载文件

Javascript FormData不';部署Redux和AXIOS时,不要在React项目中上载文件,javascript,node.js,file,multipartform-data,form-data,Javascript,Node.js,File,Multipartform Data,Form Data,我有一个使用Redux和AXIOS的完整MERN堆栈项目。我使用FormData将图像上传到我的节点服务器,该服务器有multer,它在我的本地主机上运行得非常好,即使我的chrome上的控制台说空?(FormData{})。部署时,我的FormData为空。因此,我在没有文件的情况下测试了我的FormData(只是表单的输入值),它将传递到服务器,并将其保存在req.body上 我试图添加配置我的formData,但没有成功 我做错了什么 例如 config:{headers:{'Conten

我有一个使用Redux和AXIOS的完整MERN堆栈项目。我使用FormData将图像上传到我的节点服务器,该服务器有multer,它在我的本地主机上运行得非常好,即使我的chrome上的控制台说空?(FormData{})。部署时,我的FormData为空。因此,我在没有文件的情况下测试了我的FormData(只是表单的输入值),它将传递到服务器,并将其保存在req.body上

我试图添加配置我的formData,但没有成功

我做错了什么

例如

config:{headers:{'Content Type':'multipart/form data'}
etc

以下是我的一些代码:

反应形式JS

import React, { Component, Fragment } from "react";
import PropTypes from "prop-types";
import { connect } from "react-redux";
import TextAreaFieldGroup from "../common/TextAreaFieldGroup";
import InputGroup from "../common/InputGroup";
import { addEventful, upload } from "../../actions/eventfulActions";

import Dropzone from "react-dropzone";

const imageMaxSize = 10000000
; //bytes
const acceptedFileTypes =
  "image/x-png, image/png, image/jpg, image/jpeg, image/gif";
const acceptedFileTypesArray = acceptedFileTypes.split(",").map(item => {
  return item.trim();
});

class EventfulForm extends Component {
  constructor(props) {
    super(props);
    this.state = {
      eventtitle: "",
      description: "",
      // comments:'',
      files: [],
      errors: {}
    };

    this.onChange = this.onChange.bind(this);
    this.onSubmit = this.onSubmit.bind(this);
  }


  componentWillReceiveProps(newProps) {
    if (newProps.errors) {
      this.setState({ errors: newProps.errors });
    }
  }

  verifyFile(files){
    if(files && files.length > 0){
      const currentFile = files[0]
      const currentFileType = currentFile.type
      const currentFileSize = currentFile.size
      if(currentFileSize > imageMaxSize){
        alert("TOO MANY FILES")
        return false
      }
      if (!acceptedFileTypesArray.includes(currentFileType)) {
        alert("IMAGES ONLY")
        return false
      }
      return true

    }
  }
  onSubmit(e) {
    e.preventDefault();
    const { user } = this.props.auth;



    const formdata = new FormData();
    this.state.files.forEach((file, i) => {
      const newFile = { uri: file, type: "image/jpg" };
      formdata.append("file", file, file.name);
    });

    // const newEventful = {
    //   eventtitle: this.state.eventtitle,
    //   description: this.state.description,
    //   pictures: this.state.pictures,
    //   name: user.name
    // };

    formdata.append("eventtitle", this.state.eventtitle);
    formdata.append("description", this.state.description);
    formdata.append("name", user.name);

    this.props.addEventful(formdata);
    this.setState({ eventtitle: "" });
    this.setState({ description: "" });
    this.setState({ files: [] });
  }
  onChange(e) {
    this.setState({ [e.target.name]: e.target.value });
  }

  onDrop = (files, rejectedFiles) => {
    if(rejectedFiles && rejectedFiles.length > 0){
      console.log(rejectedFiles)
      this.verifyFile(rejectedFiles)
    }
    if (files && files.length > 0) {
      const isVerified = this.verifyFile(files)
      if(isVerified){
        console.log(files[0].name);
        const formdata = new FormData();
        files.map(file => {
          formdata.append("file", file, file.name);
        });
        // formdata.append("file", files[0], files[0].name);

        console.log(formdata);
        // this.props.upload(formdata);
        this.setState({
          files: files
        });
      }
    }
  };

  render() {
    const previewStyle = {
      display: "inline",
      width: 100,
      height: 100
    };
    const { errors, files } = this.state;

    return (
      <div className="post-form mb-3">
        <div className="card card-info">
          <div className="card-header bg-info text-white">Create an Event</div>
          <div className="card-body">
            <form onSubmit={this.onSubmit}>
              <div className="form-group">
                <InputGroup
                  placeholder="Create a event title"
                  name="eventtitle"
                  value={this.state.eventtitle}
                  onChange={this.onChange}
                  error={errors.eventtitle}
                />
                {files.length > 0 && (
                  <Fragment>
                    <h3>Files name</h3>
                    {files.map((picture, i) => (
                      <p key={i}>{picture.name}</p>
                    ))}
                  </Fragment>
                )}
                <Dropzone
                  onDrop={this.onDrop.bind(this)}
                  accept={acceptedFileTypes}
                  maxSize={imageMaxSize}
                >
                  <div>
                    drop images here, or click to select images to upload.
                  </div>
                </Dropzone>


                <TextAreaFieldGroup
                  placeholder="Description"
                  name="description"
                  value={this.state.description}
                  onChange={this.onChange}
                  error={errors.description}
                />
              </div>
              <button type="submit" className="btn btn-dark">
                Submit
              </button>
            </form>
          </div>
        </div>
      </div>
    );
  }
}

EventfulForm.propTypes = {
  addEventful: PropTypes.func.isRequired,
  auth: PropTypes.object.isRequired,
  errors: PropTypes.object.isRequired
};
const mapStateToProps = state => ({
  auth: state.auth,
  errors: state.errors,
  eventful: state.files
});

export default connect(
  mapStateToProps,
  { addEventful, upload }
)(EventfulForm);
node.js

import axios from "axios";

import {
  ADD_EVENTFUL,
  GET_ERRORS,
  ADD_LIKE,
  REMOVE_LIKE,
  GET_EVENTFUL,
  GET_EVENTFULS,
  DELETE_EVENTFUL,
  CLEAR_ERRORS,
  EVENTFUL_LOADING,
  UPLOAD_FILES
} from "./types";

const config = {
  onUploadProgress: progressEvent =>
    console.log(
      "Upload Progress" +
        Math.round((progressEvent.loaded / progressEvent.total) * 100) +
        "%"
    )
};
// Add eventful
export const addEventful = eventfulData => dispatch => {
  dispatch(clearErrors());
  // .post("/api/eventfuls", eventfulData, config)

  axios({
    method: 'post',
    url: '/api/eventfuls',
    data: eventfulData,
    config: { headers: { 'Content-Type': 'multipart/form-data' } }

  }).then(res =>
      dispatch({
        type: ADD_EVENTFUL,
        payload: res.data
      })
    )
    .catch(err =>
      dispatch({
        type: GET_ERRORS,
        payload: err.response.data
      })
    );
};
const express = require("express");
const router = express.Router();
const mongoose = require("mongoose");
const passport = require("passport");
const bodyParser = require("body-parser");

// Eventful model
const Eventful = require("../../models/Eventful");
const User = require("../../models/User");

// Validation
const validateEventfulInput = require("../../validation/eventful");
const validateCommentInput = require("../../validation/comment");

var multer = require("multer");

var fs = require("fs");
var path = require("path");

var btoa = require("btoa");

router.use(
  bodyParser.urlencoded({
    extended: false
  })
);
router.use(bodyParser.json());

var storage = multer.diskStorage({
  destination: function(req, file, cb) {
    cb(null, __dirname + "../../../uploads"); //you tell where to upload the files,
  },
  filename: function(req, file, cb) {
    cb(null, file.fieldname + "-" + Date.now());
  }
});

var upload = multer({
  storage: storage
}).array("file");

router.use((request, response, next) => {
  response.header("Access-Control-Allow-Origin", "*");
  response.header(
    "Access-Control-Allow-Methods: GET, POST, PATCH, PUT, DELETE, OPTIONS"
  );
  response.header("Access-Control-Allow-Headers", "Content-Type");
  next();
});

// @route   POST api/eventfuls
// @desc    Create eventful
// @access  Private
router.post(
  "/",
  passport.authenticate("jwt", { session: false }),
  (req, res) => {
    upload(req, res, err => {
      console.log("req.body!!!!!", req.body);
      const { errors, isValid } = validateEventfulInput(req.body);

      // Check Validation
      if (!isValid) {
        console.log(errors);
        // If any errors, send 400 with errors object
        return res.status(400).json(errors);
      }

      console.log("req.files!!!!!", req.files);
      if (err) {
        console.log(err);
        res.status(404).json({
          uploadFailed: "Upload failed"
        });
      } else {
        let newArr = [];

        for (let file of req.files) {
          let fileReadSync = fs.readFileSync(file.path);
          let item = {};
          item.image = {};
          item.image.data = fileReadSync;
          item.image.contentType = "img/png";
          newArr.push(item);

          fs.unlink(file.path, function(err) {
            if (err) {
              console.log("error deleting image", file.path);
            } else {
              console.log("deleted image", file.path);
            }
          });
        }
        for (var i = 0; i < newArr.length; i++) {
          var base64 = btoa(
            new Uint8Array(newArr[i].image.data).reduce(
              (data, byte) => data + String.fromCharCode(byte),
              ""
            )
          );
          newArr[i].image.data = base64;
        }

        console.log("33333333333333333333", newArr);

        const newEventful = new Eventful({
          title: req.body.eventtitle,
          description: req.body.description,
          pictures: newArr,
          user: req.user.id,
          name: req.user.name
        });

        newEventful.save().then(eventful => res.json(eventful));
      }
      console.log("skipped....................");
    }
  );
  }
);
多部分/表单数据内容类型必须指定
边界
参数,这是您事先无法知道的


不要重写将由XHR/fetch自动设置的内容类型。

我发现您的代码中有两个问题

第一个来自npm页面,共页

这不处理多部分实体,因为它们复杂且 典型的大型自然环境。对于多部分实体,您可能感兴趣 以下模块:

  • 接线员和接线员
  • 多方和连接多方
  • 可怕的
  • 穆特
  • 因此
    body解析器
    不会填充
    req.body
    ,但由于您已经在使用
    multer
    ,下面是一个如何使用
    多部分/表单数据
    填充
    req.body
    的示例

    app.post('/', upload.none(), function (req, res, next) {
      // req.body contains the text fields
    })
    
    但是,由于您需要文件,而上述内容无法使用,因此可以使用
    upload.any()

    Second您的中间件注入顺序错误

    改变这个

    var upload = multer({
      storage: storage
    }).array("file");
    

    而不是

    router.post(
      "/",
      passport.authenticate("jwt", { session: false }),
      (req, res) => {
        upload(req, res, err => {
    
         //code
    
        }
      );
      }
    );
    

    编辑1

    添加到app.js或index.js或应用程序的起点

    global.rootPath = __dirname;
    
    global.rootPath
    现在将拥有应用程序的完整路径。ex
    /usr/user/Desktop/myapp
    使用
    path,join(global.rootPath,“uploads”)
    将为您提供
    /usr/user/Desktop/myapp/uploads
    。 使用
    path.join
    的好处是它可以处理不同的操作系统路径系统,如Windows和*nix

    始终使用
    path.join
    创建所有路径

    var storage = multer.diskStorage({
      destination: function(req, file, cb) {
        cb(null, path.join(global.rootPath, "uploads")); //you tell where to upload the files,
      },
      filename: function(req, file, cb) {
        cb(null, file.fieldname + "-" + Date.now());
      }
    });
    

    我已经在我自己的React代码中成功地使用了FormData()来上传文件,但由于某些我无法解释的原因,文件需要最后追加。我想知道这是否与之前提到边界参数要求的回复有关,并且在实际上传之前无法知道它

    尝试先添加数据,然后再添加文件。我还会尝试将单个文件作为测试用例。再一次,最后一次

    首先附加以下内容:

    formdata.append("eventtitle", this.state.eventtitle);
    formdata.append("description", this.state.description);
    formdata.append("name", user.name);
    
    那么就称之为:

    this.state.files.forEach((file, i) => {
      const newFile = { uri: file, type: "image/jpg" };
      formdata.append("file", file, file.name);
    });
    
    希望能有帮助。作为记录,我也使用multer,但在服务器端使用multer时遇到了同样的问题。在文件之前添加数据是我需要的修复方法

    问候,


    DB

    使用multer时,图像存储在请求的file属性中,所以是req.file,但您有req.files。我不确定这是否是您唯一的问题,因为我看到其他人对stackOverflow发表了评论,但我认为这也是一个问题。做一个console.log(req.file)并确保我是正确的,但我的代码中也使用了multer,我的工作正常。

    我试过使用它,也试过不使用它。是一样的。你是说我需要设定边界?非常感谢。这是一种工作,现在我有新的错误在我的pm2日志,当我试图上传图片<代码>0 | server | 2019-01-14 02:56-07:00:错误:eNote:没有这样的文件或目录,打开“/var/www/LCTW/uploads/file-1547459776817”它是如何查找该文件的?它不是应该查找base64吗?在POST 500错误中,它是否与我的
    var storage=multer.diskStorage({目的地:函数(req,file,cb){cb(null,uu dirname+“../../../../uploads”);//告诉在哪里上载文件,},文件名:函数(req,file,cb){cb cb(null,file.fieldname+“-”+Date.now();});
    ?@I.Y您可以
    fs.readFileSync(file.path)
    因此,假设文件不在那里,那么您应该得到
    enoint
    错误。我建议您始终使用创建路径!!。另外,我建议您在index.js中执行类似于
    global.rootPath=\uu dirname
    的操作,并避免使用
    。/../..//code>。理想情况下,它应该看起来像
    path,join(\uu dirname,global.rootPath,“uploads”)
    像myserver.js中这样<代码>app.use(path.join(uu dirname,global.rootPath,“uploads”)我试过了,我的网关坏了
    global.rootPath = __dirname;
    
    var storage = multer.diskStorage({
      destination: function(req, file, cb) {
        cb(null, path.join(global.rootPath, "uploads")); //you tell where to upload the files,
      },
      filename: function(req, file, cb) {
        cb(null, file.fieldname + "-" + Date.now());
      }
    });
    
    formdata.append("eventtitle", this.state.eventtitle);
    formdata.append("description", this.state.description);
    formdata.append("name", user.name);
    
    this.state.files.forEach((file, i) => {
      const newFile = { uri: file, type: "image/jpg" };
      formdata.append("file", file, file.name);
    });