Cómo publicar un archivo desde un formulario con Axios

128

Usando HTML sin procesar cuando publico un archivo en un servidor de matraces usando lo siguiente, puedo acceder a archivos desde la solicitud de matraz global:

<form id="uploadForm" action='upload_file' role="form" method="post" enctype=multipart/form-data>
    <input type="file" id="file" name="file">
    <input type=submit value=Upload>
</form>

En frasco:

def post(self):
    if 'file' in request.files:
        ....

Cuando intento hacer lo mismo con Axios, la solicitud del matraz global está vacía:

<form id="uploadForm" enctype="multipart/form-data" v-on:change="uploadFile">
<input type="file" id="file" name="file">
</form>

uploadFile: function (event) {
    const file = event.target.files[0]
    axios.post('upload_file', file, {
        headers: {
          'Content-Type': 'multipart/form-data'
        }
    })
}

Si uso la misma función uploadFile anterior pero elimino los encabezados json del método axios.post, obtengo en la clave de formulario de mi objeto de solicitud de matraz una lista csv de valores de cadena (el archivo es un .csv).

¿Cómo puedo enviar un objeto de archivo a través de axios?

Don Smythe
fuente
@Niklesh sí error tipográfico al cortar y pegar, lo arreglé arriba, incluye comillas dobles en el código.
Don Smythe
¿Intentaste v-on:change="uploadFile"con en inputlugar de formetiqueta?
Niklesh Raut
@Niklesh obtengo el mismo resultado: datos enviados como una cadena y recogidos por request.form no request.files en matraz.
Don Smythe

Respuestas:

268

Agregue el archivo a un formDataobjeto y establezca el Content-Typeencabezado en multipart/form-data.

var formData = new FormData();
var imagefile = document.querySelector('#file');
formData.append("image", imagefile.files[0]);
axios.post('upload_file', formData, {
    headers: {
      'Content-Type': 'multipart/form-data'
    }
})
Niklesh Raut
fuente
1
Después de publicar los archivos. ¿Necesitamos acceder a ellos desde una solicitud HTTP o necesitamos acceder a ellos desde los parámetros del lado del servidor?
Parth Patel
@ParthPatel: Estoy usando $_FILESpara obtener archivos en el lado del servidor ya que estoy usando PHP
Niklesh Raut
7
Gracias por esta publicación, pero todavía no veo por qué lo necesitamos FormData. Según el documento de axios, ambos Filey FormDatase tratan solo como navegador , por lo que ambas formas se pueden ver por igual ( github.com/axios/axios#request-config )
Hiroki
Increíble ! Estaba enviando 'datos: {data: formData}' que generaba el error 412. Funcionó condata:formData
Aseem
3
ATENCIÓN: el fragmento funciona como está cuando se ejecuta en el contexto de un navegador. Para ejecutarse en node.js, es necesario pasar los encabezados calculados por formData.getHeaders()Este es un problema conocido con axios; ver por ejemplohttps://github.com/axios/axios/issues/789
mjv
13

Aplicación de muestra usando Vue. Requiere un servidor backend que se ejecute en localhost para procesar la solicitud:

var app = new Vue({
  el: "#app",
  data: {
    file: ''
  },
  methods: {
    submitFile() {
      let formData = new FormData();
      formData.append('file', this.file);
      console.log('>> formData >> ', formData);

      // You should have a server side REST API 
      axios.post('http://localhost:8080/restapi/fileupload',
          formData, {
            headers: {
              'Content-Type': 'multipart/form-data'
            }
          }
        ).then(function () {
          console.log('SUCCESS!!');
        })
        .catch(function () {
          console.log('FAILURE!!');
        });
    },
    handleFileUpload() {
      this.file = this.$refs.file.files[0];
      console.log('>>>> 1st element in files array >>>> ', this.file);
    }
  }
});

https://codepen.io/pmarimuthu/pen/MqqaOE

maris
fuente
¿Puedo pedirle que eche un vistazo a una pregunta relacionada con axios aquí: stackoverflow.com/questions/59470085/… ?
Istiaque Ahmed
5

Esto funciona para mí, espero que ayude a alguien.

var frm = $('#frm');
let formData = new FormData(frm[0]);
axios.post('your-url', formData)
    .then(res => {
        console.log({res});
    }).catch(err => {
        console.error({err});
    });
OCornejo
fuente
usando Nuxt, esto finalmente funcionó para mí. eliminar headers: { 'Content-Type': 'multipart/form-data' }era la única forma en que realmente enviaría la publicación después de obtener una respuesta del servidor de las opciones. Probablemente estoy haciendo algo mal, pero está funcionando y lo dejo solo jajaja
Jeff Bluemel
¡Esto es brillante! Nunca hubiera pensado que podrías enviar el formulario completo. ¡Gracias!
Dara Java