Axios: Impossible de faire fonctionner un .post avec 'Content-Type' : 'multipart/form-data'

Créé le 11 mai 2016  ·  99Commentaires  ·  Source: axios/axios

J'ai passé quelques heures aujourd'hui à essayer de faire fonctionner une demande de publication avec quelques paramètres et un fichier que je dois télécharger.

J'ai pu le faire fonctionner avec du javascript pur et XMLHttpRequest mais cela ne fonctionne pas avec Axios. Qu'est-ce que je fais mal?

Voici le code qui fonctionne avec 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);

Quelle en serait la version "Axios" ?

Voici un de mes essais (le plus 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));

Merci! Et merci pour votre excellent travail avec Axios !

Commentaire le plus utile

@rafaelbiten J'ai juste essayé de reproduire le problème mais en vain. J'ai utilisé le code suivant :

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

Les données ont été envoyées avec succès au serveur :

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

Tous les 99 commentaires

Le code me semble bon. (Vous n'avez pas besoin de définir le Content-Type, mais ce n'est pas important.) Que se passe-t-il lorsque vous essayez d'envoyer une requête via axios ?

J'ai remarqué que définir Content-Type ou non ne change rien dans ce cas. Lorsque j'essaie d'envoyer la demande avec Axios, il semble que les données se présentent sous la forme d'une chaîne vide, de sorte que le backend répondra avec une erreur liée aux paramètres manquants.

J'utilisais 0.9.1 mais le problème persiste sur 0.11.0.

S'il vous plaît, faites-moi savoir s'il y a autre chose que je peux faire pour aider à déboguer cela, d'accord ?
Merci @nickuraltsev !

Pourriez-vous, s'il vous plaît, jeter un œil à l'apparence de vos demandes dans le panneau Réseau des outils de développement Chrome et fournir une capture d'écran si possible ?

@nickuraltsev voir si cela aide :

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

Je pense que les en-têtes de requête sont erronés.

Il n'y a donc pas de Request Payload ?

Eh bien, nous aurions dû le faire, mais les données se présentent sous la forme d'une chaîne vide. Je ne sais pas ce qui peut le casser (compte tenu du code que j'ai partagé dans mon premier message).

Je vois. Et il n'y a pas de section Request Payload pour vos requêtes dans Dev Tools, n'est-ce pas ?

Problème d'en-tête peut-être lié. Lorsque le type de contenu est défini dans l'objet de configuration dans la demande, il est concaténé, par exemple
axios.post(
'https://example.com/login',
{emailAddress : e-mail, mot de passe : hashedPassword},
{en-têtes : {'content-type' : 'application/json'}}
);

le type de contenu d'en-tête se présente sous la forme application/json,application/json
le corps ne sera pas analysé dans ce cas

@nickuraltsev c'est vrai ! Ce que vous voyez sur cette capture d'écran est tout ce que j'ai sur les outils de développement.
@rrapant a peut-être raison, mais je suis presque sûr que définir 'Content-Type' ou non, du moins dans ce cas, ne changeait rien. Il faudrait que je vérifie à nouveau pour être sûr.

@rrapant Le problème avec les valeurs de type de contenu en double a été corrigé par #317. Le correctif sera inclus dans la prochaine version. Merci!

@rafaelbiten J'ai juste essayé de reproduire le problème mais en vain. J'ai utilisé le code suivant :

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

Les données ont été envoyées avec succès au serveur :

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

@rafaelbiten Pourriez-vous s'il vous plaît essayer d'envoyer une demande avec FromData à http://httpbin.org/post comme dans mon extrait de code ?

Fermant ceci pour l'instant. N'hésitez pas à rouvrir si nécessaire.

Bonjour @nickuraltsev , j'ai le même problème.

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

Veuillez trouver ci-dessous la capture d'écran de mes informations d'en-tête,

image

J'ai une question, _axios prend-il en charge l'envoi de fichiers de données en plusieurs parties au serveur de nœud ?_

@Sreekhar Je ne sais pas si cela fonctionnera, mais pourriez-vous peut-être ajouter le FormData comme deuxième argument au lieu de l'envelopper dans un autre objet ?
axios.post('/dataAPI/sendFile', fd, config)

Si vous devez utiliser 'UploadCommand' comme nom de la partie où se trouve le fichier, vous devez utiliser ceci
fd.append('UploadCommand', this.refs.multipartfiles.files[0]);

@yungpanda J'ai trouvé une alternative pour faire ça. Je suppose que je vais devoir recréer l'API maintenant. Quoi qu'il en soit, je vais essayer de vérifier si cela fonctionne, je garderai le fil à jour. Merci pour votre réponse.

@Sreekhar Définissez Content-Type sur undefined pour permettre au navigateur de le changer en multipart/form-data et d'ajouter automatiquement une limite

@nickuraltsev c'est un exemple minimal qui ne fonctionne pas sur node :

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

Erreur : écrire après la fin

@krzkaczor Avez-vous trouvé un moyen d'envoyer des données multipart/form avec axios ?

@PierreCavalet non , j'ai utilisé request-promise la place.

@krzkaczor merci, obligé de changer aussi

@krzkaczor Essayez d'ajouter le type de contenu si vous ne l'avez pas déjà fait

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 Je suis également confronté au même problème avec axios et multipart/form-data. Pouvez-vous poster l'essentiel du code que vous avez utilisé avec request-promise.

@dan-boa ici tu vas: https://gist.github.com/krzkaczor/bdbe09d4096b051a3c18387c4ca79a06 Il montre également un hack comment envoyer une chaîne en tant que fichier (chemin de définition)

Si quelqu'un se demande, voici un exemple d'utilisation FormData avec axios . Vous devez essentiellement diffuser les données dans un tampon et transmettre les en-têtes corrects.

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

J'ai eu le même problème (dans le navigateur, pas dans le nœud). Il s'est avéré que cela fonctionne si vous ne définissez pas du tout l'en-tête Content-Type et laissez axios comprendre les choses (vérifiez également si vous ne définissez pas également cet en-tête par défaut dans les intercepteurs axios. Si vous en avez besoin par défaut pour le reste des appels d'API, vous pouvez créer une instance axios distincte pour les requêtes FormData())

J'ai fini par utiliser la promesse de demande du côté du nœud lorsque j'essayais de télécharger sur un autre serveur distant.

Je suis passé à la demande-promesse pour cette même raison. Aimez les axios autrement!

@guncha Votre exemple a fonctionné pour moi en 0.15.3, jusqu'à ce que j'essaye de télécharger un fichier binaire, qui a fini par être codé en UTF8. Dire à concat d'utiliser un tampon a résolu le problème.

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

Alternativement, j'utiliserais une promesse:

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 travaille pour moi. Je vous remercie

même problème ici

ajoutez simplement une limite à 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);
    });

Hey,
Je reçois ce fichier au format json quelqu'un peut-il m'aider comment dois-je le convertir en fichier multipart.
La plateforme utilisée est 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"
Merci

Le code fonctionne dans le navigateur mais pas sur le nœud.

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

Salut @Sreekhar
Pour ma part, j'ai changé la configuration en
const config = { headers: { 'Content-Type': 'application/json' } };
et ça a bien fonctionné

Veuillez rouvrir jusqu'à ce qu'il y ait une réponse / un flux de travail cohérent pour cela. Il semble que beaucoup de gens rencontrent encore des problèmes avec cela.

+1 réouverture

Les messages HTTP qui incluent des données de fichiers binaires semblent fonctionner correctement dans 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);
    });

            }

De plus, lors de l'utilisation de tampons pour représenter le fichier, cela a fonctionné pour moi :

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

Important à noter : aucune des solutions ci-dessus ne fonctionne PAS si vous avez défini des paramètres de données par défaut dans les valeurs par défaut de l'instance Axios. Vous pouvez également vérifier si vous spécifiez un en-tête Content-Type par défaut dans votre instance Axios (via axios.defaults.headers et axios.defaults.parameters).

Ce n'est peut-être pas pertinent, mais le problème peut être lié à l'utilisation body-parser côté serveur. J'étais aux prises avec un problème similaire et je suis tombé sur ce message:

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

TL;DR - body-parser ne gère pas les données multipart/form-data. En d'autres termes, axios n'est pas le problème et body-parser l'est. C'est peut-être la raison pour laquelle les solutions tampons mentionnées ci-dessus fonctionnent.

Je suppose que cette fonctionnalité est pour des raisons de sécurité, comme indiqué ici :

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

J'espère que cela aide quelqu'un!

J'ai le même problème. J'utilise Axios 0.16.2 et l'envoi par XMLHttpRequest fonctionne, mais pas par Axios.

J'ai un objet FormData de base :

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

J'ai essayé la suggestion de @Janekk :

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

puis la suggestion de @faalkhah :

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

ou la suggestion de @askona :

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

L'en-tête de la requête est application/json et formData est vide.

Je ne sais pas comment essayer le correctif @demeter-macik, car il semble que cela ne fonctionne que dans le back-end https://stackoverflow.com/a/13454425/968379

salut tout le monde,
J'ai le même problème
mon code dans le client
`

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

dans le serveur sails, je connecte la console req.body
J'ai trouvé, quand j'appelle request 10 fois, il y a environ 3 à 4 fois que le serveur ne reçoit pas le corps (le corps est vide).
j'ai vérifié dans devtool de chrome, la demande a toujours transmis le fichier et le corps dans la charge utile.
Je n'ai toujours pas compris pourquoi, mais j'ai une solution

c'est l'en-tête de la requête.

`code

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

Salut @Sreekhar ,
Avez-vous résolu le problème ? Je n'ai pas trouvé la solution si quelqu'un peut m'aider s'il vous plait.
Aussi, merci d'avance

Bonjour,

J'ai essayé de publier multiformdata (c'est une API Eztext SMS)
en utilisant axios avec node.js.

Cela fonctionne bien pour le code suivant,
return new Promesse(fonction(résoudre, rejeter) {

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

Mais cela ne fonctionne pas avec axios car les SMS ne sont pas envoyés, mais je reçois le code d'état 200 pour la requête suivante : -
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);
             });

pourquoi la demande de publication est un succès avec la bibliothèque 'request' et non avec Axios?

Avez-vous essayé de convertir les données de JSON en FormData sans définir d'en-tête ?
Les en-têtes des données (c'est-à-dire en plus des en-têtes d'authentification) doivent être automatiquement gérés

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

Pour la conversion de JSON en FormData, utilisez quelque chose comme dans cette réponse

N'oubliez pas que les clés imbriquées sont difficiles à gérer. Par exemple, lors de l'envoi de données à notre backend, cela fonctionne si nous les aplatissons comme ceci :

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

Même problème ici.

bien sûr, @michaelscherer ! Définir les en-têtes d'une requête ne suffit pas : vous devez soumettre un FormData pour que cela fonctionne. C'est un objet de navigateur qui sera sérialisé avec toutes les limites appropriées pour fonctionner avec la demande... ni axios ni vanilla js ne convertira une donnée JSON en FormData pour vous. Axios reconnaîtra qu'il s'agit d'un FormData et définira également les en-têtes pour vous, vous n'avez donc pas vraiment besoin de les définir
Essayez de suivre mes conseils de réponse précédents...

@Iamuertepeluda
J'ai essayé de suivre la chose selon votre suggestion mais pas de chance,,, même comportement que j'obtiens le statut 200 ok mais le SMS n'est pas envoyé avec la demande suivante
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 utilisez-vous node.js ou un navigateur ?

dans un navigateur, vous n'avez pas besoin const FormData = require('form-data'); puisque FormData est natif.

De plus, essayez sans définir d'en-têtes et de qs, ou essayez

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

comme je l'ai mentionné, il devrait définir automatiquement les en-têtes dans un navigateur

@ Ruchi2729 je vois que vous utilisez node, désolé.
Je me souviens avoir utilisé form-data avec axios une fois, mais je ne me souviens pas si cela a réellement fonctionné.

Mais êtes-vous sûr que c'est la bonne façon d'envoyer des SMS avec eztexting ? D'après leurs documents, cela semble différent, comme si vous deviez utiliser une clé API et leur propre client de nœud...

pouvons-nous le rouvrir ? On dirait que beaucoup de gens se heurtent encore à cela, y compris moi-même. Par exemple, cette requête n'arrive pas au serveur comme prévu via axios, mais si j'envoie le même fichier via Postman en tant que multipart/form-data , tout fonctionne.

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

Edit: Mon problème était d'essayer d'envoyer un data-uri encodé en base64 en tant que form-data. Si quelqu'un d'autre rencontre le même problème, voici un exemple de code pour le convertir :

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

Hé, je fais référence à ce document :- https://www.eztexting.com/developers/sms-api-documentation/rest#Sending
quel document faites-vous référence pour la clé API et tout ?

@ Ruchi2729
Désolé, j'ai confondu avec Nexmo, qui est un autre service SMS et a son propre client pour le nœud 😅

Mais de toute façon, selon la documentation à laquelle vous vous êtes référé , vous pouvez éviter FormData en définissant format sur json et laissez axios envoyer une charge utile JSON (vous pouvez le laisser deviner implicitement les en-têtes par le format de charge utile)

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

J'ai lutté avec cela beaucoup plus longtemps que je veux l'admettre, alors j'espère que cela aidera quelqu'un. J'utilise axios, express et express-fileupload. Je peux télécharger avec succès sur Node avec les paramètres que j'ai ajoutés au FormData. Je récupère les fichiers avec req.files et je récupère le reste des données du formulaire avec req.body['yourfilename']

Serveur (Express):

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

Résultat:

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

J'ai le même problème, je peux voir que j'ai réussi à envoyer les données du fichier avec mes outils de développement mais à l'intérieur de mon contrôleur mon $request->file('file') est vide
Mon composant

soumettre le formulaire() {
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((erreur) => console.log(erreur))
},

J'ai trouvé que faire quoi que ce soit avec FormData était un problème, puisque MVC ne semble pas aimer obtenir quoi que ce soit de cette façon, car vous devez spécifier le Content-Type comme multipart/form-data et il lançait une exception quand je le ferais vérifiez if (!Request.Content.IsMimeMultipartContent()) { throw new HttpResponseException(HttpStatusCode.UnsupportedMediaType); } , comme le dit le site de Microsoft : https://docs.microsoft.com/en-us/aspnet/web-api/overview/advanced/sending-html-form-data-part- 2

Était mieux juste pour mettre mon fichier dans une chaîne base64:
https://stackoverflow.com/questions/37134433/convert-input-file-to-byte-array/49676679#49676679

Ce message pourrait être plus pertinent pour savoir comment procéder, car j'ai utilisé une DropZone dans cet exemple :
https://stackoverflow.com/questions/32556664/getting-byte-array-through-input-type-file/49660172#49660172

Et je vais plus en détail là-dessus, ici: https://stackoverflow.com/questions/47574218/converting-from-blob-to-binary-to-save-it-to-mongodb/49660839#49660839

Ensuite, je pourrais créer un objet JSON :

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

Au lieu d'utiliser axios, j'ai juste utilisé un XMLHttpRequest.

 const xhr = new XMLHttpRequest();

Et ouvrez et définissez l'en-tête :

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

J'ai défini le onreadystatechange pour capturer la réponse :

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

et envoyer:

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

Si vous utilisez axios, ce serait probablement :

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

Du côté MVC, vous avez besoin d'un modèle correspondant :

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

puis ayez cela comme paramètre dans votre appel Post avec une balise [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 }));
}

Vous devriez récupérer ce que vous avez envoyé. Notez que si vous implémentez cela en tant que test, faites-le avec un très petit fichier, afin que vous n'attendiez pas indéfiniment avec le potentiel de verrouiller le navigateur/la mémoire de votre système.

@marinejax2
Je faisais comme vous l'avez dit, cela fonctionnait avec un petit fichier mais j'ai besoin d'envoyer un fichier volumineux (> 250 Mo), et oui, cela bloquait mon navigateur

Oui, pour cela, vous voudrez peut-être diviser le tableau de fichiers en morceaux d'une taille gérable et envoyer des blocs, en ayant une méthode à l'autre extrémité (côté serveur) qui peut les recombiner, et en lui donnant un paramètre pour qu'il sait de quel morceau il s'agit (1er, 2e, 3e, etc.) et combien de morceaux au total attendre avant de traiter le fichier côté serveur. Mais je pense que peu importe ce que vous faites, avec un fichier de cette taille, vous devrez attendre qu'il fasse son travail. Il faudra faire attention à la gestion de la mémoire si vous le faites également, car vous devrez vous assurer que vous effacez ou réutilisez vos variables à chaque fois et que vous ne réinstanciez pas de nouvelles versions des mêmes variables à chaque fois. vous faites un bloc. Une des rares fois où une variable globale est bonne - ou simplement définie sur un champ de modèle à chaque exécution.

Je suis d'accord avec @epferrari , veuillez envisager de rouvrir ce problème.
Il est possible d'envoyer une chaîne base64 avec FormData en chrome, mais vous ne pouvez tout simplement pas le faire avec axios dans node (v8.9.3).
Et ça marche avec 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)

=== mise à jour ===
Je ne comprends pas, j'utilise les mêmes en-têtes pour node-fetch et axios, et il semble qu'ils publient les mêmes données de formulaire sur le serveur, comment se fait-il qu'ils finissent différemment?
Au fait, la vraie URL que je poste vient de here , ce que je fais est de simuler la requête http du navigateur avec nodejs, pour envoyer une image au serveur et obtenir un lien en retour.

J'ai contourné cela en utilisant:

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

cela a fonctionné:

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

J'ai le même problème

ne fonctionne pas avec golang

Il suffit de trouver un moyen simple dans Vue, mais je pense qu'il peut être utilisé dans d'autres situations.😀
Back-end : Express.js et le package 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

Même nous étions confrontés au même problème. L'en-tête content -type a été supprimé du script java de réaction, puis cela a bien fonctionné. Auparavant, la limite n'était pas configurée lorsque vous la définissiez explicitement dans le type de contenu

EDIT : Après avoir lu plus à ce sujet, il semble qu'Express était le problème de mon côté. Espérons que cela puisse servir à d'autres

Même problème ici. @nickuraltsev recommande FORTEMENT de rouvrir le problème.

J'essaie de publier un fichier sur mon serveur de nœud via axios en utilisant le code suivant :

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

Le corps de la requête est complètement vide côté serveur

J'ai essayé d'envoyer le fichier directement, de lire le fichier en tant que ArrayBuffer et de lire le fichier en tant que texte (charge utile trop volumineuse cependant) et les 3 n'ont pas fonctionné.

Deux ans plus tard :
Même problème...

@demeter-macik merci, l'ajout de limite a fonctionné pour moi :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}`,
      },
    });

Cela fonctionne définitivement pour moi - tous les navigateurs, y compris Safari iOS.

Mon code ressemble à ceci :

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



    })

} ;

// appelle samplePost pour téléverser

exemplePost({

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]
Envoyé : mardi 11 septembre 2018 11:23
À : axios/axios [email protected]
Cc : DavidRueter [email protected] ; Commentaire [email protected]
Objet : Re : [axios/axios] Impossible d'obtenir un .post avec 'Content-Type' : 'multipart/form-data' (#318)

4 heures et comptant pour faire une demande de publication depuis Safari. Ça ne se passe toujours pas... que diable les gars ??

Aucune des solutions ici n'a fonctionné pour moi... :(


Vous recevez ceci parce que vous avez commenté.
Répondez directement à cet e-mail, consultez-le sur GitHub https://github.com/axios/axios/issues/318#issuecomment-420371510 ou désactivez le fil https://github.com/notifications/unsubscribe-auth/AFbi6JQBv06LTwL4z3HIAlvXAXDyps1- ks5uZ_9wgaJpZM4Ibm_z . https://github.com/notifications/beacon/AFbi6BSPfwPvNaWPFSdvtLKRYXS1m4uKks5uZ_9wgaJpZM4Ibm_z.gif

cela a fonctionné pour moi aussi, merci @arvi

twiliosms = async (Codigo) => {

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

var form = new FormData();
form.append('À', '+524772773737');
form.append('De', '+737373737');
form.append('Corps', Codigo);

essayer {
soit axapi = attendre axios(
{
URL : '2010-04-01/Accounts/AC8aa53c907943af79234414bb725c2cd3/Messages.json',
URL de base : 'https://api.twilio.com',
en-têtes : {'content-type' : multipart/form-data; boundary=${form._boundary} ,},
données : formulaire,
authentification : {
nom d'utilisateur : 'AC8aa53c907943af79234414bb725c2cd3',
mot de passe : * ,
},
méthode : 'post',
}
)

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

J'erre dans cette bibliothèque qui nécessite toujours des solutions de contournement auto-écrites pour les publications de données de formulaire ....

Toute mise à jour?

J'ai une erreur similaire dans NodeJS 10.11.0 et Axios 0.18.0 (voir #1892). J'ai essayé le correctif de @arvi mais cela ne fonctionne pas.

pour moi, cela fonctionne:

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

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

et cela ne fonctionnera pas

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

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

sachez que le format du paramètre postdata doit être (url , FormData) , et non (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()

        });
});

J'ai le même problème. Réception d'un 404 sans erreur. Utilisation formidable pour l'analyseur de formulaire, express et axios.

Je ne sais pas si cela aide quelqu'un, mais je ne voyais ce problème que sur Safari et je l'ai résolu en utilisant formdata-polyfill . Safari devrait prendre en charge FormData.append() nativement mais peut-être que l'implémentation est légèrement différente ?

EDIT : je me suis trompé : j'utilisais une URL créée à partir d'un blob. Une fois que j'ai commencé à utiliser le bon blob, tout a fonctionné comme un charme!

J'ai le même problème avec Blob alors que je peux télécharger File. La conversion de Blob en fichier est simple mais j'aimerais savoir s'il s'agit d'un bogue ou si j'ai mal interprété la syntaxe :

`` 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': text/plain`,
},
})

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
Contenu-Disposition : formulaire-données ; nom="blob"

------WebKitFormBoundarytmInU7WtcHvmgYbc
Contenu-Disposition : formulaire-données ; nom="fichier" ; nom de fichier="dscn2950.jpg"
Type de contenu : image/jpeg

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

```
Selon la documentation mozilla formData.append, il semble que je pourrais utiliser des objets Blob.

Ce qui m'a bloqué, c'est que mon serveur ne gérait pas correctement les fichiers, en utilisant https://www.npmjs.com/package/multer l'a corrigé

ça m'est utile ! Merci!

Rien ici n'a fonctionné pour moi car mon code était parfaitement bon.
Le vrai problème était avec le fichier que je faisais glisser à partir des résultats de recherche Windows - Chrome n'a pas pu trouver l'emplacement réel et il a cassé l'ensemble de l'analyse FormData. Naviguer vers le fichier et le faire glisser a résolu le problème.

Salut tout le monde,
Aidez-moi, s'il vous plaît.

POST https://www.googleapis.com/upload/drive/v3/files?uploadType=multipart HTTP/1.1
Autorisation : Porteur [YOUR_AUTH_TOKEN]
Type de contenu : multipart/connexe ; frontière=foo_bar_baz
Longueur du contenu : [NUMBER_OF_BYTES_IN_ENTIRE_REQUEST_BODY]

--foo_bar_baz
Type de contenu : application/json ; jeu de caractères=UTF-8

{
"nom": "monObjet"
}

--foo_bar_baz
Type de contenu : image/jpeg

[JPEG_DATA]
--foo_bar_baz--

axios ne prend pas en charge le type de requête multipart/liée

Pour moi, c'était (je suppose) avaler. Parce que j'obtenais l'erreur avec des fichiers minifiés sur mon serveur. J'ai tout supprimé manuellement du dossier dist, laissé le type de contenu indéfini et tout fonctionne comme prévu.
Donc, vous aurez qc comme :

formdata.append("selectPaymentType", $scope.extraFields.selectPaymentType);
formdata.append("pickupMethod", $scope.extraFields.selectPickupType);
laisser requête = {
méthode : 'POST',
URL : baseURL + 'commandes',
données : données de formulaire,
en-têtes : {
'Content-Type' : non défini,
'x-access-token' : $scope.userToken
}
} ;
$http(demande)
.succès(fonction (d) { })
.error(fonction () { });

PS : Ceci est un extrait... Je joins également des fichiers et beaucoup plus de champs...

SERVEUR:

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

form.parse(req, function(err, champs, fichiers) {
//VOTRE CODE ICI
})

salut svp j'ai besoin d'aide : j'ai eu "fichier : cette valeur ne doit pas être vide." quand j'essaie de récupérer une image en utilisant 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)); } constructeur(accessoires) {
super (accessoires);

this.state = {

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

}

}
```

Pour n'importe qui, cela a fonctionné pour moi.
Si vous utilisez un fichier d'entrée, vous devez utiliser MULTER dans votre router.post('/') comme un middleware, avant d'obtenir les autres champs d'entrée.

vérifiez votre axios.create, ces en-têtes devraient "headers:{}" et ne pas utiliser data.like ceci :
var instance = axios.create({
en-têtes : {
// 'Content-Type' : 'application/x-www-form-urlencoded;charset=UTF-8',
},
// Les données: {},
paramètres : {}
});

À ce jour, cela ne fonctionne pas sur nodejs. L'approche request-promise a également fonctionné pour moi.

J'ai passé 2 jours à essayer de faire fonctionner cela avec axios dans nodejs. J'ai passé 30 secondes à le faire fonctionner avec request-promise dans nodejs.

J'ai essayé différentes solutions mais j'ai finalement résolu ce problème en ajoutant les en-têtes :

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 Oui. Oui. Oui.

J'ai passé une demi-journée à déterminer si cela était lié à la configuration du client ou du serveur.
À la fin, headers: form.getHeaders() a fait l'affaire.

Déplacé vers got parce que ça _fonctionne_ juste avec formData et multipart/form-data - https://github.com/sindresorhus/got 🙌
Proche, mais pas de cigare 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)
  }

Vous pouvez le faire de cette façon :
handleSubmit = (e : tout) => {
e.preventDefault();
données constantes = new FormData();
data.append('product_csv', this.state.csvfile);
laissez accessToken = localStorage.getItem('access_token');
axios
.post('/upload', données,
{ en-têtes :
{ 'Content-Type' : 'multipart/form-data', Autorisation : accessToken }
})
.then(res => {
console.log('res', res);
});
} ;

@Googrosh Brilliant, .getHeaders() l'a fait fonctionner pour moi aussi. Je ne peux pas vous dire combien d'heures j'ai passé dessus. Merci!

J'utilise react-native. Et j'ai fini ce problème en utilisant rn-fetch-blob . Dommage :(

J'ai le même problème, cela ne fonctionne tout simplement pas avec un simple FormData sans aucun fichier et .getHeaders() n'aide pas. Déplacé vers "got" lib qui fonctionne. Mentionné ici aussi https://github.com/form-data/form-data/issues/458 (j'utilise Node v12)

Façon de faire ES6 2020

Ayant le formulaire en html, j'ai lié des données comme ceci:

LES DONNÉES:

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

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

Côté réception, si vous utilisez Express, vous avez besoin de multer . body-parser ne gère pas l'analyse des requêtes en plusieurs parties.

@DespertaWeb Cela ne fonctionne pas lorsqu'il n'y a pas de fichiers.

Cette page vous a été utile?
0 / 5 - 0 notes

Questions connexes

StefH picture StefH  ·  3Commentaires

Spartano picture Spartano  ·  3Commentaires

altruisticsoftware picture altruisticsoftware  ·  3Commentaires

c0debreaker picture c0debreaker  ·  3Commentaires

reggi picture reggi  ·  3Commentaires