Axios: No se puede obtener un .post con 'Content-Type': 'multipart/form-data' para trabajar

Creado en 11 may. 2016  ·  99Comentarios  ·  Fuente: axios/axios

Pasé algunas horas hoy tratando de hacer que una solicitud de publicación funcione con algunos parámetros y un archivo que necesito cargar.

Pude hacerlo funcionar con javascript puro y XMLHttpRequest pero no funciona con Axios. ¿Qué estoy haciendo mal?

Aquí está el código que funciona usando XMLHttpRequest:

let data = new FormData();

data.append('action', 'ADD');
data.append('param', 0);
data.append('secondParam', 0);
data.append('file', new Blob([payload], { type: 'text/csv' }));

// this works
let request = new XMLHttpRequest();
request.open('POST', url);
request.send(data);

¿Cuál sería la versión 'Axios' de eso?

Aquí está uno de mis intentos (el simple):

// this won't work
const config = { headers: { 'Content-Type': 'multipart/form-data' } };
    axios.post(url, data, config)
    .then(response => console.log(response))
    .catch(errors => console.log(errors));

¡Gracias! ¡Y gracias por su gran trabajo con Axios!

Comentario más útil

@rafaelbiten Acabo de intentar reproducir el problema pero fue en vano. Use el siguiente código:

const data = new FormData();

data.append('action', 'ADD');
data.append('param', 0);
data.append('secondParam', 0);
data.append('file', new Blob(['test payload'], { type: 'text/csv' }));

axios.post('http://httpbin.org/post', data);

Los datos se enviaron con éxito al servidor:

screen shot 2016-05-12 at 9 12 19 pm

Todos 99 comentarios

El código me parece bien. (No necesita establecer el tipo de contenido, pero no es importante). ¿Qué sucede cuando intenta enviar una solicitud a través de axios?

Noté que configurar Content-Type o no no cambia nada en este caso. Cuando trato de enviar la solicitud con Axios, parece que los datos van como una cadena vacía, por lo que el backend responderá con un error relacionado con los parámetros que faltan.

Estaba usando 0.9.1 pero el problema persiste en 0.11.0.

Avíseme si hay algo más que pueda hacer para ayudar a depurar esto, ¿de acuerdo?
Tks @nickuraltsev !

¿Podría echar un vistazo a cómo se ven sus solicitudes en el panel Red de Chrome Dev Tools y proporcionar una captura de pantalla si es posible?

@nickuraltsev mira si esto ayuda:

screen shot 2016-05-11 at 2 56 12 pm

Creo que los encabezados de solicitud están equivocados.

Entonces, ¿no hay carga útil de solicitud?

Bueno, deberíamos haberlo hecho, pero los datos van como una cadena vacía. No sé qué puede estar rompiéndolo (considerando el código que compartí en mi primera publicación).

Veo. Y no hay una sección de Carga útil de solicitud para sus solicitudes en Herramientas de desarrollo, ¿correcto?

Posible problema de encabezado relacionado. Cuando el tipo de contenido se establece en el objeto de configuración en la solicitud, se concatena, por ejemplo
axios.post(
'https://ejemplo.com/login',
{dirección de correo electrónico: correo electrónico, contraseña: hashPassword},
{encabezados: {'tipo de contenido': 'aplicación/json'}}
);

el tipo de contenido del encabezado aparece como aplicación/json, aplicación/json
el cuerpo no se analizará en este caso

@nickuraltsev cierto! Lo que ves en esa captura de pantalla es todo lo que tengo en las herramientas de desarrollo.
@rrapant puede tener razón, pero estoy casi seguro de que configurar 'Content-Type' o no, al menos en este caso, no cambió nada. Tendría que volver a consultar para estar seguro.

@rrapant El problema con los valores de tipo de contenido duplicado se solucionó en el n. ° 317. La solución se incluirá en la próxima versión. ¡Gracias!

@rafaelbiten Acabo de intentar reproducir el problema pero fue en vano. Use el siguiente código:

const data = new FormData();

data.append('action', 'ADD');
data.append('param', 0);
data.append('secondParam', 0);
data.append('file', new Blob(['test payload'], { type: 'text/csv' }));

axios.post('http://httpbin.org/post', data);

Los datos se enviaron con éxito al servidor:

screen shot 2016-05-12 at 9 12 19 pm

@rafaelbiten ¿Podría intentar enviar una solicitud con FromData a http://httpbin.org/post como en mi fragmento de código?

Cerrando esto por ahora. Por favor, siéntase libre de reabrir si es necesario.

Hola @nickuraltsev , tengo el mismo problema.

      var fd = new FormData();
      fd.append('file', this.refs.multipartfiles.files[0]);

            const config = { headers: { 'Content-Type': 'multipart/form-data' } };
            axios.post('/dataAPI/sendFile', {
                "UploadCommand": fd
              }, config)
              .then(function (response) {
                console.log(response);
              })
              .catch(function (error) {
                console.log(error);
              });

Encuentre la captura de pantalla de la información de mi encabezado a continuación,

image

Tengo una pregunta, _¿Axios admite el envío de archivos de datos de varias partes al servidor de nodos?_

@Sreekhar No sé si funcionará, pero ¿podría agregar FormData como segundo argumento en lugar de envolverlo en otro objeto?
axios.post('/dataAPI/sendFile', fd, config)

Si necesita usar 'UploadCommand' como el nombre de la parte donde está el archivo, debe usar esto
fd.append('UploadCommand', this.refs.multipartfiles.files[0]);

@yungpanda Encontré una alternativa para hacer eso. Supongo que tendré que volver a crear la API ahora. De todos modos, intentaré comprobar si funciona, mantendré el hilo actualizado. Gracias por su respuesta.

@Sreekhar Establezca Content-Type en indefinido para permitir que el navegador lo cambie a multipart/form-data y agregue límites automáticamente

@nickuraltsev este es un ejemplo mínimo que no funciona en el nodo:

const data = new FormData();

data.append('action', 'ADD');
data.append('param', 0);
data.append('secondParam', 0);

axios.post('http://httpbin.org/post', data).then(req => {
  console.log('Req done: ', req)
}).catch(err => {
  console.error('Error: ', err)
})

Error: escribir después del final

@krzkaczor ¿Ha encontrado alguna solución para enviar datos de varias partes/formularios con axios?

@PierreCavalet no, usé request-promise en su lugar.

@krzkaczor gracias, obligado a cambiar también

@krzkaczor Intente agregar el tipo de contenido si aún no lo ha hecho

const config = { headers: { 'Content-Type': 'multipart/form-data' } };
let fd = new FormData();
fd.append('file',files[0])
return axios.post("http://localhost:5000/upload", fd, config)

@krzkaczor también estoy enfrentando el mismo problema con axios y multipart/form-data. ¿Puedes publicar la esencia del código que usaste con request-promise?

@dan-boa aquí tienes: https://gist.github.com/krzkaczor/bdbe09d4096b051a3c18387c4ca79a06 También muestra un truco sobre cómo enviar una cadena como archivo (ruta de configuración)

Si alguien se pregunta, aquí hay un ejemplo de cómo usar FormData con axios . Básicamente, debe transmitir los datos a un búfer y pasar los encabezados correctos.

const concat = require("concat-stream")
const fd = new FormData()

fd.append("hello", "world")
fd.append("file", fs.createReadStream(file))
fd.pipe(concat(data => {
  axios.post("/hello", data, {
    headers: fd.getHeaders()
  })
}))

Tuve el mismo problema (en el navegador, no en el nodo). Resultó que funciona si no configura el encabezado Content-Type en absoluto y deja que axios resuelva las cosas (también verifique si no configura ese encabezado como predeterminado en los interceptores axios también. Si necesita algo valores predeterminados para el resto de las llamadas a la API, puede crear una instancia de axios separada para las solicitudes de FormData())

Terminé yendo con la promesa de solicitud en el lado del nodo cuando intentaba cargar a otro servidor remoto.

Cambié a solicitud-promesa por la misma razón. ¡Me encanta axios de lo contrario!

@guncha Su ejemplo funcionó para mí en 0.15.3, hasta que intenté cargar un archivo binario, que terminó codificado como UTF8. Decirle a concat que use un búfer solucionó el problema.

const concat = require("concat-stream")
const fd = new FormData()

fd.append("hello", "world")
fd.append("file", fs.createReadStream(binaryFile))
fd.pipe(concat({encoding: 'buffer'}, data => {
  axios.post("/hello", data, {
    headers: fd.getHeaders()
  })
}))

Alternativamente, usaría una promesa:

const promise = new Promise((resolve) => {
  const fd = new FormData();
  fd.append("hello", "world");
  fd.append("file", fs.createReadStream(binaryFile));
  fd.pipe(concat({ encoding: 'buffer' }, data => resolve({ data, headers: fd.getHeaders() })));
});
promise.then(({ data, headers }) => axios.post('/hello', data, { headers }));
const callApi = (url, params) => {
  const formData  = new FormData()
  for(let name in params) {
    let param = params[name]
    if (typeof param === 'object') {
      param = JSON.stringify(params[name])
    }
    formData.append(name, param)
  }

  return axios.post(url, formData)
    .then(response => {
      console.log(response)
    })
}

@guncha trabajando para mí. gracias

mismo problema aquí

simplemente agregue el límite a Content-Type :

const request = require('axios');
const FormData = require('form-data');
const fs = require('fs');

let data = new FormData();
data.append('file1', fs.createReadStream('./image1.jpeg'), 'image1.jpeg');
data.append('file2', fs.createReadStream('./image2.jpeg'), 'image2.jpeg');

let options = {
    method: 'POST',
    url: 'http://localhost:3200/upload',
    headers: {
        'Content-Type': `multipart/form-data; boundary=${data._boundary}`
    },
    data
};

return request(options)
    .then(response => {
        console.log(response);
    });

Oye,
Obtuve este archivo en formato json. ¿Alguien puede ayudarme? ¿Cómo debo convertirlo en un archivo de varias partes?
La plataforma utilizada es java8.
"body": "------WebKitFormBoundaryQsJGeBuR8e9dQ4Pm\r\nContent-Disposition: form-data; name=\"file\"; filename=\"backup prolog.txt\"\r\nContent-Type: text/plain\r\n\r\n%All the Pre-Defined relations\r\nconnected(hira,rohit,father).\r\nconnected(rohit,rakesh,father).\r\nconnected(ram,hira,father).\r\nconnected(kavri,hira,mother).\r\nconnected(hira,kavri,son).\r\nconnected(arun,vinayak,father).\r\nconnected(vinayak,arun,son).\r\nconnected(arun,shashi,husband).\r\nconnected(shashi,arun,wife).\r\nconnected(vinayak,vardaan,brother).\r\nconnected(vardaan,vinayak,brother).\r\nconnected(shashi,vinayak,mother).\r\nconnected(vinayak,shashi,son).\r\n\r\n\r\n\r\nconnected2(X,Y,D) :- connected(X,Y,D).\r\n%connected2(X,Y,D) :- connected(Y,X,D).\r\n\r\nnext_node(Current, Next,R, Path) :-connected2(Current, Next, R),not(member(Next, Path)).\r\n\r\nfunc(how,is,X,related,to,Y):-depth_first(X,Y,[X],P),write(P).\r\n%Procedure to Start the depth_first\r\ndepth_first(Goal, Goal, _, [Goal]).\r\n\r\ndepth_first(Start, Goal, Visited, [Start,is,R,of|Path]) :-next_node(Start, Next_node,R, Visited),depth_first(Next_node, Goal,[Next_node,R|Visited], Path).\r\n\r\n\r\n\r\n\r\n\r\n\r\n------WebKitFormBoundaryQsJGeBuR8e9dQ4Pm--\r\n"
Gracias

El código funciona en el navegador pero no en el nodo.

const fdata = new FormData();
fdata.append('user', u);
fdata.append('hostnames', n.join(' '));
const host = localStorage.getItem('host');
const port = localStorage.getItem('port');
axios({
  url: `http://${host}:${port}/hosts/remove`,
  method: 'post',
  data: fdata
}).then(response => {
  if (response.status === 200) {
    console.log(response.data);
    console.log('Removed host successfully');
  }
  return null;
}).catch(er => console.log(er));

Hola @Sreekhar
Para mí, cambié la configuración a
const config = { headers: { 'Content-Type': 'application/json' } };
y funcionó bien

Vuelva a abrir hasta que haya alguna respuesta/flujo de trabajo consistente para esto. Parece que mucha gente todavía tiene problemas con esto.

+1 reabrir

Las publicaciones HTTP que incluyen datos de archivos binarios parecen funcionar bien en axios v0.16.2

// The following was tested successfully with axios v0.16.2

// Create a new form.  Note:  could also specify an existing form as
// the parameter to the FormData() constructor to copy all the elements
// from the existing form to the new one being created.

var tempFormData = new FormData();

var someNoteValue = 'Hello World';
var someAudioData = [];  // populate this with data from file, with MediaRecorder() etc.


// Add form fields

tempFormData.set('SomeNote', 'Hello World');
tempFormData.set('SomeRecording', someAudioData[0], 'SampleRecording.webm');


// Optional:  output list of form fields to the console for debugging

for (var pair of tempFormData.entries()) {
    console.log('Form field: ' + pair[0] + ', ' + pair[1]);
}


// Call Axios to post the form to myurl

axios({
    method: 'post',
    url: 'myurl',
    data: tempFormData,
    config: { headers: {'Content-Type': 'multipart/form-data' }}
})
    .then(function (response) {
        //handle success
        console.log(response);
    })
    .catch(function (response) {
        //handle error
        console.log(response);
    });

            }

Además, al usar búferes para representar archivos, esto funcionó para mí:

      const form = new FormData();
      const fileBuffer = new Buffer(
        'MM2 - noticeably shallower than the original - score: 101%', 'utf-8'
      );
      form.append('name', 'reviews.txt'); // additional form data field
      form.append('file', fileBuffer, 'original-file-name.bar');

      const res = await axios.post(`/uploadfile`, form, { headers: form.getHeaders() });

Importante tener en cuenta: cualquiera de las soluciones anteriores NO funciona si tiene parámetros de datos predeterminados establecidos en los valores predeterminados de la instancia de Axios. También puede verificar si especifica un encabezado de tipo de contenido predeterminado en su instancia de Axios (a través de axios.defaults.headers y axios.defaults.parameters).

Es posible que esto no sea el punto, pero el problema podría estar relacionado con el uso de body-parser en el lado del servidor. Estaba luchando con un problema similar y me encontré con esta publicación:

https://philna.sh/blog/2016/06/13/the-surprise-multipart-form-data/

TL;DR - body-parser no maneja datos de formularios/multipartes. En otras palabras, axios no es el problema y body-parser sí lo es. Esta podría ser la razón por la que funcionan las soluciones amortiguadoras mencionadas anteriormente.

Supongo que esta funcionalidad es por razones de seguridad, como se indica aquí:

http://andrewkelley.me/post/do-not-use-bodyparser-with-express-js.html

¡Espero que ayude a alguien!

Tengo el mismo problema. Uso Axios 0.16.2 y el envío por XMLHttpRequest funciona, pero no por Axios.

Tengo un objeto FormData básico:

const formData = new FormData();
formData.append('nombre', 'textoNombre');

Probé la sugerencia de @Janekk :

axios({
      method: 'post',
      url,
      withCredentials: true,
      data: { formData },
    })

entonces la sugerencia de @faalkhah :

const config = { headers: { 'Content-Type': 'application/json' } };
    axios({
      method: 'post',
      url,
      withCredentials: true,
      data: { formData },
      config,
    })

o la sugerencia de @askona :

const config = { headers: { 'Content-Type': undefined } };
    axios({
      method: 'post',
      url,
      withCredentials: true,
      data: { formData },
      config,
    })

El encabezado de la solicitud es application/json y formData está vacío.

No sé cómo probar la corrección de @demeter-macik, porque parece que solo funciona en el back-end https://stackoverflow.com/a/13454425/968379

Hola a todos,
Tengo el mismo problema
mi código en el cliente
`

    const url = '/file/uploadTest';
    const formData = new FormData();
    formData.append('file', file);
    formData.append('params1', value);
    formData.append('params2', value2)

    const config = {
        headers: {
            'Content-Type': 'multipart/form-data',
        }
    }
    axios.post(url,formData,config)`

en el servidor de velas, registro la consola req.body
Descubrí que, cuando llamo a la solicitud 10 veces, hay aproximadamente 3 4 veces que el servidor no recibe el cuerpo (el cuerpo está vacío).
Verifiqué en devtool de Chrome, la solicitud aún transmite el archivo y el cuerpo en la carga útil.
Todavía no he descubierto por qué, pero tengo una solución.

ese es el encabezado de la solicitud.

`código

    const url = '/file/uploadTest';
    const formData = new FormData();
    formData.append('file', file);
    formData.append('params1', value);
    formData.append('params2', value2)
    const config = {
        headers: {
            'Content-Type': 'multipart/form-data',
            'params1': value,
            'params2': value2
        }
    }
    axios.post(url,formData,config)`

Hola @Sreekhar ,
¿Resolviste el problema? No encontre la solucion alguien me puede ayudar por favor.
Además, gracias por adelantado.

Hola,

He estado tratando de publicar multiformdata (es una API de Eztext SMS)
usando axios con node.js.

Funciona bien para el siguiente código,
volver nueva Promesa(función(resolver, rechazar) {

        var request = require("request");
        var options = {
            method: 'POST',
            url: 'https://app.eztexting.com/sending/messages',
            qs: {format: 'json'},
            formData:
                {
                    User: '**',
                    Password: '**',
                    'PhoneNumbers[0]': '8572222***',
                    Message: 'Appointment Reminder',
                    MessageTypeID: '1'
                }
        };
        request(options, function (error, response, body) {
            if (error) {
                console.log(error);
                reject(error);
            }
            else {
                console.log(response);
                resolve(response);
            }

            // console.log(body);
        });

Pero no funciona con axios ya que no se envían SMS, pero obtengo el código de estado 200 para la siguiente solicitud:
var axios=requerir('axios');

         axios.post('https://app.eztexting.com/sending/messages', {
             qs: { format: 'json' },
             headers: {
                 'Content-Type': 'application/x-www-form-urlencoded'
             },
             formData:
                 { User: '****',
                     Password: '2sH****5',
                     'PhoneNumbers[0]':'85722******',
                     Message: 'Hello Yahska',
                     MessageTypeID: 1 }
         })
             .then(function (response) {
                 console.log(response);
             })
             .catch(function (error) {
                 console.log(error);
             });

¿Por qué la solicitud de publicación es un éxito con la biblioteca 'request' y no con Axios?

¿Ha intentado convertir los datos de JSON a FormData sin configurar ningún encabezado?
Los encabezados de los datos (es decir, además de los encabezados de autenticación) deben manejarse automáticamente

async function sendMessage(myJSONPayload){
  try{
    const data = convertJSON2FormData(myJSONPayload);

    const response = await axios.post('https://app.eztexting.com/sending/messages', {
  data
});
    console.log(response);
  } catch(ex){
    console error(err);
  }
}

sendMessage ({ User: '****',
                     Password: '2sH****5',
                     'PhoneNumbers[0]':'85722******',
                     Message: 'Hello Yahska',
                     MessageTypeID: 1 }
         });

Para la conversión de JSON a FormData, use algo como en esta respuesta

Recuerde que las claves anidadas son difíciles de manejar. Por ejemplo, cuando enviamos datos a nuestro backend, funciona si los aplanamos así:

{a: {b: 2}} --> formData.append("a.b",2)

el mismo problema aqui.

por supuesto, @michaelscheurer! Establecer los encabezados de una solicitud no es suficiente: debe enviar un FormData para que funcione. Es un objeto de navegador que se serializará con todos los límites adecuados para trabajar con la solicitud... ni axios ni vanilla js convertirán datos JSON a FormData por usted. Axios reconocerá que es un FormData y también configurará los encabezados por usted, por lo que realmente no necesita configurarlos.
Intenta seguir mis sugerencias de respuestas anteriores...

@Iamuertepeluda
Intenté hacer lo siguiente según su sugerencia, pero no tuve suerte... el mismo comportamiento cuando obtengo el estado 200 está bien, pero no se envía SMS con la siguiente solicitud.
var axios=requerir('axios');

    const FormData = require('form-data');

    const form = new FormData();

    //fo this jason I created a form
    // formData:
    // {
    //     User: '*****',
    //         Password
    // :
    //     '******',
    //         'PhoneNumbers[0]'
    // :
    //     '8****2763',
    //         Message
    // :
    //     'Appointment Reminder',
    //         MessageTypeID
    // :
    //     '1'
    // }

    form.append('User','****');
    form.append('Password','*****');
    form.append('PhoneNumbers[0]','*****');
    form.append('Message','Appointment Reminder');
    form.append('MessageTypeID','1');


         axios.post('https://app.eztexting.com/sending/messages', form,
    {
        qs: {format: 'json'},
        headers:
        {
                'content-type'
        :
            'multipart/form-data; boundary=----WebKitFormBoundary7MA4YWxkTrZu0gW'
        }
    }
)
             .then(function (response) {
                 console.log(response);
             })
             .catch(function (error) {
                 console.log(error);
             });

@ Ruchi2729 ¿estás usando node.js o un navegador?

en un navegador no necesita const FormData = require('form-data'); ya que FormData es nativo.

Además intente sin establecer encabezados y qs, o intente

axios.request({
 url: "https://app.eztexting.com/sending/messages"
 type: "post",
 data: form //the instance of FormData of your stub
});

como mencioné, debería establecer encabezados automáticamente en un navegador

@ Ruchi2729 Veo que estás usando un nodo, lo siento.
Recuerdo haber usado form-data con axios una vez, pero no recuerdo si realmente funcionó.

Pero, ¿estás seguro de que esta es la forma correcta de enviar SMS con eztexting? Según sus documentos, parece diferente, como si debería usar una clave api y su propio cliente de nodo ...

¿Podemos reabrir esto? Parece que mucha gente todavía se enfrenta a esto, incluyéndome a mí. Por ejemplo, esta solicitud no llega al servidor como se esperaba a través de axios, pero si envío el mismo archivo a Postman como multipart/form-data , todo funciona.

screen shot 2018-03-26 at 12 22 35 am

Editar: Mi problema estaba tratando de enviar un uri de datos codificado en base64 como datos de formulario. Si alguien más está luchando con el mismo problema, aquí hay un código de muestra para convertirlo:

async function importCsv(data: CsvImportData): Promise<void> {
    const formData = new FormData();
    const headers = {'Content-Type': 'multipart/form-data'};

    formData.append('csv', dataURItoFile(data.file, `upload_${Date.now()}.csv`));

    try {
      await axios.post('https://example.com/api/upload/csv', formData, {headers});
    } catch(e) {
      console.error(e);
    }
}

function dataURItoFile(dataURI: string, defaultFileName: string): File {
  let byteString: string;
  const [metadata, data] = dataURI.split(',');
  if (/base64$/.test(metadata)) {
    byteString = atob(data);
  } else {
    byteString = unescape(data);
  }

  const mimetype: string = metadata.split(':')[1].split(';')[0];
  const filename: string = (metadata.match(/name\=(.*);/) || [])[1] || defaultFileName;

  let dataView: Uint8Array = new Uint8Array(byteString.length);
  for (let i = 0; i < byteString.length; i++) {
    dataView[i] = byteString.charCodeAt(i);
  }
  return new File([dataView], filename);
}

Hola, me estoy refiriendo a este documento: - https://www.eztexting.com/developers/sms-api-documentation/rest#Sending
¿A qué documento se refiere para la clave API y todo?

@Ruchi2729
Lo siento, lo confundí con Nexmo, que es otro servicio de SMS y tiene su propio cliente para el nodo 😅

Pero de todos modos, de acuerdo con la documentación a la que se refirió , puede evitar FormData configurando format en json y dejar que axios envíe una carga útil JSON (puede dejar que adivine encabezados implícitamente por el formato de carga útil)

https://app.eztexting.com/sending/messages?format=json

Luché con esto mucho más tiempo que quiero admitir, así que espero que esto ayude a alguien. Estoy usando axios, express y express-fileupload. Puedo subir con éxito a Node con los parámetros que he agregado a FormData. Recojo los archivos con req.files y el resto de los datos del formulario con req.body['yourfilename']

Servidor (Exprés):

screen shot 2018-03-27 at 1 59 08 pm

router.post('/helper/amazon/upload', function(req, res) { if (!req.files) { return res.status(400).send('No files were uploaded.') } console.log(req.body.filename); return console.log(req.files);

Interfaz (axios)

screen shot 2018-03-27 at 1 58 45 pm

const formData = new FormData(); formData.append('file', this.validFile); formData.append('filename', 'trails/' + this.$route.params.id.split('-')[0] + '/camping/'); axios.post( /api/ayudante/amazon/upload , formData, { headers: { 'Content-Type': 'multipart/form-data' } });

Resultado:

screen shot 2018-03-27 at 2 02 11 pm

Tengo el mismo problema, puedo ver que envío con éxito los datos del archivo con mis herramientas de desarrollo, pero dentro de mi controlador mi $request->file('file') está vacío
mi componente

enviarFormulario() {
this.formData =new FormData();
this.formData.append('archivo',this.$refs.file.files[0]);
this.formData.append('análisis',this.analyticsForm.analysis);
this.formData.append('_method','PATCH');
axios.post('/análisis',
this.formData
,{headers: {'Content-Type': 'multipart/form-data'}}).then(response => this.isSubmittedRedirect(false,'/sources/'+this.source+'/description'+'') )
.catch((error) => consola.log(error))
},

Descubrí que hacer cualquier cosa con FormData era un problema, ya que a MVC no parece gustarle obtener nada de esa manera, porque tiene que especificar el Tipo de contenido como multipart/form-data y estaba lanzando una excepción cuando yo marque if (!Request.Content.IsMimeMultipartContent()) { throw new HttpResponseException(HttpStatusCode.UnsupportedMediaType); } , como dice el sitio de Microsoft: https://docs.microsoft.com/en-us/aspnet/web-api/overview/advanced/sending-html-form-data-part- 2

Era mejor simplemente poner mi archivo en una cadena base64:
https://stackoverflow.com/questions/37134433/convert-input-file-to-byte-array/49676679#49676679

Esta publicación podría ser más relevante sobre cómo hacerlo, ya que usé DropZone en este ejemplo:
https://stackoverflow.com/questions/32556664/getting-byte-array-through-input-type-file/49660172#49660172

Y voy más en detalle al respecto, aquí: https://stackoverflow.com/questions/47574218/converting-from-blob-to-binary-to-save-it-to-mongodb/49660839#49660839

Entonces podría crear un objeto JSON:

const myObj = {
   file = myBase64String,
   title = "myfileTitle.jpg"`
   type = "image/jpeg"`
}

En lugar de usar axios, solo usé XMLHttpRequest.

 const xhr = new XMLHttpRequest();

Y abra y configure el encabezado:

 xhr.open('POST', '/api/FileUpload/Post', true);
 xhr.setRequestHeader('Content-Type', 'application/json;charset=UTF-8' );
 xhr.withCredentials = true;

Configuré onreadystatechange para capturar la respuesta:

xhr.onreadystatechange = (response) =>
    if (xhr.readyState === 4 && xhr.status === 200) {
        console.log(response.target.responseText);
    }
}

y enviar:

 xhr.send(JSON.stringify(myObj));

Si usa axios, probablemente sería:

try {
    var axios = require('axios');
    const config = {
        headers: {
            'Content-Type': 'application/json;charset=UTF-8',
        }
    }
    await axios.post('https://example.com/api/upload/post', myObj, config)
        .then(function (response) {
             console.log(response);
         })
         .catch(function (error) {
             console.log(error);
         });
}
catch(e) { console.log(e); }

En el lado de MVC, necesita un modelo coincidente:

public class MyModel {
    public string file { get; set; }
    public string title { get; set; }
    public string type { get; set; }
}

y luego tenga eso como un parámetro en su llamada Post con una etiqueta [FromBody]:

[System.Web.Http.HttpPost]
public virtual JsonResult<string> Post([FromBody]MyModel myModelObject)
{
    string strBase64FileString = myModelObject.file;
    string strTitle = myModelObject.title;
    string strFileType = myModelObject.type;

    return Json(JsonConvert.SerializeObject(new { file = myModelObject.file, title = myModelObject.title, myModelObject.type }));
}

Deberías recuperar lo que enviaste. Tenga en cuenta que si implementa esto como una prueba, hágalo con un archivo muy pequeño, para que no tenga que esperar para siempre con el potencial de bloquear el navegador/la memoria de su sistema.

@navyjax2
Estaba haciendo lo que dijiste, estaba trabajando con un archivo pequeño pero necesito enviar un archivo grande (> 250Mo), y sí, estaba bloqueando mi navegador

Sí, para eso, es posible que desee dividir la matriz de archivos en fragmentos de un tamaño manejable y enviarlos en bloques, tener un método en el otro extremo (del lado del servidor) que pueda volver a combinarlos y darle un parámetro para que sabe qué fragmento es (primero, segundo, tercero, etc.) y cuántos fragmentos totales esperar antes de procesar el archivo en el lado del servidor. Pero creo que, sin importar lo que haga, con un archivo de ese tamaño, tendrá que esperar a que haga lo suyo. Tendrá que tener cuidado con la administración de la memoria si lo hace de la manera fragmentada, también, porque tendrá que asegurarse de borrar o reutilizar sus variables cada vez y no volver a crear instancias de nuevas versiones de las mismas variables cada vez. haces un bloque. Una de las pocas veces que una variable global es buena, o simplemente se establece en un campo de modelo en cada ejecución.

Estoy de acuerdo con @epferrari , considere reabrir este problema.
Está bien enviar una cadena base64 con FormData en Chrome, pero no se puede hacer con axios en el nodo (v8.9.3).
Y funciona con node-fetch...

const fetch = require('node-fetch')
const axios = require('axios')
const FormData = require('form-data')
const base64Img = require('base64-img')

const b64 = base64Img.base64Sync('./test.jpg').split('base64,')[1]
const form = new FormData()
form.append('b64_data', b64)
const headers = form.getHeaders()

// with node-fetch it worked
fetch('http://some.url', {
  method: 'POST',
  body: form,
  headers,
}).then(res => res.text()).then(console.log).catch(console.log)

// not working with axios
axios({
  method: 'POST',
  url: 'http://some.url',
  data: form,
  headers,
}).then(console.log).catch(console.log)

=== actualizar ===
No entiendo, uso los mismos encabezados para node-fetch y axios, y parece que publican los mismos datos de formulario en el servidor, ¿cómo es que terminan de manera diferente?
Por cierto, la URL real que estoy publicando proviene de aquí , lo que estoy haciendo es simular la solicitud http del navegador con nodejs, para enviar una imagen al servidor y obtener un enlace de vuelta.

Resolví esto usando:

<input onChange="emitImageInfo(this)" type="file" multiple>

function emitImageInfo($event){
  let files = $event.target.files
  let formData = new FormData();

  for (let i = 0; i < files.length; i++)
      formData.append('image[' + i + ']', files[i])

  axios.post('file/upload', formData)
     .then((result) => { console.log('got it') })
     .catch((err) => { console.log(err) })
}

esto funcionó:

axios.post(localhost:3000/items, formData, { headers: { 'Content-Type': 'multipart/form-data' }});

Tengo el mismo problema

no funciona con golang

Simplemente encuentre una forma simple en Vue, pero creo que se puede usar en otras situaciones.😀
Back-end: Express.js y paquete express-fileupload.

<template>
  <div>
    <input type="file"
           name=""
           id="file-upload"
           multiple
           @change="filesChange($event.target.files)">
    <button @click="handleSubmit">Send</button>
  </div>
</template>

<script>
export default {
  data() {
    return {
      formData: new FormData(),
    };
  },
  methods: {
    filesChange(fileList) {
      // First: append file to FormData
      Array.from(Array(fileList.length).keys()).map(x => {
        this.formData.append(fileList[x].name, fileList[x]);
      });
    },
    handleSubmit() {
      // Append Text
      this.formData.append('username', 'Jeremy');

      // Append Number: Will be string
      this.formData.append('number', 9527);

      // Append Array: Need to be converted to a string
      this.formData.append('arrData', JSON.stringify([1, 2, 3]));

      // Append Array: Need to be converted to a string
      this.formData.append(
        'objData',
        JSON.stringify({ name: 'Jeremy', age: 28 })
      );

      this.axios({
        method: 'post',
        url: `file/multi-users`,
        data: this.formData,
      }).then(res => {
        console.log(res);
      });
    },
  },
};
</script>

capture

Incluso nos enfrentamos al mismo problema. El encabezado de tipo de contenido se eliminó del script java de reacción y luego funcionó bien. Anteriormente, el límite no se configuraba cuando configuraba explícitamente el tipo de contenido

EDITAR: Después de leer más al respecto, parece que Express fue el problema de mi parte. Esperemos que esto pueda ser útil para otros.

Mismo problema aquí. @nickuraltsev Recomendaría ENCARECIDAMENTE reabrir el problema.

Estoy tratando de publicar un archivo en mi servidor de nodo a través de axios usando el siguiente código:

let ff = new FileReader();
ff.onload = (ev) => {
      var result = ev.target.result;
      console.log(`result: ${result} of type ${typeof(result)}`);
      axios.post('/test', {
                 file: result
                 })
                 .then((response) => {
                         console.log(`Response: ${response}`)
                  })
                  .catch((err) => {
                        console.log(`Test error: ${err}`);
                   })
}

var sampleFile = //getting the file here
ff.readAsArrayBuffer(sampleFile);

Sin embargo, el cuerpo de la solicitud está completamente vacío del lado del servidor

Intenté enviar el archivo directamente, leer el archivo como ArrayBuffer y leer el archivo como texto (aunque la carga útil es demasiado grande) y los 3 no funcionaron.

Dos años después:
El mismo problema...

@demeter-macik gracias, agregar un límite funcionó para mí :smile:

    const form = new FormData();
    form.append('email', '[email protected]');
    form.append('phone_no', '63');
    form.append('phone_code', '9179303100');

    if (logo) {
      form.append('logo', logo);
    }

    const response = await axios({
      method: 'post',
      url: `${apiUrl}users`,
      data: form,
      headers: {
        'content-type': `multipart/form-data; boundary=${form._boundary}`,
      },
    });

Esto definitivamente funciona para mí, todos los navegadores, incluido Safari iOS.

Mi código es algo como esto:

función muestraPost (config) {

// save reference this

let that = this;



// can optionally pull in form fields from an existing HTML form)

let myForm = document.getElementById('myForm');

let myFormData = new FormData(myForm);



// add in data from config.data if applicable

if (config && config.data) {

    that.objToStr(config.data, '', myFormData);



    for (let n2 in config.data) {

        if (config.data.hasOwnProperty(n2)) {

            myFormData.set(n2, config.data[n2]);

        }

    }

}



if (config.binaryFiles && config.binaryFiles.length > 0) {



    for (let i = 0; i < config.binaryFiles.length; i = i + 1) {

        let thisFile = config.binaryFiles[i];

        myFormData.append(thisFile.fieldName, thisFile.binaryData, thisFile.fileName)

    }

}





let axiosConfig = {

    method: 'post',

    url: config.url,

    data: myFormData,



    onUploadProgress: config.onUploadProgress,

};



if (config && config.binaryFiles && config.binaryFiles.length > 0) {

    axiosConfig.headers = {'Content-Type': 'multipart/form-data'};

}

else {

    axiosConfig.headers = {'Content-Type': 'application/x-www-form-urlencoded'};

}



const ax = axios.create();

// note that passing in config to the constructor is broken as of axios v0.19.0-beta.1

// So we work around by passing in config to the request() method



ax.request(axiosConfig)

    .then(function (response) {

        // handle success



        alert(response.data);



    })

};

// llamar a samplePost para cargar

muestraPost({

url: 'async',

data: {somefield: 'some value'}, //note: passes in as form fields



// optionally include array of binary files

binaryFiles: thisFileList

});

De: Antonio Vázquez [email protected]
Enviado: martes, 11 de septiembre de 2018 11:23
Para: axios/axios [email protected]
CC: David Rueter [email protected] ; Comentar [email protected]
Asunto: Re: [axios/axios] No puedo hacer que funcione un .post con 'Content-Type': 'multipart/form-data' (#318)

4 horas y contando para hacer una solicitud de publicación desde Safari. Sigue sin pasar... que diablos chicos??

Ninguna de las soluciones aquí me funcionó... :(


Estás recibiendo esto porque comentaste.
Responda a este correo electrónico directamente, véalo en GitHub https://github.com/axios/axios/issues/318#issuecomment-420371510 o silencie el hilo https://github.com/notifications/unsubscribe-auth/AFbi6JQBv06LTwL4z3HIAlvXAXDyps1- ks5uZ_9wgaJpZM4Ibm_z . https://github.com/notifications/beacon/AFbi6BSPfwPvNaWPFSdvtLKRYXS1m4uKks5uZ_9wgaJpZM4Ibm_z.gif

esto funcionó para mí también, gracias @arvi

twiliosms = asíncrono (Código) => {

var FormData = require('form-data');
var fs = require('fs');

var formulario = new FormData();
formulario.append('Para', '+524772773737');
form.append('De', '+737373737');
form.append('Cuerpo', Codigo);

tratar {
let axapi = esperar axios(
{
URL: '2010-04-01/Cuentas/AC8aa53c907943af79234414bb725c2cd3/Mensajes.json',
URL base: 'https://api.twilio.com',
encabezados: {'tipo de contenido': multipart/form-data; boundary=${form._boundary} ,},
formulario de datos,
autenticación: {
nombre de usuario: 'AC8aa53c907943af79234414bb725c2cd3',
contraseña: * ,
},
método: 'publicar',
}
)

} captura (e) {consola.error (e)}
}

Estoy deambulando por esta biblioteca que aún requiere soluciones autoescritas para las publicaciones de datos de formularios....

¿Cualquier actualización?

Tengo un error similar en NodeJS 10.11.0 y Axios 0.18.0 (ver #1892). Probé la solución de @arvi pero no funciona.

para mí, esto funciona:

let formData = new FormData(document.querySelector('#form'));

axios.post("/api/xxx", formData).then(console.log).catch(console.error)

y esto no funcionará

let formData = new FormData(document.querySelector('#form'));

axios.post("/api/xxx", {data: formData}).then(console.log).catch(console.error)

tenga en cuenta que el formato de parámetro de postdata debe ser (url , FormData) , no (url, {data: FormData})

beforeAll(function (done) {

          //parse form fields
          var parsefields = function(req,res){
            var form = new formidable.IncomingForm();
            form.parse(req, function (err, fields, files) {
              if (err) res.status(404).json(err)
              else res.status(200).json(fields);
            });  
          }

          router.route('parsefields').post(parsefields)

          //start server
          s = express()
          s.use('/',router)
          s.listen(4000,(err)=>{done(err)})
          done()
        });

        it('should parse and return form fields', function (done) {

          const fd = new FormData()
          fd.append('key','value')

          axios({
            method: 'POST',
            url: 'http://localhost:4000/parsefields',
            data: fd,
            headers : fd.getHeaders(),
          }).then(function (res) {
            expect(res).to.exist
            expect(res.body.key).to.equals('value')
          }).catch(err => {
            expect(err).not.to.exist
          })
          done()

        });
});

Estoy teniendo el mismo problema. Recibiendo un 404 sin error. Usando formidable para el analizador de formularios, express y axios.

No sé si esto ayuda a alguien, pero estaba viendo este problema solo en Safari y lo solucioné usando formdata-polyfill . Safari debería ser compatible con FormData.append() de forma nativa, pero tal vez la implementación sea ligeramente diferente.

EDITAR: Me equivoqué: estaba usando una URL creada a partir de un Blob. ¡Una vez que comencé a usar el blob correcto, todo funcionó a la perfección!

Tengo el mismo problema con Blob mientras puedo cargar archivos. La conversión de Blob a archivo es simple, pero me gustaría saber si esto es un error o si malinterpreté la sintaxis:

`` js upload () { let data = new FormData() data.append('file', this.croppedFile) data.append('blob', this.croppedBlob, 'blob.jpeg') axios.post('/api/fp/process/', data, { headers: { 'Accept': texto/simple`,
},
})

croppedFile is derived from croppedBlob with this simple code:
   `   return new File([this.cropImg], this.file.name, { type: this.file.type })`

Firefox dev tools show:

------WebKitFormBoundarytmInU7WtcHvmgYbc
Contenido-Disposición: formulario-datos; nombre="mancha"

------WebKitFormBoundarytmInU7WtcHvmgYbc
Contenido-Disposición: formulario-datos; nombre="archivo"; nombre de archivo="dscn2950.jpg"
Tipo de contenido: imagen/jpeg

gota:http :// localhost:8080/9a6446d1-1ca2-4fd3-a6c8-8b36d863c146
------WebKitFormBoundarytmInU7WtcHvmgYbc--

```
De acuerdo con la documentación de mozilla formData.append, parece que podría usar objetos Blob.

Lo que me atascó fue que mi servidor no estaba manejando los archivos correctamente, usando https://www.npmjs.com/package/multer lo solucionó

me es util! ¡Gracias!

Aquí nada funcionó para mí porque mi código era perfectamente bueno.
El problema real fue con el archivo que estaba arrastrando desde los resultados de búsqueda de Windows: Chrome no pudo encontrar la ubicación real y rompió todo el análisis de FormData. Navegar hasta el archivo y arrastrarlo resolvió el problema.

Hola a todos,
Por favor, ayúdame.

PUBLICAR https://www.googleapis.com/upload/drive/v3/files?uploadType=multipart HTTP/1.1
Autorización: Portador [YOUR_AUTH_TOKEN]
Tipo de contenido: multiparte/relacionado; límite=foo_bar_baz
Longitud del contenido: [NUMBER_OF_BYTES_IN_ENTIRE_REQUEST_BODY]

--foo_bar_baz
Tipo de contenido: aplicación/json; conjunto de caracteres = UTF-8

{
"nombre": "miObjeto"
}

--foo_bar_baz
Tipo de contenido: imagen/jpeg

[JPEG_DATOS]
--foo_bar_baz--

axios no admite el tipo de solicitud multiparte/relacionada

Para mí fue (supongo) trago. Porque estaba recibiendo el error con archivos minificados en mi servidor. Eliminé manualmente todo de la carpeta dist, dejé el tipo de contenido como indefinido y todo funciona como se esperaba.
Entonces tendrás algo como:

formdata.append("selectPaymentType", $scope.extraFields.selectPaymentType);
formdata.append("pickupMethod", $scope.extraFields.selectPickupType);
dejar solicitud = {
método: 'POST',
url: baseURL + 'pedidos',
datos: datos de formulario,
encabezados: {
'Tipo de contenido': indefinido,
'x-token-de-acceso': $scope.userToken
}
};
$http(solicitud)
.éxito(función (d) { })
.error(función() { });

PD: Esto es un extracto... También adjunto archivos y muchos más campos...

SERVIDOR:

var form = new multiparty.Form({uploadDir : './uploads/orders/'});

form.parse(req, function(err, campos, archivos) {
//TU CÓDIGO AQUÍ
})

hola, por favor, necesito ayuda: obtuve "archivo: este valor no debe estar en blanco". cuando intento buscar publicar una imagen usando fetch :
handleSubmit = (event) => { event.preventDefault(); //const { category } = this.state; console.log(this.state.file) let formData = new FormData(); formData.append("file",this.state.file); formData.append("name",this.state.name); alert('You Added a new Category Named ' + this.state.file); fetch(`${process.env.REACT_APP_BASE_URL}/category/image`, { method: 'POST', body: formData }).then(res => res.json()).then(err => console.log(err)); } constructor(accesorios) {
súper (accesorios);

this.state = {

    name: '',
    file: null
  ,
  isLoaded: false,
  isEditMode: false,

}

}
```

Para cualquiera, esto funcionó para mí.
Si está usando un archivo de entrada, debe usar MULTER en su router.post('/') como un middleware, antes de obtener los otros campos de entrada.

verifique su axios.create, estos encabezados deberían "encabezados: {}" y no usar datos. Así:
var instancia = axios.create({
encabezados: {
// 'Tipo de contenido': 'aplicación/x-www-form-urlencoded;charset=UTF-8',
},
// datos: {},
parámetros: {}
});

Hasta el día de hoy, esto no funciona en nodejs. El enfoque request-promise también funcionó para mí.

Pasé 2 días tratando de hacer que esto funcionara con axios en nodejs. Pasó 30 segundos para que realmente funcionara con request-promise en nodejs.

Probé diferentes soluciones pero al final manejé este problema agregando los encabezados:

const FormData = require('form-data')
const axios = require('axios')

const form = new FormData()
form.append('foo', 'bar')

await axios.post('http://myserver', form, { headers: form.getHeaders() })

@Googrosh Sí. Si. Si.

Pasé medio día averiguando si está relacionado con la configuración del cliente o del servidor.
Al final, headers: form.getHeaders() funcionó.

Se movió a got porque simplemente _funciona_ con formData y multipart/form-data - https://github.com/sindresorhus/got 🙌
Cerca, pero sin cigarros Axios 👋

  const form = new FormData()
  const stream = fs.createReadStream(file.path)

  form.append('file', stream, file.name)

  try {
    await got.post('http://example.com', { body: form })
  } catch (error) {
    next(error)
  }

Puedes hacerlo de esta manera:
handleSubmit = (e: cualquiera) => {
e.preventDefault();
datos constantes = new FormData();
data.append('product_csv', this.state.csvfile);
let accessToken = localStorage.getItem('access_token');
axios
.post('/subir', datos,
{ encabezados:
{ 'Content-Type': 'multipart/form-data', Autorización: accessToken }
})
.entonces(res => {
consola.log('res', res);
});
};

@Googrosh Brilliant, .getHeaders() también funcionó para mí. No puedo decirte cuántas horas pasé en esto. ¡Gracias!

Estoy usando react-native. Y terminé este problema usando rn-fetch-blob . Demasiado :(

Tengo el mismo problema, simplemente no funciona con FormData simple sin ningún archivo y .getHeaders() no ayuda. Movido a lib "obtenida" que simplemente funciona. Lo mencioné aquí también https://github.com/form-data/form-data/issues/458 (estoy usando Node v12)

2020 ES6 forma de hacer

Teniendo el formulario en html, enlacé datos así:

DATOS:

form: {
   name: 'Joan Cap de porc',
   email: '[email protected]',
   phone: 2323,
   query: 'cap d\ou'
   file: null,
   legal: false
},

onSubmit:

async submitForm() {
  const formData = new FormData()
  Object.keys(this.form).forEach((key) => {
    formData.append(key, this.form[key])
  })

  try {
    await this.$axios.post('/ajax/contact/contact-us', formData)
    this.$emit('formSent')
  } catch (err) {
    this.errors.push('form_error')
  }
}

Ver: https://github.com/axios/axios/issues/789#issuecomment -508114703

En el extremo receptor, si usa Express, necesita multer . body-parser no maneja el análisis de solicitudes de varias partes.

@DespertaWeb No funciona cuando no hay archivos.

¿Fue útil esta página
0 / 5 - 0 calificaciones