Axios: Não é possível obter um .post com 'Content-Type': 'multipart/form-data' para funcionar

Criado em 11 mai. 2016  ·  99Comentários  ·  Fonte: axios/axios

Passei algumas horas hoje tentando fazer uma solicitação de postagem funcionar com alguns parâmetros e um arquivo que preciso enviar.

Consegui fazê-lo funcionar com javascript puro e XMLHttpRequest, mas não funciona com o Axios. O que estou fazendo errado?

Aqui está o 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);

Qual seria a versão 'Axios' disso?

Aqui está uma das minhas tentativas (a simples):

// 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));

Obrigada! E obrigado pelo seu excelente trabalho com a Axios!

Comentários muito úteis

@rafaelbiten Acabei de tentar reproduzir o problema, mas sem sucesso. Usei o seguinte 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);

Os dados foram enviados com sucesso para o servidor:

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

Todos 99 comentários

O código me parece bom. (Você não precisa definir o Content-Type, mas não é importante.) O que acontece quando você tenta enviar uma solicitação via axios?

Percebi que definir Content-Type ou não não altera nada neste caso. Quando tento enviar a solicitação com Axios, parece que os dados vão como uma seqüência vazia para que o backend responda com um erro relacionado a parâmetros ausentes.

Eu estava usando 0.9.1, mas o problema persiste em 0.11.0.

Por favor, deixe-me saber se há mais alguma coisa que eu possa fazer para ajudar a depurar isso, ok?
Tks @nickuraltsev !

Você poderia por favor dar uma olhada em como seus pedidos se parecem no painel de rede Chrome dev Tools e fornecem uma captura de tela, se possível?

@nickuraltsev veja se isso ajuda:

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

Eu acho que os cabeçalhos de solicitação estão errados.

Então não há Request Payload?

Bem, deveríamos ter, mas os dados vão como uma string vazia. Não sei o que pode estar quebrando (considerando o código que compartilhei no meu primeiro post).

Eu vejo. E não há uma seção Request Payload para suas solicitações no Dev Tools, correto?

Possivelmente problema de cabeçalho relacionado. Quando o tipo de conteúdo é definido no objeto de configuração na solicitação, ele é concatenado, por exemplo
axios.post(
'https://example.com/login',
{emailAddress: email, senha: hashedPassword},
{headers: {'content-type': 'application/json'}}
);

header content-type vem como application/json,application/json
body não será analisado neste caso

@nickuraltsev certo! O que você vê nessa captura de tela é tudo o que tenho nas ferramentas de desenvolvimento.
@rrapant pode estar certo, mas tenho quase certeza de que definir 'Content-Type' ou não, pelo menos neste caso, não estava mudando nada. Teria que verificar novamente para ter certeza.

@rrapant O problema com valores de tipo de conteúdo duplicados foi corrigido por #317. A correção será incluída na próxima versão. Obrigada!

@rafaelbiten Acabei de tentar reproduzir o problema, mas sem sucesso. Usei o seguinte 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);

Os dados foram enviados com sucesso para o servidor:

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

@rafaelbiten Você poderia tentar enviar uma solicitação com FromData para http://httpbin.org/post como no meu trecho de código?

Fechando isso por enquanto. Sinta-se à vontade para reabrir se necessário.

Oi @nickuraltsev , estou com o mesmo 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);
              });

Encontre a captura de tela das informações do meu cabeçalho abaixo,

image

Eu tenho uma pergunta, _o axios suporta o envio de arquivos de dados de várias partes para o servidor do nó?_

@Sreekhar Não sei se funcionará, mas você poderia adicionar o FormData como o segundo argumento em vez de envolvê-lo em outro objeto?
axios.post('/dataAPI/sendFile', fd, config)

Se você precisar usar 'UploadCommand' como o nome da parte onde o arquivo está, você precisa usar isso
fd.append('UploadCommand', this.refs.multipartfiles.files[0]);

@yungpanda eu encontrei uma alternativa para fazer isso. Acho que vou ter que recriar a API agora. De qualquer forma, vou tentar verificar se funciona, vou manter o tópico atualizado. Obrigado pela sua resposta.

@Sreekhar Defina Content-Type como indefinido para permitir que o navegador o altere para multipart/form-data e adicione limite automaticamente

@nickuraltsev este é um exemplo mínimo que não funciona no nó:

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)
})

Erro: escrever após o término

@krzkaczor Você encontrou algum trabalho para enviar multipart/form-data com axios?

@PierreCavalet não, usei request-promise em vez disso.

@krzkaczor obrigado, forçado a mudar também

@krzkaczor Tente adicionar o tipo de conteúdo se você ainda não o fez

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 também estou enfrentando o mesmo problema com axios e multipart/form-data. Você pode postar a essência do código que você usou com request-promise.

@dan-boa aqui vai: https://gist.github.com/krzkaczor/bdbe09d4096b051a3c18387c4ca79a06 Também mostra um hack como enviar string como arquivo (definindo caminho)

Se alguém estiver se perguntando, aqui está um exemplo de como usar FormData com axios . Basicamente, você precisa transmitir os dados para um buffer e passar os cabeçalhos corretos.

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()
  })
}))

Eu tive o mesmo problema (no navegador, não no nó). Acontece que funciona se você não definir o cabeçalho Content-Type e deixar o axios descobrir as coisas (verifique também se você não definir esse cabeçalho como padrão nos interceptores do axios também. padrões para o restante das chamadas da API, você pode criar uma instância axios separada para solicitações FormData())

Acabei indo com solicitação-promessa no lado do nó ao tentar fazer upload para outro servidor remoto.

Eu mudei para solicitação-promessa por esse mesmo motivo. Amor axios de outra forma!

@guncha Seu exemplo funcionou para mim em 0.15.3, até que tentei fazer upload de um arquivo binário, que acabou codificado como UTF8. Dizer ao concat para usar um buffer corrigiu o 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, eu usaria uma promessa:

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 trabalhando para mim. obrigada

mesmo problema aqui

basta adicionar limite 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);
    });

Ei,
Estou recebendo este arquivo no formato json, alguém pode me ajudar como devo convertê-lo em arquivo multipart.
A plataforma utilizada é 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"
obrigado

O código funciona no navegador, mas não no nó.

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));

Olá @Sreekhar
Para mim, mudei a configuração para
const config = { headers: { 'Content-Type': 'application/json' } };
e funcionou bem

Reabra até que haja alguma resposta/fluxo de trabalho consistente para isso. Parece que muitas pessoas ainda estão enfrentando problemas com isso.

+1 reabrir

Postagens HTTP que incluem dados de arquivos binários parecem funcionar bem no 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);
    });

            }

Além disso, ao usar buffers para representar o arquivo, isso funcionou para mim:

      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 observar: qualquer uma das soluções acima NÃO funciona se você tiver quaisquer parâmetros de dados padrão definidos nos padrões da instância do Axios. Você também pode verificar se especifica um cabeçalho Content-Type padrão em sua instância do Axios (via axios.defaults.headers e axios.defaults.parameters).

Isso pode não estar certo, mas o problema pode estar relacionado ao uso de body-parser no lado do servidor. Eu estava lutando com um problema semelhante e encontrei este post:

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

TL;DR - body-parser não lida com dados multipart/form-data. Em outras palavras, axios não é o problema e body-parser é. Pode ser por isso que as soluções de buffer mencionadas acima funcionam.

Presumo que essa funcionalidade seja por motivos de segurança, conforme observado aqui:

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

Espero que ajude alguém!

Eu tenho o mesmo problema. Eu uso o Axios 0.16.2 e o envio por XMLHttpRequest funciona, mas não pelo Axios.

Eu tenho o objeto FormData básico:

const formData = new FormData();
formData.append('name', 'textName');

Eu tentei a sugestão de @Janekk :

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

então a sugestão de @faalkhah :

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

ou a sugestão de @askona :

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

O cabeçalho da solicitação é application/json e formData está vazio.

Não sei como tentar a correção @demeter-macik, porque parece que funciona apenas no back-end https://stackoverflow.com/a/13454425/968379

Olá a todos,
Eu tenho o mesmo problema
meu código no 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)`

no servidor de velas, eu registro o console req.body
Descobri, quando chamo request 10 vezes, tem umas 3 4 vezes que o servidor não recebe o body (body está vazio).
eu verifiquei no devtool do chrome, o pedido ainda transmite o arquivo e o corpo no payload.
Eu ainda não descobri o porquê, mas eu tenho uma solução

que é o cabeçalho da solicitação.

`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)`

Olá @Sreekhar ,
Você resolveu o problema ? Não encontrei a solução alguém pode me ajudar, por favor.
Além disso, obrigado antecipadamente

Olá,

Eu tenho tentado postar multiformdata (é uma API SMS Eztext)
usando axios com node.js.

Funciona bem para o seguinte código,
return new Promise(função(resolver, rejeitar) {

        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);
        });

Mas não funciona com axios, pois o SMS não é enviado, mas recebo o código de status como 200 para a seguinte solicitação: -
var axios=require('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 que a solicitação de postagem é um sucesso com a biblioteca 'request' e não com o Axios?

Você já tentou converter os dados de JSON para FormData sem definir nenhum cabeçalho?
Os cabeçalhos dos dados (ou seja, além dos cabeçalhos de autenticação) devem ser tratados automaticamente

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 a conversão de JSON para FormData, use algo como nesta resposta

Lembre-se de que as chaves aninhadas são difíceis de manipular. Por exemplo, ao enviar dados para nosso back-end, funciona se os nivelarmos assim:

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

mesmo problema aqui.

claro, @michaelscheurer! Definir os cabeçalhos de uma solicitação não é suficiente: você deve enviar um FormData para que funcione. É um objeto do navegador que será serializado com todos os limites adequados para trabalhar com a solicitação ... nem axios nem vanilla js converterão dados JSON em FormData para você. O Axios reconhecerá que é um FormData e também definirá os cabeçalhos para você, para que você realmente não precise defini-los
Tente seguir minhas dicas de resposta anteriores ...

@Iamuertepeluda
Eu tentei seguir conforme sua sugestão, mas sem sorte, mesmo comportamento que recebo o status 200 ok, mas o SMS não está sendo enviado com a seguinte solicitação
var axios=require('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 você está usando node.js ou navegador?

em um navegador você não precisa de const FormData = require('form-data'); já que FormData é nativo.

Além disso, tente sem definir cabeçalhos e qs, ou tente

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

como mencionei, deve definir cabeçalhos automaticamente em um navegador

@ Ruchi2729 vejo que você está usando o nó, desculpe.
Lembro-me de ter usado form-data com axios uma vez, mas não me lembro se realmente funcionou.

Mas você tem certeza que esta é a maneira correta de enviar SMS com eztexting? De seus documentos, parece diferente, como você deve usar uma chave de API e seu próprio cliente de nó ...

podemos reabrir isso? Parece que muitas pessoas ainda estão lutando contra isso, inclusive eu. Por exemplo, essa solicitação não chega ao servidor como esperado via axios, mas se eu enviar o mesmo arquivo pelo Postman como multipart/form-data , tudo funciona.

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

Edit: Meu problema estava tentando enviar um data-uri codificado em base64 como dados de formulário. Se alguém estiver enfrentando o mesmo problema, aqui está um código de exemplo para convertê-lo:

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);
}

Ei, estou me referindo a este documento:- https://www.eztexting.com/developers/sms-api-documentation/rest#Sending
qual documento você está se referindo para a chave de API e tudo mais?

@Ruchi2729
Desculpe confundi com o Nexmo, que é outro serviço de SMS e tem cliente próprio para node 😅

Mas de qualquer forma, de acordo com a documentação a que você se referiu , você pode evitar FormData definindo format para json e deixar axios enviar uma carga JSON (você pode deixá-la adivinhar cabeçalhos implicitamente pelo formato da carga)

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

Eu lutei com isso por muito mais tempo que eu quero admitir, então espero que isso ajude alguém. Estou usando axios, express e express-fileupload. Posso fazer upload com sucesso para o Node com parâmetros que adicionei ao FormData. Eu pego os arquivos com req.files e pego o resto dos dados do formulário com req.body['yourfilename']

Servidor (Expresso):

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);

Front-end (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/helper/amazon/upload , formData, { headers: { 'Content-Type': 'multipart/form-data' } });

Resultado:

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

Eu tenho o mesmo problema, posso ver que enviei com sucesso os dados do arquivo com minhas ferramentas de desenvolvimento, mas dentro do meu contoller meu $ request->file('file') está vazio
Meu componente

enviar o formulário() {
this.formData =new FormData();
this.formData.append('file',this.$refs.file.files[0]);
this.formData.append('analysis',this.analyticsForm.analysis);
this.formData.append('_method','PATCH');
axios.post('/analytics',
this.formData
,{headers: {'Content-Type': 'multipart/form-data'}}).then(response => this.isSubmittedRedirect(false,'/sources/'+this.source+'/description'+'') )
.catch((erro) => console.log(erro))
},

Descobri que fazer qualquer coisa com FormData era um problema, já que o MVC não parece gostar de obter nada dessa maneira, porque você precisa especificar o Content-Type como multipart/form-data e estava lançando uma exceção quando eu verifique if (!Request.Content.IsMimeMultipartContent()) { throw new HttpResponseException(HttpStatusCode.UnsupportedMediaType); } , como o site da Microsoft diz para fazer: https://docs.microsoft.com/en-us/aspnet/web-api/overview/advanced/sending-html-form-data-part- 2

Foi melhor apenas colocar meu arquivo em uma string base64:
https://stackoverflow.com/questions/37134433/convert-input-file-to-byte-array/49676679#49676679

Este post pode ser mais relevante sobre como fazer isso, pois usei um DropZone neste exemplo:
https://stackoverflow.com/questions/32556664/getting-byte-array-through-input-type-file/49660172#49660172

E eu vou mais detalhadamente sobre isso, aqui: https://stackoverflow.com/questions/47574218/converting-from-blob-to-binary-to-save-it-to-mongodb/49660839#49660839

Então eu poderia criar um objeto JSON:

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

Em vez de usar axios, usei apenas um XMLHttpRequest.

 const xhr = new XMLHttpRequest();

E abra e defina o cabeçalho:

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

Eu configurei o onreadystatechange para capturar a resposta:

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

e envia:

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

Se você usar axios, provavelmente seria:

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); }

No lado do MVC, você precisa de um modelo correspondente:

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

e, em seguida, tenha isso como um parâmetro em sua chamada Post com uma tag [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 }));
}

Você deve devolver o que enviou. Observe que, se você implementar isso como um teste, faça-o com um arquivo muito pequeno, para não ficar esperando para sempre com o potencial de bloquear o navegador/memória do seu sistema.

@navyjax2
Eu estava fazendo como você disse, estava trabalhando com arquivo pequeno, mas preciso enviar arquivo grande (> 250Mo), e sim, estava travando meu navegador

Sim, para isso, você pode querer quebrar a matriz de arquivos em pedaços de tamanho gerenciável e enviar blocos, tendo um método na outra extremidade (do lado do servidor) que possa combiná-los novamente e dando a ele um parâmetro para que sabe qual pedaço é (1º, 2º, 3º, etc.) e quantos pedaços totais esperar antes de processar o arquivo no lado do servidor. Mas acho que, não importa o que você faça, com um arquivo desse tamanho, você terá que esperar que ele funcione. Terá que ter cuidado com o gerenciamento de memória se você fizer isso também, porque você teria que garantir que está limpando ou reutilizando suas variáveis ​​a cada vez e não reinstanciando novas versões das mesmas variáveis ​​a cada vez você faz um bloqueio. Uma das poucas vezes que uma variável global é boa - ou apenas definida para um campo de modelo a cada execução.

Concordo com @epferrari , considere reabrir este problema.
Não há problema em enviar uma string base64 com FormData no chrome, mas não é possível fazer isso com axios no node (v8.9.3).
E funciona com 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)

=== atualização ===
Eu não entendo, eu uso os mesmos cabeçalhos para busca de nó e axios, e parece que eles postam os mesmos dados de formulário no servidor, como eles terminam de maneira diferente?
A propósito, a url real que estou postando vem daqui , o que estou fazendo é simular a solicitação http do navegador com nodejs, para enviar uma imagem para o servidor e obter um link de volta.

Eu contornei isso 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) })
}

isso funcionou:

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

Eu tenho o mesmo problema

não trabalho com golang

Basta encontrar uma maneira simples no Vue, mas acho que pode ser usada em outras situações.😀
Back-end: Express.js e pacote 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

Até nós estávamos enfrentando o mesmo problema. O cabeçalho content -type foi removido do script java react e funcionou bem. Anteriormente, o limite não estava sendo configurado quando você definiu explicitamente no tipo de conteúdo

EDIT: Depois de ler mais sobre isso, o Express foi o problema do meu lado. Espero que isso possa ser útil para outras pessoas

Mesma questão aqui. @nickuraltsev Recomendaria FORTEMENTE a reabertura do problema.

Estou tentando postar um arquivo no meu servidor de nós via axios usando o seguinte 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);

O corpo da solicitação está completamente vazio no lado do servidor

Tentei enviar o arquivo diretamente, lendo o arquivo como um ArrayBuffer e lendo o arquivo como texto (carga útil muito grande) e todos os 3 não funcionaram.

Dois anos depois:
Mesmo problema...

@demeter-macik obrigado, adicionar limite funcionou para mim :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}`,
      },
    });

Isso definitivamente está funcionando para mim - todos os navegadores, incluindo o Safari iOS.

Meu código é algo assim:

function samplePost (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);



    })

};

// chama samplePost para fazer upload

amostraPost({

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: terça-feira, 11 de setembro de 2018 11:23
Para: axios/axios [email protected]
Cc: DavidRueter [email protected] ; Comente [email protected]
Assunto: Re: [axios/axios] Não consigo fazer um .post com 'Content-Type': 'multipart/form-data' funcionar (#318)

4 horas e contando para fazer uma solicitação de postagem do Safari. Ainda não está acontecendo... que diabos pessoal ??

Nenhuma das soluções aqui funcionou comigo ... :(


Você está recebendo isso porque comentou.
Responda a este e-mail diretamente, visualize-o no GitHub https://github.com/axios/axios/issues/318#issuecomment-420371510 ou silencie o tópico https://github.com/notifications/unsubscribe-auth/AFbi6JQBv06LTwL4z3HIAlvXAXDyps1- ks5uZ_9wgaJpZM4Ibm_z . https://github.com/notifications/beacon/AFbi6BSPfwPvNaWPFSdvtLKRYXS1m4uKks5uZ_9wgaJpZM4Ibm_z.gif

isso funcionou para mim também, obrigado @arvi

twiliosms = assíncrono (Codigo) => {

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

var formulário = new FormData();
form.append('Para', '+524772773737');
form.append('De', '+737373737');
form.append('Corpo', Código);

experimentar {
deixe axapi = aguarde axios(
{
url: '2010-04-01/Accounts/AC8aa53c907943af79234414bb725c2cd3/Messages.json',
baseURL: 'https://api.twilio.com',
headers: {'content-type': multipart/form-data; boundary=${form._boundary} ,},
dados: formulário,
autenticação: {
nome de usuário: 'AC8aa53c907943af79234414bb725c2cd3',
senha: * ,
},
método: 'postar',
}
)

} catch (e) {console.error(e)}
}

Estou vagando por esta biblioteca ainda requer soluções alternativas auto-escritas para postagens de dados de formulário ....

Qualquer atualização?

Eu tenho um erro semelhante no NodeJS 10.11.0 e no Axios 0.18.0 (veja #1892). Eu tentei a correção do @arvi , mas não funciona.

para mim, isso funciona:

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

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

e isso não vai funcionar

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

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

esteja ciente de que o formato do parâmetro postdata deve ser (url , FormData) , não (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()

        });
});

Estou tendo o mesmo problema. Recebendo um 404 sem erro. Usando formidável para analisador de formulários, expresso e axios.

Não sei se isso ajuda alguém, mas estava vendo esse problema apenas no Safari e o corrigi usando formdata-polyfill . O Safari deve suportar FormData.append() nativamente, mas talvez a implementação seja um pouco diferente?

EDIT: eu estava errado: eu estava usando uma URL criada a partir de um Blob. Uma vez que comecei a usar o blob correto, tudo funcionou como um encanto!

Eu tenho o mesmo problema com o Blob enquanto posso fazer o upload do arquivo. Converter de Blob para arquivo é simples, mas gostaria de saber se isso é um bug ou interpretei mal a sintaxe:

`` 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/simples`,
},
})

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
Conteúdo-Disposição: forma-dados; nome="blob"

------WebKitFormBoundarytmInU7WtcHvmgYbc
Conteúdo-Disposição: forma-dados; nome="arquivo"; nomedoarquivo="dscn2950.jpg"
Tipo de conteúdo: imagem/jpeg

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

```
De acordo com a documentação do mozilla formData.append, parece que eu poderia usar objetos Blob.

O que me deixou preso foi que meu servidor não estava lidando com arquivos corretamente, usando https://www.npmjs.com/package/multer corrigiu

é útil para mim! Obrigado!

Nada aqui funcionou para mim porque meu código era perfeitamente bom.
O verdadeiro problema era com o arquivo que eu estava arrastando dos resultados de pesquisa do Windows - o Chrome não conseguiu encontrar o local real e quebrou toda a análise de FormData. Navegar até o arquivo e arrastá-lo resolveu o problema.

Olá a todos,
Por favor me ajude.

POST https://www.googleapis.com/upload/drive/v3/files?uploadType=multipart HTTP/1.1
Autorização: portador [YOUR_AUTH_TOKEN]
Tipo de conteúdo: multipart/relacionado; limite=foo_bar_baz
Comprimento do conteúdo: [NUMBER_OF_BYTES_IN_ENTIRE_REQUEST_BODY]

--foo_bar_baz
Tipo de conteúdo: application/json; conjunto de caracteres=UTF-8

{
"nome": "meuObjeto"
}

--foo_bar_baz
Tipo de conteúdo: imagem/jpeg

[JPEG_DATA]
--foo_bar_baz--

axios não suporta o tipo de solicitação multipart/relacionada

Para mim foi (eu acho) gole. Porque eu estava recebendo o erro com arquivos minificados no meu servidor. Apaguei manualmente tudo da pasta dist, deixei o tipo de conteúdo como indefinido e tudo funciona conforme o esperado.
Então você terá algo como:

formdata.append("selectPaymentType", $scope.extraFields.selectPaymentType);
formdata.append("pickupMethod", $scope.extraFields.selectPickupType);
deixe pedido = {
método: 'POST',
url: baseURL + 'pedidos',
dados: formdata,
cabeçalhos: {
'Tipo de conteúdo': indefinido,
'x-access-token': $scope.userToken
}
};
$http(solicitação)
.sucesso(função (d) {})
.error(função() { });

PS: Este é um trecho... Também anexo arquivos e muito mais campos...

SERVIDOR:

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

form.parse(req, function(err, campos, arquivos) {
// SEU CÓDIGO AQUI
})

hii plz eu preciso de ajuda: eu tenho "arquivo: Este valor não deve estar em branco." quando tento buscar postar uma imagem 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)); } construtor(props) {
super(adereços);

this.state = {

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

}

}
```

Para qualquer um, isso funcionou para mim.
Se estiver usando o arquivo de entrada, você deve usar MULTER em seu router.post('/') como um middleware, antes de obter os outros campos de entrada.

verifique seu axios.create, esses cabeçalhos devem ser "headers:{}" e não use data.like this :
var instância = axios.create({
cabeçalhos: {
// 'Content-Type': 'application/x-www-form-urlencoded;charset=UTF-8',
},
// dados: {},
parâmetros: {}
});

Até hoje, isso não está funcionando no nodejs. A abordagem request-promise também funcionou para mim.

Passei 2 dias tentando fazer isso funcionar com axios em nodejs. Gastei 30 segundos para realmente fazê-lo funcionar com solicitação-promessa em nodejs.

Tentei soluções diferentes, mas no final lidei com esse problema adicionando os cabeçalhos:

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 Sim. sim. sim.

Passei meio dia descobrindo se está relacionado à configuração do cliente ou do servidor.
No final, headers: form.getHeaders() fez o truque.

Movido para got porque apenas _funciona_ com formData e multipart/form-data - https://github.com/sindresorhus/got 🙌
Perto, mas sem charuto 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)
  }

Você pode fazer desta forma:
handleSubmit = (e: qualquer) => {
e.preventDefault();
dados const = new FormData();
data.append('product_csv', this.state.csvfile);
let accessToken = localStorage.getItem('access_token');
axios
.post('/upload', dados,
{ cabeçalhos:
{ 'Content-Type': 'multipart/form-data', Autorização: accessToken }
})
.then(res => {
console.log('res', res);
});
};

@Googrosh Brilhante, .getHeaders() funcionou para mim também. Eu não posso te dizer quantas horas eu gastei nisso. Obrigado!

Estou usando react-native. E acabei com esse problema usando rn-fetch-blob . Que pena :(

Eu tenho o mesmo problema, ele simplesmente não funciona com FormData simples sem nenhum arquivo e .getHeaders() não ajuda. Movido para "got" lib que simplesmente funciona. Mencionei aqui também https://github.com/form-data/form-data/issues/458 (estou usando o Node v12)

2020 ES6 maneira de fazer

Tendo o formulário em html eu vinculei os dados assim:

DADOS:

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

ao enviar:

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')
  }
}

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

No lado receptor, se você estiver usando o Express, precisará de multer . body-parser não lida com a análise de solicitações de várias partes.

@DespertaWeb Não funciona quando não há arquivos.

Esta página foi útil?
0 / 5 - 0 avaliações