페치를 사용하여 멀티 파트 양식 데이터로 POST하려면 어떻게합니까?


90

다음과 같은 URL을 가져옵니다.

fetch(url, {
  mode: 'no-cors',
  method: method || null,
  headers: {
    'Accept': 'application/json, application/xml, text/plain, text/html, *.*',
    'Content-Type': 'multipart/form-data'
  },
  body: JSON.stringify(data) || null,
}).then(function(response) {
  console.log(response.status)
  console.log("response");
  console.log(response)
})

내 API는 데이터가 될 것으로 예상 하므로이 유형을 multipart/form-data사용 content-type하고 있지만 상태 코드 400으로 응답을 제공합니다.

내 코드에 어떤 문제가 있습니까?

답변:


176

당신은이 설정하는 Content-Type것으로 multipart/form-data,하지만 사용 JSON.stringify하는 반환 본문 데이터에 application/json. 콘텐츠 유형이 일치하지 않습니다.

multipart/form-data대신 데이터를 인코딩해야합니다 json. 일반적으로 multipart/form-data파일을 업로드 할 때 사용 application/x-www-form-urlencoded되며 HTML 양식의 기본값 인 것보다 약간 더 복잡 합니다.

사양 multipart/form-dataRFC 1867 에서 찾을 수 있습니다 .

자바 스크립트를 통해 이러한 종류의 데이터를 제출하는 방법에 대한 가이드는 여기를 참조 하세요 .

기본 아이디어는 FormData 객체 를 사용하는 것입니다 (IE <10에서는 지원되지 않음).

async function sendData(url, data) {
  const formData  = new FormData();

  for(const name in data) {
    formData.append(name, data[name]);
  }

  const response = await fetch(url, {
    method: 'POST',
    body: formData
  });

  // ...
}

이 문서 확인 하지 세트에 Content-Type헤더를. 브라우저가 boundary매개 변수를 포함하여이를 설정합니다 .


const fd = new FormData (); // 업로드 할 파일. fd.append ( 'file', fileToUpload); fd.append ( 'jsondatakey', 'jsondatavalue'); 이것으로 본문의 일부 json 데이터와 함께 파일을 보낼 수 있습니다.
Jnana

승인이 필요한 경우 어떻게합니까?
DAVE

26

나는 최근에 IPFS와 함께 일하고 있었고 이것을 해결했습니다. IPFS가 파일을 업로드하는 컬 예제는 다음과 같습니다.

curl -i -H "Content-Type: multipart/form-data; boundary=CUSTOM" -d $'--CUSTOM\r\nContent-Type: multipart/octet-stream\r\nContent-Disposition: file; filename="test"\r\n\r\nHello World!\n--CUSTOM--' "http://localhost:5001/api/v0/add"

기본적인 아이디어는 각 부분 (의 문자열로 분할한다는 것입니다 boundary과는 --) 그 자체 헤더있다 ( Content-Type예를 들어, 두 번째 부분에서하십시오.) FormData그것이 우리의 목표를 달성 할 수있는 더 좋은 방법이 그래서 개체가 당신을 위해 모든 것을 관리합니다.

이것은 다음과 같은 API를 가져 오는 것으로 변환됩니다.

const formData = new FormData()
formData.append('blob', new Blob(['Hello World!\n']), 'test')

fetch('http://localhost:5001/api/v0/add', {
  method: 'POST',
  body: formData
})
.then(r => r.json())
.then(data => {
  console.log(data)
})

17
위의 방법에 대해 참고하십시오. FormData를 사용하면 헤더를 제공하지 마십시오. 자동으로 설정되는 경계를 재정의하기 때문입니다.
Matt Pengelly

1
@MattPengelly 감사합니다! 승인과 같은 사용자 지정 헤더를 설정하는 방법은 무엇입니까?
Dragos Strugar

7
@DragosStrugar는 여전히 헤더를 설정할 수 있습니다 (인증 포함). FormData를 사용하는 경우 수동으로 Content-Type 헤더를 설정하지 마십시오.
RobertMcReed

3
FormData를 사용하는 경우 헤더에 'Content-Type'을 제공하지 마십시오.
caot

1
컬 예제에서는 필요합니다. FormData예제 에서는 브라우저가 해당 헤더를 전송하고이 솔루션의 핵심 인 모든 MIME 경계를 관리하기 때문에 필요하지 않습니다.
konsumer
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.