Maison > interface Web > js tutoriel > Conversion de FormData en une chaîne multipart/form-data et inversement à l'aide de la réponse

Conversion de FormData en une chaîne multipart/form-data et inversement à l'aide de la réponse

DDD
Libérer: 2024-12-08 18:46:12
original
366 Les gens l'ont consulté

Converting FormData to a multipart/form-data String and Back Using Response

En travaillant sur un autre article sur la conversion de diverses valeurs en ReadableStream, je suis tombé sur une astuce intéressante pour convertir FormData en une chaîne de données multipart/form et inversement en utilisant la réponse. Étonnamment, FormData ne fournit pas cette fonctionnalité par défaut. Cependant, en tirant parti des méthodes de réponse, nous pouvons y parvenir assez facilement.

J'ai même essayé d'obtenir de l'aide de ChatGPT (4o et o1-preview), mais il n'a pas pu suggérer ou synthétiser cette solution, même avec des indices. Les recherches Google n'ont donné aucun résultat non plus. Il semble que cette approche soit méconnue ou peu connue, même si je ne revendique pas son originalité. Je ne pense pas que la possibilité d'une telle conversion ait été intentionnellement conçue par les auteurs de l'API Response ; il s'agit plutôt d'un effet secondaire, ce qui rend la solution encore plus intéressante. J'ai donc décidé d'écrire cet article pour partager mes découvertes.

Conversion de FormData en une chaîne Multipart/Form-Data

Supposons que nous ayons une instance de FormData :

const formData = new FormData();
formData.set('value', 123);
formData.set(
  'myfile',
  new File(['{"hello":"world"}'], 'demo.json', { type: 'application/json' })
);
Copier après la connexion

Notre objectif est d'obtenir une chaîne multipart/form-data à partir de cette instance FormData. Les suggestions courantes impliquent la sérialisation manuelle de FormData dans une chaîne ou l'exécution de manipulations complexes via Request, ou l'utilisation d'une bibliothèque pour cela. Cependant, nous pouvons simplement utiliser le constructeur Response, qui accepte FormData comme corps, puis appeler sa méthode text() pour obtenir la représentation sous forme de chaîne souhaitée :

// FormData -> multipart/form-data string
function convertFormDataToMultipartString(formData) {
  return new Response(formData).text();
}

const multipartString = await convertFormDataToMultipartString(formData);

console.log(multipartString);
// Example output:
// ------WebKitFormBoundaryQi7NBNu0nAmyAhpU
// Content-Disposition: form-data; name="value"
//
// 123
// ------WebKitFormBoundaryQi7NBNu0nAmyAhpU
// Content-Disposition: form-data; name="myfile"; filename="demo.json"
// Content-Type: application/json
//
// {"hello":"world"}
// ------WebKitFormBoundaryQi7NBNu0nAmyAhpU--
Copier après la connexion

Si nécessaire, nous pouvons également extraire des valeurs supplémentaires comme l'en-tête Content-Type et la limite :

// FormData -> multipart/form-data
async function convertFormDataToMultipart(formData) {
  const response = new Response(formData);
  const contentType = response.headers.get('Content-Type');
  const boundary = contentType.match(/boundary=(\S+)/)[1];

  return {
    contentType,
    boundary,
    body: await response.text(),
  };
}

const multipart = await convertFormDataToMultipart(formData);

console.log(multipart);
// {
//   contentType: 'multipart/form-data; boundary=----WebKitFormBoundarybfJIH5LgEGPqNcqt',
//   boundary: '----WebKitFormBoundarybfJIH5LgEGPqNcqt',
//   body: '------WebKitFormBoundarybfJIH5LgEGPqNcqt\r\n...'
// }
Copier après la connexion

Au lieu d'utiliser text(), nous pouvons également utiliser d'autres méthodes comme arrayBuffer() pour obtenir le contenu codé de FormData sous forme d'ArrayBuffer. L'avantage de ce type de valeur est qu'il s'agit d'un objet transférable et peut être transféré efficacement entre les travailleurs en utilisant postMessage() (c'est-à-dire sans copier, contrairement à une chaîne). L'objet FormData lui-même n'est pas transférable.

Conversion de la chaîne Multipart/Form-Data en FormData

Pour inverser le processus, nous utilisons à nouveau Response, mais cette fois nous utilisons sa méthode formData(). Un aspect clé de cette méthode est qu'elle nécessite l'en-tête Content-Type correct, qui doit inclure le type multipart/form-data et la limite utilisée pour séparer les parties. Si nous avons la valeur limite, nous pouvons l'insérer dans l'en-tête. Cependant, nous pourrions n’avoir que la chaîne en plusieurs parties et rien d’autre. Dans ce cas, nous pouvons extraire la limite de la chaîne à l'aide d'une expression régulière.

// multipart/form-data string -> FormData
async function convertMultipartStringToFormData(multipartString) {
  const boundary = multipartString.match(/^\s*--(\S+)/)[1];

  return new Response(multipartString, {
    headers: {
      // Without the correct header, the string won't be parsed,
      // and an exception will be thrown on formData() call
      'Content-Type': 'multipart/form-data; boundary=' + boundary,
    },
  }).formData();
}

const restoredFormData = await convertMultipartStringToFormData(multipartString);

console.log([...restoredFormData]);
// [
//   ['value', '123'],
//   ['myfile', File]
// ]
Copier après la connexion

Tout comme pour la sérialisation de FormData, nous pouvons convertir non seulement les chaînes mais également ArrayBuffer, TypedArray et ReadableStream en FormData, puisque Response accepte des valeurs telles que la valeur du corps.

Conclusion

Un inconvénient potentiel est que les deux types de conversions sont des opérations asynchrones. En dehors de cela, la méthode semble assez fiable et peut être utilisée pour le débogage ou lorsqu'une conversion est nécessaire en dehors de fetch().

Cette méthode est largement prise en charge par les navigateurs (elle devrait fonctionner dans n'importe quel navigateur publié après 2017). La méthode est également applicable dans Node.js, Deno et Bun s'ils prennent en charge l'objet Response (c'est-à-dire les versions où fetch() est disponible).

J'espère que vous trouverez cette approche aussi intrigante que moi. Il s'agit d'un moyen simple mais efficace de convertir FormData en une chaîne de données multipart/form (et pas seulement une chaîne) et inversement, en tirant parti des capacités de l'API Response. Si vous avez des idées ou connaissez d'autres méthodes pour obtenir le même résultat, n'hésitez pas à les partager dans les commentaires !

Ce qui précède est le contenu détaillé de. pour plus d'informations, suivez d'autres articles connexes sur le site Web de PHP en chinois!

source:dev.to
Déclaration de ce site Web
Le contenu de cet article est volontairement contribué par les internautes et les droits d'auteur appartiennent à l'auteur original. Ce site n'assume aucune responsabilité légale correspondante. Si vous trouvez un contenu suspecté de plagiat ou de contrefaçon, veuillez contacter admin@php.cn
Tutoriels populaires
Plus>
Derniers téléchargements
Plus>
effets Web
Code source du site Web
Matériel du site Web
Modèle frontal