React.js,如何将multipart/form-data发送到服务器

Pet*_*ang 13 file-upload multipartform-data reactjs

我们想将一个图像文件作为multipart/form发送到后端,我们尝试使用html表单来获取文件并将文件作为formData发送,这里是代码

export default class Task extends React.Component {

  uploadAction() {
    var data = new FormData();
    var imagedata = document.querySelector('input[type="file"]').files[0];
    data.append("data", imagedata);

    fetch("http://localhost:8910/taskCreationController/createStoryTask", {
      mode: 'no-cors',
      method: "POST",
      headers: {
        "Content-Type": "multipart/form-data"
        "Accept": "application/json",
        "type": "formData"
      },
      body: data
    }).then(function (res) {
      if (res.ok) {
        alert("Perfect! ");
      } else if (res.status == 401) {
        alert("Oops! ");
      }
    }, function (e) {
      alert("Error submitting form!");
    });
  }

  render() {
    return (
        <form encType="multipart/form-data" action="">
          <input type="file" name="fileName" defaultValue="fileName"></input>
          <input type="button" value="upload" onClick={this.uploadAction.bind(this)}></input>
        </form>
    )
  }
}
Run Code Online (Sandbox Code Playgroud)

后端的错误是"嵌套异常是org.springframework.web.multipart.MultipartException:无法解析多部分servlet请求;嵌套异常是java.io.IOException:org.apache.tomcat.util.http.fileupload.FileUploadException:请求被拒绝,因为没有找到多部分边界".

阅读本文后,我们尝试在fetch中设置边框到标题:

fetch("http://localhost:8910/taskCreationController/createStoryTask", {
      mode: 'no-cors',
      method: "POST",
      headers: {
        "Content-Type": "multipart/form-data; boundary=AaB03x" +
        "--AaB03x" +
        "Content-Disposition: file" +
        "Content-Type: png" +
        "Content-Transfer-Encoding: binary" +
        "...data... " +
        "--AaB03x--",
        "Accept": "application/json",
        "type": "formData"
      },
      body: data
    }).then(function (res) {
      if (res.ok) {
        alert("Perfect! ");
      } else if (res.status == 401) {
        alert("Oops! ");
      }
    }, function (e) {
      alert("Error submitting form!");
    });
  }
Run Code Online (Sandbox Code Playgroud)

这次,后端的错误是:servlet [dispatcherServlet]的Servlet.service()在上下文中,路径[]引发异常[请求处理失败; 具有根本原因的嵌套异常是java.lang.NullPointerException]

我们添加多部分边界吗?应该在哪里?也许我们一开始就错了,因为我们没有得到multipart/form-data.我们怎样才能正确地得到它?

Fat*_*ora 13

这是我通过axios预览图像上传的解决方案。

import React, { Component } from 'react';
import axios from "axios";
Run Code Online (Sandbox Code Playgroud)

反应组件类:

class FileUpload extends Component {

    // API Endpoints
    custom_file_upload_url = `YOUR_API_ENDPOINT_SHOULD_GOES_HERE`;


    constructor(props) {
        super(props);
        this.state = {
            image_file: null,
            image_preview: '',
        }
    }

    // Image Preview Handler
    handleImagePreview = (e) => {
        let image_as_base64 = URL.createObjectURL(e.target.files[0])
        let image_as_files = e.target.files[0];

        this.setState({
            image_preview: image_as_base64,
            image_file: image_as_files,
        })
    }

    // Image/File Submit Handler
    handleSubmitFile = () => {

        if (this.state.image_file !== null){

            let formData = new FormData();
            formData.append('customFile', this.state.image_file);
            // the image field name should be similar to your api endpoint field name
            // in my case here the field name is customFile

            axios.post(
                this.custom_file_upload_url,
                formData,
                {
                    headers: {
                        "Authorization": "YOUR_API_AUTHORIZATION_KEY_SHOULD_GOES_HERE_IF_HAVE",
                        "Content-type": "multipart/form-data",
                    },                    
                }
            )
            .then(res => {
                console.log(`Success` + res.data);
            })
            .catch(err => {
                console.log(err);
            })
        }
    }


    // render from here
    render() { 
        return (
            <div>
                {/* image preview */}
                <img src={this.state.image_preview} alt="image preview"/>

                {/* image input field */}
                <input
                    type="file"
                    onChange={this.handleImagePreview}
                />
                <label>Upload file</label>
                <input type="submit" onClick={this.handleSubmitFile} value="Submit"/>
            </div>
        );
    }
}

export default FileUpload;
Run Code Online (Sandbox Code Playgroud)


Pet*_*ang 9

我们只是尝试删除我们的标题,它的工作原理!

fetch("http://localhost:8910/taskCreationController/createStoryTask", {
      mode: 'no-cors',
      method: "POST",
      body: data
    }).then(function (res) {
      if (res.ok) {
        alert("Perfect! ");
      } else if (res.status == 401) {
        alert("Oops! ");
      }
    }, function (e) {
      alert("Error submitting form!");
    });
Run Code Online (Sandbox Code Playgroud)

  • 后台如何处理这些数据?假设 php @PeterJiang (2认同)

小智 8

该文件也可在事件中使用:

e.target.files[0]
Run Code Online (Sandbox Code Playgroud)

(消除了对 的需要document.querySelector('input[type="file"]').files[0];

uploadAction(e) {
  const data = new FormData();
  const imagedata = e.target.files[0];
  data.append('inputname', imagedata);
  ...
Run Code Online (Sandbox Code Playgroud)

注: 使用console.log(data.get('inputname'))调试,console.log(data)将不显示的附加数据。


Sub*_*a M 7

https://muffinman.io/uploading-files-using-fetch-multipart-form-data/最适合我。它使用 formData。

import React from "react";
import logo from "./logo.svg";
import "./App.css";
import "bootstrap/dist/css/bootstrap.min.css";
import Button from "react-bootstrap/Button";

const ReactDOM = require("react-dom");


export default class App extends React.Component {
  constructor(props) {
    super(props);
    this.test = this.test.bind(this);
    this.state = {
      fileUploadOngoing: false
    };
  }

  test() {
    console.log(
      "Test this.state.fileUploadOngoing=" + this.state.fileUploadOngoing
    );
    this.setState({
      fileUploadOngoing: true
    });

    const fileInput = document.querySelector("#fileInput");
    const formData = new FormData();

    formData.append("file", fileInput.files[0]);
    formData.append("test", "StringValueTest");

    const options = {
      method: "POST",
      body: formData
      // If you add this, upload won't work
      // headers: {
      //   'Content-Type': 'multipart/form-data',
      // }
    };
    fetch("http://localhost:5000/ui/upload/file", options);
  }
  render() {
    console.log("this.state.fileUploadOngoing=" + this.state.fileUploadOngoing);
    return (
      <div>
        <input id="fileInput" type="file" name="file" />
        <Button onClick={this.test} variant="primary">
          Primary
        </Button>

        {this.state.fileUploadOngoing && (
          <div>
            <h1> File upload ongoing abc 123</h1>
            {console.log(
              "Why is it printing this.state.fileUploadOngoing=" +
                this.state.fileUploadOngoing
            )}
          </div>
        )}

      </div>
    );
  }
}
Run Code Online (Sandbox Code Playgroud)