首頁 > web前端 > js教程 > 使用 Response 將 FormData 轉換為 multipart/form-data 字串並傳回

使用 Response 將 FormData 轉換為 multipart/form-data 字串並傳回

DDD
發布: 2024-12-08 18:46:12
原創
375 人瀏覽過

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

在撰寫另一篇有關將各種值轉換為ReadableStream 的文章時,我偶然發現了一個巧妙的技巧,可以將FormData 轉換為多部分/表單資料字串,然後使用Response 將其轉換回來。令人驚訝的是,FormData 並未立即提供此功能。然而,透過利用 Response 的方法,我們可以輕鬆實現這一點。

我甚至嘗試從 ChatGPT(4o 和 o1-preview)獲得幫助,但即使有提示,它也無法建議或綜合此解決方案。谷歌搜尋也沒有產生任何結果。儘管我不聲稱具有獨創性,但這種方法似乎是未知的或鮮為人知的。我不認為這種轉換的能力是 Response API 的作者有意設計的;它更多的是一個副作用,這使得解決方案更加有趣。因此,我決定寫這篇文章來分享我的發現。

將 FormData 轉換為多部分/表單資料字串

假設我們有一個 FormData 實例:

const formData = new FormData();
formData.set('value', 123);
formData.set(
  'myfile',
  new File(['{"hello":"world"}'], 'demo.json', { type: 'application/json' })
);
登入後複製

我們的目標是從此 FormData 實例取得 multipart/form-data 字串。常見的建議包括手動將 FormData 序列化為字串或透過 Request 執行複雜的操作,或使用函式庫。但是,我們可以簡單地使用 Response 建構函數,它接受 FormData 作為正文,然後呼叫其 text() 方法來取得所需的字串表示形式:

// 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--
登入後複製

如果需要,我們也可以提取其他值,例如 Content-Type 標頭和邊界:

// 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...'
// }
登入後複製

除了使用 text() 之外,我們還可以使用 arrayBuffer() 等其他方法來取得 FormData 的編碼內容作為 ArrayBuffer。這種類型的值的優點是它是一個可傳輸的對象,並且可以使用 postMessage() 在工作人員之間有效地傳輸(意味著無需複製,與字串不同)。 FormData 物件本身是不可轉讓的。

將多部分/表單資料字串轉換回 FormData

為了反轉這個過程,我們再次使用 Response,但這次我們使用它的 formData() 方法。此方法的一個關鍵方面是它需要正確的 Content-Type 標頭,其中必須包含 multipart/form-data 類型以及用於分隔各部分的邊界。如果我們有邊界值,我們可以將其插入到標頭中。但是,我們可能只有多部分字串而沒有其他內容。在這種情況下,我們可以使用正規表示式從字串中提取邊界。

// 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]
// ]
登入後複製

就像序列化 FormData 一樣,我們不僅可以將字串轉換為 FormData,還可以將 ArrayBuffer、TypedArray 和 ReadableStream 轉換為 FormData,因為 Response 接受此類值作為正文值。

結論

一個潛在的缺點是這兩種類型的轉換都是非同步操作。除此之外,該方法看起來相當可靠,可以用於調試或需要在 fetch() 之外進行轉換時。

此方法具有廣泛的瀏覽器支援(它應該適用於 2017 年之後發布的任何瀏覽器)。如果 Node.js、Deno 和 Bun 支援 Response 物件(即 fetch() 可用的版本),則該方法也適用於它們。

我希望您跟我一樣覺得這種方法很有趣。這是一種簡單而有效的方法,可利用 Response API 的功能將 FormData 轉換為多部分/表單資料字串(而不僅僅是字串)並傳回。如果您有任何想法或知道其他方法可以達到相同的結果,請隨時在評論中分享!

以上是使用 Response 將 FormData 轉換為 multipart/form-data 字串並傳回的詳細內容。更多資訊請關注PHP中文網其他相關文章!

來源:dev.to
本網站聲明
本文內容由網友自願投稿,版權歸原作者所有。本站不承擔相應的法律責任。如發現涉嫌抄襲或侵權的內容,請聯絡admin@php.cn
熱門教學
更多>
最新下載
更多>
網站特效
網站源碼
網站素材
前端模板