etc./StackOverFlow

application/x-www-form-urlencoded 또는 multipart/form-data?

청렴결백한 만능 재주꾼 2022. 3. 22. 11:03
반응형

질문자 :max


HTTP에는 데이터를 POST하는 두 가지 방법이 있습니다: application/x-www-form-urlencodedmultipart/form-data . multipart/form-data 를 사용하는 경우에만 파일을 업로드할 수 있다는 것을 알고 있습니다. API 컨텍스트(브라우저 관련 없음)에서 인코딩 유형 중 하나를 사용할 때 추가 지침이 있습니까? 이것은 예를 들어 다음을 기반으로 할 수 있습니다.

  • 데이터 크기
  • ASCII가 아닌 문자의 존재
  • (인코딩되지 않은) 이진 데이터에 존재
  • 추가 데이터를 전송해야 하는 경우(예: 파일 이름)

나는 기본적으로 지금까지 다양한 콘텐츠 유형의 사용과 관련하여 웹에서 공식적인 지침을 찾지 못했습니다.



TL;DR

요약; 전송할 바이너리(영숫자가 아닌) 데이터(또는 상당한 크기의 페이로드)가 있는 경우 multipart/form-data . 그렇지 않으면 application/x-www-form-urlencoded .


언급한 MIME 유형은 사용자 에이전트(브라우저)가 지원해야 하는 HTTP POST 요청에 대한 Content-Type 이러한 두 가지 유형의 요청의 목적은 이름/값 쌍 목록을 서버로 보내는 것입니다. 전송되는 데이터의 유형과 양에 따라 방법 중 하나가 다른 방법보다 더 효율적입니다. 그 이유를 이해하려면 각자가 아래에서 무엇을 하고 있는지 살펴봐야 합니다.

application/x-www-form-urlencoded 경우 서버로 전송되는 HTTP 메시지의 본문은 본질적으로 하나의 거대한 쿼리 문자열입니다. 이름/값 쌍은 앰퍼샌드( & )로 구분되고 이름은 같음 기호( = ). 이에 대한 예는 다음과 같습니다.

MyVariableOne=ValueOne&MyVariableTwo=ValueTwo

사양 에 따르면:

[예약 및] 영숫자가 아닌 문자는 '%HH', 퍼센트 기호 및 문자의 ASCII 코드를 나타내는 두 개의 16진수로 대체됩니다.

즉, 값 중 하나에 존재하는 영숫자가 아닌 각 바이트를 나타내는 데 3바이트가 필요합니다. 대용량 바이너리 파일의 경우 페이로드를 3배로 늘리는 것은 매우 비효율적입니다.

이것이 multipart/form-data 가 들어오는 곳입니다. 이름/값 쌍을 전송하는 이 방법을 사용하면 각 쌍은 MIME 메시지에서 "부분"으로 표시됩니다(다른 답변에서 설명). 부분은 특정 문자열 경계로 구분됩니다(특히 이 경계 문자열이 "값" 페이로드에서 발생하지 않도록 선택됨). Content-Type 과 같은 자체 MIME 헤더 세트가 있으며 특히 Content-Disposition 은 각 부분에 "이름"을 제공할 수 있습니다. 각 이름/값 쌍의 값 조각은 MIME 메시지의 각 부분에 대한 페이로드입니다. MIME 사양은 값 페이로드를 나타낼 때 더 많은 옵션을 제공합니다. 대역폭을 절약하기 위해 바이너리 데이터의 보다 효율적인 인코딩을 선택할 수 있습니다(예: 기본 64 또는 원시 바이너리).

multipart/form-data 사용하지 않습니까? 대부분의 웹 양식과 같이 짧은 영숫자 값의 경우 모든 MIME 헤더를 추가하는 오버헤드가 보다 효율적인 이진 인코딩으로 절약할 수 있는 비용보다 훨씬 큽니다.


Matt Bridges

여기에서 최소한 첫 번째 단락을 읽으십시오!

나는 이것이 3년이나 늦었다는 것을 알고 있지만 Matt의 (수락된) 대답은 불완전하며 결국 당신을 곤경에 빠뜨릴 것입니다. 당신이 사용하도록 선택할 경우 키 여기에, 그것을이다 multipart/form-data 경계해야 서버가 결국 수신하는 파일 데이터에 나타나지 않습니다.

이것은 application/x-www-form-urlencoded 에서는 문제가 되지 않습니다. x-www-form-urlencoded 7BIT 바이트 3개로 바꾸는 간단한 방법으로 항상 이진 데이터를 처리할 수 있습니다. 비효율적이지만 작동합니다(파일 이름과 이진 데이터를 보낼 수 없다는 설명은 올바르지 않습니다. 다른 키/값 쌍으로 보내기만 하면 됩니다).

multipart/form-data 의 문제는 파일 데이터에 경계 구분 기호가 없어야 한다는 것입니다( RFC 2388 참조; 섹션 5.2에는 이 문제를 방지하는 적절한 집계 MIME 유형이 없는 것에 대한 다소 구차한 변명이 포함되어 있습니다).

그래서, 첫눈에, multipart/form-data 바이너리하거나, 어떠한 파일 업로드에 값이 없음이다. 서버가 잘못된 장소에서 경계를 발견 할 것이다, 당신의 파일이 잘립니다, 또는 POST - 당신이 제대로 경계를 선택하지 않은 경우, 당신은 결국 일반 텍스트 또는 원시 바이너리를 전송하고 있는지, 문제가있는 실패합니다.

핵심은 선택한 경계 문자가 인코딩된 출력에 나타나지 않도록 인코딩과 경계를 선택하는 것입니다. 한 가지 간단한 해결책은 base64 를 사용하는 것입니다(원시 바이너리를 사용하지 마십시오). base64 에서는 3개의 임의 바이트가 4개의 7비트 문자로 인코딩되며, 여기서 출력 문자 세트는 [A-Za-z0-9+/=] (즉, 영숫자, '+', '/' 또는 '=')입니다. = = 또는 이중 == 로 인코딩된 출력의 끝에만 나타날 수 있습니다. base64 출력에 나타날 수 없는 7비트 ASCII 문자열로 선택하십시오. 인터넷에서 볼 수 있는 많은 선택이 이 테스트에 실패합니다. 예를 들어 MDN 형식 문서 는 이진 데이터를 보낼 때 경계로 "blob"을 사용합니다. 좋지 않습니다. 그러나 "!blob!" base64 출력에는 절대 나타나지 않습니다.


EML

HTTP가 multipart 또는 x-www-form-urlencoded의 POST로 제한되어 있다고 생각하지 않습니다. Content-Type Header 는 HTTP POST 메소드와 직교합니다(자신에게 맞는 MIME 유형을 채울 수 있습니다). 이것은 또한 일반적인 HTML 표현 기반 웹앱의 경우이기도 합니다(예: json 페이로드는 ajax 요청에 대한 페이로드를 전송하는 데 매우 유명해졌습니다).

HTTP를 통한 Restful API와 관련하여 내가 접한 가장 인기 있는 콘텐츠 유형은 application/xml 및 application/json입니다.

애플리케이션/xml:

  • data-size: XML은 매우 장황하지만 압축을 사용하고 쓰기 액세스 사례(예: POST 또는 PUT을 통한)가 읽기 액세스보다 훨씬 더 드물다고 생각할 때 일반적으로 문제가 되지 않습니다(많은 경우 모든 트래픽의 <3%). ). 쓰기 성능을 최적화해야 하는 경우는 거의 없습니다.
  • 비 ASCII 문자의 존재: utf-8을 XML의 인코딩으로 사용할 수 있습니다.
  • 바이너리 데이터의 존재: base64 인코딩을 사용해야 함
  • 파일 이름 데이터: 이 내부 필드를 XML로 캡슐화할 수 있습니다.

애플리케이션/json

  • data-size: XML보다 더 작고, 여전히 텍스트이지만 압축할 수 있습니다.
  • 비 ASCII 문자: json은 utf-8입니다.
  • 바이너리 데이터: base64( json-binary-question 참조 )
  • 파일 이름 데이터: json 내부에 자체 필드 섹션으로 캡슐화

자체 리소스로 바이너리 데이터

이진 데이터를 자체 자산/리소스로 나타내려고 합니다. 그것은 또 다른 호출을 추가하지만 물건을 더 잘 분리합니다. 예시 이미지:

POST /images Content-type: multipart/mixed; boundary="xxxx" ... multipart data 201 Created Location: http://imageserver.org/../foo.jpg  
POST /images Content-type: multipart/mixed; boundary="xxxx" ... multipart data 201 Created Location: http://imageserver.org/../foo.jpg

이후 리소스에서는 바이너리 리소스를 링크로 간단히 인라인할 수 있습니다.

<main-resource> ... <link href="http://imageserver.org/../foo.jpg"/> </main-resource>
<main-resource> ... <link href="http://imageserver.org/../foo.jpg"/> </main-resource>

manuel aldana

나는 Manuel이 말한 많은 부분에 동의합니다. 사실 그의 댓글은 이 URL을 참조합니다...

http://www.w3.org/TR/html401/interact/forms.html#h-17.13.4

... 다음을 명시합니다.

"application/x-www-form-urlencoded" 콘텐츠 유형은 ASCII가 아닌 문자가 포함된 대량의 이진 데이터 또는 텍스트를 보내는 데 비효율적입니다. "multipart/form-data" 콘텐츠 유형은 파일, 비ASCII 데이터 및 이진 데이터가 포함된 양식을 제출하는 데 사용해야 합니다.

그러나 나를 위해 그것은 도구/프레임워크 지원으로 귀결될 것입니다.

  • API 사용자가 앱을 구축하기 위해 어떤 도구와 프레임워크를 기대하십니까?
  • 한 방법을 다른 방법보다 선호하는 데 사용할 수 있는 프레임워크 또는 구성 요소가 있습니까?

사용자에 대한 명확한 아이디어와 그들이 API를 사용하는 방법을 알고 있다면 결정하는 데 도움이 될 것입니다. API 사용자를 위해 파일 업로드를 어렵게 만들면 사용자가 이동하고 지원하는 데 많은 시간을 할애하게 됩니다.

이에 대한 두 번째는 API 작성을 위한 도구 지원과 하나의 업로드 메커니즘을 다른 것보다 쉽게 수용할 수 있다는 것입니다.


Martin Peck

HTML5 캔버스 이미지 데이터 업로드에 대한 약간의 힌트:

canvas 요소에서 가져온 이미지를 서버에 업로드하는 데 문제가 있었습니다. 나는 적어도 한 시간 동안 고군분투했고 내 서버에 이미지를 올바르게 저장하지 못했습니다.

jQuery ajax 호출의 contentType application/x-www-form-urlencoded 모든 것이 올바른 방향으로 진행되었고 base64로 인코딩된 데이터가 올바르게 해석되어 이미지로 성공적으로 저장되었습니다.


누군가에게 도움이 될 수도 있습니다!


Torsten Barthel

Content-Type=x-www-urlencoded-form을 사용해야 하는 경우 FormDataCollection을 매개변수로 사용하지 마십시오. asp.net Core 2+에서 FormDataCollection에는 포맷터에 필요한 기본 생성자가 없습니다. 대신 IFormCollection을 사용하십시오.

 public IActionResult Search([FromForm]IFormCollection type) { return Ok(); }

jahansha

출처 : http:www.stackoverflow.com/questions/4007969/application-x-www-form-urlencoded-or-multipart-form-data

반응형