อะไรenctype='multipart/form-data'
หมายถึงในรูปแบบ HTML และเมื่อเราควรจะใช้มันได้หรือไม่
อะไรenctype='multipart/form-data'
หมายถึงในรูปแบบ HTML และเมื่อเราควรจะใช้มันได้หรือไม่
คำตอบ:
เมื่อคุณทำการร้องขอ POST คุณต้องเข้ารหัสข้อมูลที่เป็นเนื้อหาของคำขอในบางวิธี
รูปแบบ HTML มีวิธีการเข้ารหัสสามวิธี
application/x-www-form-urlencoded
(ค่าเริ่มต้น)multipart/form-data
text/plain
กำลังเพิ่มapplication/json
งาน แต่ก็ถูกทอดทิ้ง
(การเข้ารหัสอื่นเป็นไปได้กับคำขอ HTTP ที่สร้างขึ้นโดยใช้วิธีอื่นนอกเหนือจากการส่งแบบฟอร์ม HTML JSON เป็นรูปแบบทั่วไปสำหรับใช้กับบริการเว็บและบางส่วนยังคงใช้ SOAP)
รูปแบบเฉพาะนั้นไม่สำคัญสำหรับนักพัฒนาส่วนใหญ่ จุดสำคัญคือ:
text/plain
ไม่เคยใช้งานเมื่อคุณเขียนรหัสฝั่งไคลเอ็นต์:
multipart/form-data
เมื่อฟอร์มของคุณมี<input type="file">
องค์ประกอบใด ๆmultipart/form-data
หรือapplication/x-www-form-urlencoded
แต่application/x-www-form-urlencoded
จะมีประสิทธิภาพมากขึ้นเมื่อคุณเขียนรหัสฝั่งเซิร์ฟเวอร์:
ส่วนใหญ่ (เช่น Perl CGI->param
หรือของ$_POST
superglobal ของ PHP ) จะดูแลความแตกต่างให้คุณ ไม่ต้องพยายามแยกวิเคราะห์ข้อมูลดิบที่ได้รับจากเซิร์ฟเวอร์
บางครั้งคุณจะพบห้องสมุดที่ไม่สามารถจัดการกับทั้งสองรูปแบบ ไลบรารียอดนิยมของ Node.js สำหรับการจัดการข้อมูลฟอร์มคือbody-parserซึ่งไม่สามารถจัดการคำขอหลายส่วนได้ (แต่มีเอกสารซึ่งแนะนำทางเลือกบางอย่างที่สามารถทำได้)
หากคุณกำลังเขียน (หรือดีบัก) ไลบรารีสำหรับการแยกวิเคราะห์หรือสร้างข้อมูลดิบคุณต้องเริ่มกังวลเกี่ยวกับรูปแบบ คุณอาจต้องการทราบเกี่ยวกับเรื่องนี้เพื่อประโยชน์ของความสนใจ
application/x-www-form-urlencoded
จะมากหรือน้อยเหมือนสตริงการสืบค้นที่ส่วนท้ายของ URL
multipart/form-data
มีความซับซ้อนมากขึ้น แต่อนุญาตให้รวมไฟล์ทั้งหมดไว้ในข้อมูลได้ ตัวอย่างของผลที่สามารถพบได้ในHTML 4 สเปค
text/plain
ถูกนำเสนอโดย HTML 5 และมีประโยชน์สำหรับการดีบักเท่านั้น - จากข้อมูลจำเพาะ : พวกเขาไม่สามารถตีความได้อย่างน่าเชื่อถือโดยคอมพิวเตอร์ - และฉันยืนยันว่าคนอื่น ๆ รวมกับเครื่องมือ (เช่นแผงเครือข่ายในเครื่องมือนักพัฒนาของเบราว์เซอร์ส่วนใหญ่) จะดีกว่า สำหรับการที่).
เมื่อใดที่เราควรใช้
คำตอบของเควนตินเป็นขวา: การใช้งานmultipart/form-data
หากรูปแบบมีการอัปโหลดไฟล์และอย่างอื่นซึ่งเป็นค่าเริ่มต้นถ้าคุณไม่ใช้application/x-www-form-urlencoded
enctype
ผมกำลังจะไป:
มีสามความเป็นไปได้สำหรับenctype
:
application/x-www-form-urlencoded
multipart/form-data
(ข้อมูลจำเพาะจุดถึงRFC7578 )text/plain
. นี่คือ "คอมพิวเตอร์ไม่สามารถตีความได้อย่างน่าเชื่อถือ" ดังนั้นจึงไม่ควรใช้ในการผลิตและเราจะไม่ตรวจสอบเพิ่มเติมเมื่อคุณเห็นตัวอย่างของแต่ละวิธีมันจะเห็นได้ชัดว่ามันทำงานอย่างไรและเมื่อคุณควรใช้แต่ละวิธี
คุณสามารถสร้างตัวอย่างโดยใช้:
nc -l
หรือเซิร์ฟเวอร์ ECHO: เซิร์ฟเวอร์ทดสอบ HTTP ยอมรับการร้องขอ GET / POSTบันทึกฟอร์มเป็น.html
ไฟล์ขั้นต่ำ:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8"/>
<title>upload</title>
</head>
<body>
<form action="http://localhost:8000" method="post" enctype="multipart/form-data">
<p><input type="text" name="text1" value="text default">
<p><input type="text" name="text2" value="aωb">
<p><input type="file" name="file1">
<p><input type="file" name="file2">
<p><input type="file" name="file3">
<p><button type="submit">Submit</button>
</form>
</body>
</html>
เราตั้งค่าข้อความเริ่มต้นเป็นaωb
ซึ่งหมายความว่าaωb
เพราะω
เป็นU+03C9
ซึ่งเป็นไบต์61 CF 89 62
ใน UTF-8
สร้างไฟล์ที่จะอัพโหลด:
echo 'Content of a.txt.' > a.txt
echo '<!DOCTYPE html><title>Content of a.html.</title>' > a.html
# Binary file containing 4 bytes: 'a', 1, 2 and 'b'.
printf 'a\xCF\x89b' > binary
เรียกใช้เซิร์ฟเวอร์ echo เล็ก ๆ ของเรา:
while true; do printf '' | nc -l 8000 localhost; done
เปิด HTML บนเบราว์เซอร์ของคุณเลือกไฟล์และคลิกที่ส่งและตรวจสอบเทอร์มินัล
nc
พิมพ์คำขอที่ได้รับ
ทดสอบกับ: Ubuntu 14.04.3, nc
BSD 1.105, Firefox 40
ส่ง Firefox แล้ว:
POST / HTTP/1.1
[[ Less interesting headers ... ]]
Content-Type: multipart/form-data; boundary=---------------------------735323031399963166993862150
Content-Length: 834
-----------------------------735323031399963166993862150
Content-Disposition: form-data; name="text1"
text default
-----------------------------735323031399963166993862150
Content-Disposition: form-data; name="text2"
aωb
-----------------------------735323031399963166993862150
Content-Disposition: form-data; name="file1"; filename="a.txt"
Content-Type: text/plain
Content of a.txt.
-----------------------------735323031399963166993862150
Content-Disposition: form-data; name="file2"; filename="a.html"
Content-Type: text/html
<!DOCTYPE html><title>Content of a.html.</title>
-----------------------------735323031399963166993862150
Content-Disposition: form-data; name="file3"; filename="binary"
Content-Type: application/octet-stream
aωb
-----------------------------735323031399963166993862150--
สำหรับไฟล์ไบนารีและฟิลด์ข้อความไบต์61 CF 89 62
(เป็นaωb
UTF-8) จะถูกส่งไปตามตัวอักษร คุณสามารถตรวจสอบว่าด้วยnc -l localhost 8000 | hd
ซึ่งบอกว่าไบต์:
61 CF 89 62
ถูกส่งไป ( 61
== 'a' และ62
== 'b')
ดังนั้นจึงเป็นที่ชัดเจนว่า:
Content-Type: multipart/form-data; boundary=---------------------------735323031399963166993862150
กำหนดประเภทเนื้อหาเป็นmultipart/form-data
และบอกว่าเขตข้อมูลจะถูกคั่นด้วยboundary
สตริงที่กำหนด
แต่ทราบว่า:
boundary=---------------------------735323031399963166993862150
มีสอง dadhes น้อย--
กว่าอุปสรรคที่เกิดขึ้นจริง
-----------------------------735323031399963166993862150
--
เพราะนี่คือมาตรฐานต้องมีขอบเขตที่จะเริ่มต้นด้วยการขีดสองขีด เครื่องหมายขีดคั่นอื่น ๆ นั้นเป็นเพียงวิธีที่ Firefox เลือกใช้ขอบเขตโดยพลการ RFC 7578 ระบุอย่างชัดเจนว่า--
จำเป็นต้องมีขีดกลางสองอันดังกล่าว:
4.1 พารามิเตอร์ "ขอบเขต" ของหลายส่วน / แบบฟอร์มข้อมูล
เช่นเดียวกับชนิดหลายส่วนอื่น ๆ ชิ้นส่วนจะถูกคั่นด้วยตัวคั่นขอบเขตสร้างโดยใช้ CRLF, "-" และค่าของพารามิเตอร์ "ขอบเขต"
ทุกสาขาจะได้รับส่วนหัวย่อยบางอย่างก่อนที่ข้อมูลที่: Content-Disposition: form-data;
สนามname
ที่filename
ตามด้วยข้อมูล
เซิร์ฟเวอร์จะอ่านข้อมูลจนกว่าจะถึงสตริงขอบเขตถัดไป เบราว์เซอร์จะต้องเลือกขอบเขตที่จะไม่ปรากฏในฟิลด์ใด ๆ ดังนั้นนี่คือสาเหตุที่ขอบเขตอาจแตกต่างกันระหว่างคำขอ
เนื่องจากเรามีขอบเขตที่ไม่ซ้ำกันจึงไม่จำเป็นต้องเข้ารหัสข้อมูล: ส่งข้อมูลไบนารีตามที่เป็นอยู่
สิ่งที่ต้องทำ: ขนาดขอบเขตที่เหมาะสมที่สุด ( log(N)
ฉันเดิมพัน) คืออะไรและชื่อ / เวลาทำงานของอัลกอริทึมที่พบมันคืออะไร ถามได้ที่: /cs/39687/find-the-shortest-sequence-that-is-not-a-s--ub-sequent-of-a-set-of-sequences
Content-Type
ถูกกำหนดโดยเบราว์เซอร์โดยอัตโนมัติ
มันถูกกำหนดอย่างไรถูกถามอย่างถูกต้องที่: ประเภทไฟล์ mime ที่อัพโหลดโดยเบราว์เซอร์เป็นอย่างไร?
ตอนนี้เปลี่ยนenctype
ไปapplication/x-www-form-urlencoded
โหลดเบราว์เซอร์และส่งอีกครั้ง
ส่ง Firefox แล้ว:
POST / HTTP/1.1
[[ Less interesting headers ... ]]
Content-Type: application/x-www-form-urlencoded
Content-Length: 51
text1=text+default&text2=a%CF%89b&file1=a.txt&file2=a.html&file3=binary
เห็นได้ชัดว่าข้อมูลไฟล์ไม่ได้ถูกส่ง แต่เป็นเพียงชื่อไฟล์ ดังนั้นจึงไม่สามารถใช้ไฟล์นี้ได้
สำหรับฟิลด์ข้อความเราจะเห็นว่าตัวอักษรที่พิมพ์ได้ปกติเหมือนa
และb
ถูกส่งไปในหนึ่งไบต์ในขณะที่ตัวอักษรที่ไม่สามารถพิมพ์ได้เช่นนั้น0xCF
และ0x89
เพิ่มขึ้น3 ไบต์แต่ละตัว: %CF%89
!
การอัปโหลดไฟล์มักจะมีอักขระที่ไม่สามารถพิมพ์ได้จำนวนมาก (เช่นรูปภาพ) ในขณะที่รูปแบบข้อความแทบจะไม่เคยทำเลย
จากตัวอย่างที่เราได้เห็นว่า:
multipart/form-data
: เพิ่มค่าใช้จ่ายขอบเขตจำนวนเล็กน้อยให้กับข้อความและต้องใช้เวลาในการคำนวณ แต่ส่งแต่ละไบต์เป็นหนึ่งไบต์
application/x-www-form-urlencoded
: มีขอบเขตไบต์เดียวต่อฟิลด์ ( &
) แต่เพิ่มตัวคูณค่าใช้จ่ายเชิงเส้นเป็น3xสำหรับอักขระที่ไม่สามารถพิมพ์ได้ทุกตัว
ดังนั้นแม้ว่าเราจะสามารถส่งไฟล์ได้application/x-www-form-urlencoded
เราก็ไม่ต้องการเพราะมันไม่มีประสิทธิภาพ
แต่สำหรับตัวอักษรที่พิมพ์ได้ที่พบในช่องข้อความมันไม่สำคัญและสร้างค่าใช้จ่ายน้อยลงดังนั้นเราจึงใช้มัน
%CF
คือ 3 ไบต์ยาว%
, C
และF
:-) เรื่องของการทำให้การอ่านของมนุษย์
nc
จะไม่ยอมรับทั้ง-l
และ-p
อาร์กิวเมนต์พร้อมกัน แต่สิ่งนี้ได้ผลกับฉัน: while true; do printf '' | nc -l 8000; done
.
Content-Type
มีสองยัติภังค์ ( --
) --
น้อยลงเช่นเมื่อใช้จริงเขตแดนในเนื้อหาของข้อความที่คุณจะต้องนำหน้าด้วย นอกจากนี้ขอบเขตสุดท้ายจะต้องต่อท้ายด้วย--
แต่ก็ง่ายที่จะสังเกตเห็น ดูstackoverflow.com/questions/3508252/…
enctype='multipart/form-data
เป็นประเภทที่ช่วยให้การเข้ารหัสไฟล์จะถูกส่งผ่านโพสต์ ค่อนข้างง่ายหากไม่มีการเข้ารหัสไฟล์จะไม่สามารถส่งผ่านPOSTได้
หากคุณต้องการที่จะช่วยให้ผู้ใช้สามารถอัปโหลดไฟล์ผ่านทางรูปแบบที่คุณต้องใช้นี้enctype
multipart/form-data
สำหรับการส่งไฟล์ที่ไม่ใช่ไบนารี แต่มันไม่มีประสิทธิภาพ ฉันเชื่อว่าการใช้application/x-www-form-urlencoded
เป็นวิธีที่ถูกต้องในการส่งข้อมูลที่ไม่ใช่ไบนารี แต่บางคนที่มีประสบการณ์เกี่ยวกับไฟล์ที่ไม่ใช่ไบนารีอาจต้องแก้ไขฉัน
multipart/form-data
สำหรับส่งไฟล์คือมันจะทำงานโดยอัตโนมัติทั้งในส่วนหน้าและส่วนหลัง คุณไม่ต้องทำอะไรเป็นพิเศษ ไฟล์ทั้งหมดเป็นไบนารีแม้ว่าพวกเขาควรจะมีข้อความเท่านั้น application/x-www-form-urlencoded
เป็นวิธีมาตรฐานในการโพสต์รูปแบบโดยไม่ต้องแนบไฟล์ multipart/form-data
เป็นวิธีมาตรฐานในการโพสต์แบบฟอร์มพร้อมไฟล์ที่แนบมา (นอกจากนี้ยังมีการเข้ารหัสอื่น ๆ อีกมากมายเช่นapplication/json
และapplication/json-patch+json
ซึ่งเป็นเรื่องปกติสำหรับการสื่อสารระหว่างเซิร์ฟเวอร์และไคลเอนต์)
multipart/form-data
คุณอย่างสามารถส่งไฟล์ผ่านทางไปรษณีย์โดยไม่ต้องใช้ สิ่งที่คุณไม่สามารถทำได้คือใช้การส่งแบบฟอร์ม HTML ธรรมดาโดยไม่มี JavaScript การตั้งค่ารูปแบบที่จะใช้multipart/form-data
เป็นกลไกเดียวที่HTMLจัดเตรียมไว้ให้คุณใช้ไฟล์ POST โดยไม่ต้องใช้ JavaScript ฉันรู้สึกว่ามันไม่ชัดเจนในคำตอบและผู้อ่านที่ไร้เดียงสาอาจคิดว่าการไม่สามารถส่งไฟล์โดยไม่มีmultipart/form-data
ข้อ จำกัด ของHTTP ; นั่นไม่ใช่กรณี
เมื่อส่งแบบฟอร์มคุณจะบอกให้เบราว์เซอร์ของคุณส่งผ่านโปรโตคอล HTTP ข้อความบนเครือข่ายห่อหุ้มอย่างเหมาะสมในโครงสร้างข้อความโปรโตคอล TCP / IP หน้า HTML มีวิธีการส่งข้อมูลไปยังเซิร์ฟเวอร์: โดยใช้<form>
s
เมื่อส่งแบบฟอร์มคำขอ HTTP จะถูกสร้างและส่งไปยังเซิร์ฟเวอร์ข้อความจะมีชื่อฟิลด์ในแบบฟอร์มและค่าที่กรอกโดยผู้ใช้ ส่งนี้จะเกิดขึ้นกับPOST
หรือวิธีการGET
HTTP
POST
บอกเบราว์เซอร์ของคุณเพื่อสร้างข้อความ HTTP และใส่เนื้อหาทั้งหมดไว้ในเนื้อความของข้อความ (เป็นวิธีที่มีประโยชน์มากในการทำสิ่งต่าง ๆ ปลอดภัยและยืดหยุ่นได้มากขึ้น)GET
จะส่งข้อมูลแบบฟอร์มในสตริงการสืบค้น มีข้อ จำกัด บางประการเกี่ยวกับการแสดงข้อมูลและความยาวแอตทริบิวต์enctype
มีเหตุผลเมื่อใช้POST
วิธีการเท่านั้น เมื่อระบุจะสั่งให้เบราว์เซอร์ส่งแบบฟอร์มโดยการเข้ารหัสเนื้อหาในแบบเฉพาะ จากMDN - ประเภทฟอร์ม :
เมื่อค่าของวิธีการโพสต์แอตทริบิวต์ enctype เป็นประเภท MIME ของเนื้อหาที่ใช้ในการส่งแบบฟอร์มไปยังเซิร์ฟเวอร์
application/x-www-form-urlencoded
: นี่เป็นค่าเริ่มต้น เมื่อส่งแบบฟอร์มชื่อและค่าทั้งหมดจะถูกรวบรวมและการเข้ารหัส URLจะดำเนินการกับสตริงสุดท้ายmultipart/form-data
: อักขระจะไม่ถูกเข้ารหัส สิ่งนี้สำคัญเมื่อฟอร์มมีตัวควบคุมการอัปโหลดไฟล์ คุณต้องการส่งไฟล์ไบนารี่และสิ่งนี้ทำให้มั่นใจได้ว่าบิทสตรีมจะไม่เปลี่ยนแปลงtext/plain
: Spaces ได้รับการแปลง แต่จะไม่มีการเข้ารหัสอีกเมื่อส่งแบบฟอร์มความกังวลด้านความปลอดภัยบางอย่างอาจเกิดขึ้นตามที่ระบุไว้ในRFC 7578 ส่วนที่ 7: ข้อมูลแบบฟอร์มหลายส่วน - ข้อควรพิจารณาด้านความปลอดภัย :
ซอฟต์แวร์ประมวลผลแบบฟอร์มทั้งหมดควรปฏิบัติต่อข้อมูลฟอร์มผู้ใช้ที่ให้มา
ด้วยความไวเนื่องจากมักจะมีข้อมูลที่เป็นความลับหรือการ
ระบุตัวตน มีการใช้คุณสมบัติ "กรอกข้อมูลอัตโนมัติ" ในเว็บเบราว์เซอร์อย่างแพร่หลาย สิ่งเหล่านี้อาจถูกใช้เพื่อหลอกลวงผู้ใช้ให้
ส่งข้อมูลที่เป็นความลับโดยไม่รู้ตัวเมื่อ
ทำงานที่ไม่มีพิษภัยเป็นอย่างอื่น multipart / form-data ไม่ได้จัดหาฟีเจอร์ใด ๆ
สำหรับการตรวจสอบความสมบูรณ์ของการรับประกันความลับการหลีกเลี่ยง
ความสับสนของผู้ใช้หรือคุณลักษณะความปลอดภัยอื่น ๆ ข้อกังวลเหล่านั้นจะต้องได้รับการ
แก้ไขโดยแอปพลิเคชันการกรอกแบบฟอร์มและแบบฟอร์มการแปลข้อมูลแอปพลิเคชันที่ได้รับแบบฟอร์มและประมวลผลนั้นจะต้องระมัดระวังไม่ให้ข้อมูลกลับไปยังไซต์การประมวลผลแบบฟอร์มที่ร้องขอซึ่งไม่ได้ตั้งใจจะส่ง
สิ่งสำคัญคือเมื่อตีความชื่อไฟล์ของ
ฟิลด์ส่วนหัวของเนื้อหา - การจัดการเพื่อไม่ให้เขียนทับไฟล์ใน
พื้นที่ไฟล์ของผู้รับโดยไม่ตั้งใจ
สิ่งนี้เกี่ยวข้องกับคุณหากคุณเป็นนักพัฒนาซอฟต์แวร์และเซิร์ฟเวอร์ของคุณจะประมวลผลแบบฟอร์มที่ส่งโดยผู้ใช้ซึ่งอาจมีข้อมูลที่ละเอียดอ่อน
enctype
ทำ ฉันรู้ว่ามันอย่างแท้จริงจากmultipart/form-data
RFC แต่อย่างไรก็ตามมันเป็นการถ่ายโอนข้อมูลโดยพลการของการพิจารณาความปลอดภัยเกี่ยวกับการส่งรูปแบบที่มีฉากทั้งหมดให้กับว่าข้อมูลจะถูกส่งเป็นหรือapplication/x-www-form-urlencoded
multipart/form-data
enctype='multipart/form-data'
หมายความว่าจะไม่มีการเข้ารหัสอักขระ นั่นคือเหตุผลที่ใช้ชนิดนี้ในขณะอัพโหลดไฟล์ไปยังเซิร์ฟเวอร์
ดังนั้นmultipart/form-data
จะใช้เมื่อแบบฟอร์มต้องการข้อมูลไบนารีเช่นเนื้อหาของไฟล์ที่จะอัปโหลด
ตั้งค่าแอตทริบิวต์ method เป็น POST เนื่องจากไม่สามารถใส่เนื้อหาไฟล์ไว้ในพารามิเตอร์ URL โดยใช้แบบฟอร์ม
ตั้งค่าของ enctype เป็นหลายส่วน / form-data เนื่องจากข้อมูลจะถูกแบ่งออกเป็นหลายส่วนหนึ่งสำหรับแต่ละไฟล์บวกหนึ่งสำหรับข้อความของร่างกายแบบฟอร์มที่อาจส่งไปกับพวกเขา
POST
มีแนวโน้มว่าจะเพียงพอสำหรับการส่งไฟล์ผ่านแบบฟอร์มและการเพิ่มmultipart/form-data
เป็นเพียงโบนัสในทางที่คลุมเครือ นั่นไม่ใช่กรณี multipart/form-data
ไฟล์ส่วนใหญ่อย่างจะต้องใช้
<head>
และ<body>
ไม่เกี่ยวข้องและสับสน
โดยทั่วไปแล้วนี่คือเมื่อคุณมีแบบฟอร์ม POST ซึ่งจำเป็นต้องอัพโหลดไฟล์เป็นข้อมูล ... นี่จะบอกเซิร์ฟเวอร์ว่ามันจะเข้ารหัสข้อมูลที่ถ่ายโอนอย่างไรในกรณีนี้มันจะไม่ได้รับการเข้ารหัสเพราะมันจะถ่ายโอนและอัปโหลดเท่านั้น ไฟล์ไปยังเซิร์ฟเวอร์เช่นเช่นเมื่ออัปโหลดภาพหรือ PDF
คุณลักษณะ enctype ระบุวิธีการเข้ารหัสข้อมูลแบบฟอร์มเมื่อส่งไปยังเซิร์ฟเวอร์
แอตทริบิวต์ enctype สามารถใช้ได้เฉพาะถ้า method = "post"
ไม่มีการเข้ารหัสอักขระ จำเป็นต้องใช้ค่านี้เมื่อคุณใช้ฟอร์มที่มีการควบคุมการอัปโหลดไฟล์
จากW3Schools
multipart/form-data
คำพูดนี้ไม่ได้พูดถึง มันค่อนข้างชัดเจน ประโยค "ไม่มีการเข้ารหัสอักขระ" หมายความว่าอย่างไร -1