Queremos enviar un archivo de imagen como multipart/form al backend, tratamos de usar el formulario html para obtener el archivo y enviar el archivo como formData, aquí están los códigos
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> ) } }El error en el backend es "la excepción anidada es org.springframework.web.multipart.MultipartException: no se pudo analizar la solicitud de servlet de varias partes; la excepción anidada es java.io.IOException: org.apache.tomcat.util.http.fileupload.FileUploadException: el la solicitud fue rechazada porque no se encontró ningún límite multiparte".
Después de leer esto , intentamos establecer un límite para los encabezados en la búsqueda:
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!"); }); }Esta vez, el error en el backend es: Servlet.service() para el servlet [dispatcherServlet] en contexto con la ruta [] arrojó una excepción [Falló el procesamiento de la solicitud; la excepción anidada es java.lang.NullPointerException] con causa raíz
¿Añadimos el límite multiparte, verdad? ¿Dónde debería estar? Tal vez nos equivoquemos al principio porque no obtenemos los datos de formulario/multiparte. ¿Cómo podemos conseguirlo correctamente?
¡Simplemente intentamos eliminar nuestros encabezados y funciona!
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!"); });Aquí está mi solución para cargar imágenes con vista previa a través de axios .
import React, { Component } from 'react'; import axios from "axios";Clase de componente de reacción:
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;El archivo también está disponible en el evento:
e.target.files[0] (elimina la necesidad de document.querySelector('input[type="file"]').files[0]; )
uploadAction(e) { const data = new FormData(); const imagedata = e.target.files[0]; data.append('inputname', imagedata); ... Nota: Use console.log(data.get('inputname')) para la depuración, console.log(data) no mostrará los datos adjuntos.