khi nào chúng ta nên sử dụng nó
Câu trả lời của Quentin là đúng: sử dụng multipart/form-datanếu biểu mẫu có chứa tệp tải lên và utility/x-www-form-urlencodednếu không, đó là mặc định nếu bạn bỏ qua enctype.
Tôi sẽ:
- thêm một số tài liệu tham khảo HTML5
- giải thích lý do tại sao anh ta đúng với một ví dụ gửi mẫu
Tài liệu tham khảo HTML5
Có ba khả năng cho enctype:
- utility/x-www-form-urlencoded
- multipart/form-data(thông số kỹ thuật chỉ ra RFC7578 )
- textual content/plain. Đây là “không đáng tin cậy bằng máy tính”, vì vậy nó không bao giờ nên được sử dụng trong sản xuất và chúng tôi sẽ không nhìn sâu hơn vào nó.
Cách tạo các ví dụ
Khi bạn thấy một ví dụ về mỗi phương thức, nó sẽ trở nên rõ ràng về cách chúng hoạt động và khi nào bạn nên sử dụng từng phương thức.
Bạn có thể tạo các ví dụ bằng cách sử dụng:
- nc -lhoặc máy chủ ECHO: Máy chủ thử nghiệm HTTP chấp nhận các yêu cầu GET / POST
- một tác nhân người dùng như trình duyệt hoặc cURL
Lưu biểu mẫu vào một .htmltệp tối thiểu :
<!DOCTYPE html> <html lang=”en”> <head> <meta charset=”utf-8″/> <title>add</title> </head> <physique> <kind motion=”http://localhost:8000″ technique=”submit” enctype=”multipart/form-data”> <p><enter sort=”textual content” title=”text1″ worth=”textual content default”> <p><enter sort=”textual content” title=”text2″ worth=”aωb”> <p><enter sort=”file” title=”file1″> <p><enter sort=”file” title=”file2″> <p><enter sort=”file” title=”file3″> <p><button sort=”submit”>Submit</button> </kind> </physique> </html>
Chúng tôi thiết lập các giá trị văn bản mặc định aωb, có nghĩa là aωbbởi vì ωlà U+03C9, đó là các byte 61 CF 89 62trong UTF-8.
Tạo tập tin để tải lên:
echo ‘Content material of a.txt.’ > a.txt echo ‘<!DOCTYPE html><title>Content material of a.html.</title>’ > a.html # Binary file containing 4 bytes: ‘a’, 1, 2 and ‘b’. printf ‘axCFx89b’ > binary
Chạy máy chủ echo nhỏ của chúng tôi:
whereas true; do printf ” | nc -l 8000 localhost; performed
Mở HTML trên trình duyệt của bạn, chọn các tệp và nhấp vào gửi và kiểm tra thiết bị đầu cuối.
nc in yêu cầu nhận được.
Đã thử nghiệm trên: Ubuntu 14.04.3, ncBSD 1.105, Firefox 40.
nhiều dữ liệu / biểu mẫu
Firefox đã gửi:
POST / HTTP/1.1 [[ Less interesting headers … ]] Content material-Kind: multipart/form-data; boundary=-735323031399963166993862150 Content material-Size: 834 -735323031399963166993862150 Content material-Disposition: form-data; title=”text1″ textual content default -735323031399963166993862150 Content material-Disposition: form-data; title=”text2″ aωb -735323031399963166993862150 Content material-Disposition: form-data; title=”file1″; filename=”a.txt” Content material-Kind: textual content/plain Content material of a.txt. -735323031399963166993862150 Content material-Disposition: form-data; title=”file2″; filename=”a.html” Content material-Kind: textual content/html <!DOCTYPE html><title>Content material of a.html.</title> -735323031399963166993862150 Content material-Disposition: form-data; title=”file3″; filename=”binary” Content material-Kind: utility/octet-stream aωb -735323031399963166993862150-
Đối với tệp nhị phân và trường văn bản, các byte 61 CF 89 62( aωbtrong UTF-8) được gửi theo nghĩa đen. Bạn có thể xác minh rằng với nc -l localhost 8000 | hd, nói rằng các byte:
61 CF 89 62
đã được gửi ( 61== ‘a’ và 62== ‘b’).
Vì vậy, rõ ràng rằng:
-
Content material-Kind: multipart/form-data; boundary=-9051914041544843365972754266đặt loại nội dung thành multipart/form-datavà nói rằng các trường được phân tách bằng boundarychuỗi đã cho .
-
mỗi trường có một số tiêu đề phụ trước dữ liệu của nó : Content material-Disposition: form-data;, trường title, the filename, theo sau là dữ liệu.
Máy chủ đọc dữ liệu cho đến chuỗi ranh giới tiếp theo. Trình duyệt phải chọn một ranh giới sẽ không xuất hiện trong bất kỳ trường nào, vì vậy đây là lý do tại sao ranh giới có thể khác nhau giữa các yêu cầu.
Bởi vì chúng tôi có ranh giới duy nhất, không cần mã hóa dữ liệu: dữ liệu nhị phân được gửi như hiện có.
TODO: kích thước ranh giới tối ưu ( log(N)tôi đặt cược) và tên / thời gian chạy của thuật toán tìm thấy nó là gì? Đã hỏi tại: https://cs.stackexchange.com/questions/39487/find-the-shortest- resultence-that-is-not-a-sub-resultence-of-a-set-of- outcome
-
Content material-Kind được tự động xác định bởi trình duyệt.
Làm thế nào nó được xác định chính xác đã được hỏi tại: Làm thế nào loại mime của một tệp tải lên được xác định bởi trình duyệt?
ứng dụng / x-www-form-urlencoding
Bây giờ thay đổi enctypethành utility/x-www-form-urlencoded, tải lại trình duyệt và gửi lại.
Firefox đã gửi:
POST / HTTP/1.1 [[ Less interesting headers … ]] Content material-Kind: utility/x-www-form-urlencoded Content material-Size: 51 text1=textual content+default&text2=apercentCFpercent89b&file1=a.txt&file2=a.html&file3=binary
Rõ ràng dữ liệu tệp không được gửi, chỉ có các tên cơ sở. Vì vậy, điều này không thể được sử dụng cho các tập tin.
Đối với trường văn bản, chúng tôi thấy rằng các ký tự có thể in thông thường như avà bđược gửi trong một byte, trong khi các ký tự không in được như thế 0xCFvà 0x89chiếm 3 byte mỗi ký tự : %CFpercent89!
So sánh
Tải lên tệp thường chứa nhiều ký tự không in được (ví dụ hình ảnh), trong khi các hình thức văn bản hầu như không bao giờ thực hiện.
Từ các ví dụ chúng ta đã thấy rằng:
-
multipart/form-data: thêm một vài byte chi phí biên cho thông báo và phải dành thời gian để tính toán nó, nhưng sẽ gửi mỗi byte trong một byte.
-
utility/x-www-form-urlencoded: có một ranh giới byte đơn trên mỗi trường ( &), nhưng thêm hệ số chi phí tuyến tính là 3x cho mỗi ký tự không in được.
Do đó, ngay cả khi chúng tôi có thể gửi tệp cùng utility/x-www-form-urlencoded, chúng tôi sẽ không muốn, vì nó rất kém hiệu quả.
Nhưng đối với các ký tự có thể in được tìm thấy trong các trường văn bản, nó không quan trọng và tạo ra ít chi phí hơn, vì vậy chúng tôi chỉ sử dụng nó.