Yanıtlar:
Bir POST isteği yaptığınızda, isteğin gövdesini oluşturan verileri bir şekilde kodlamanız gerekir.
HTML formları üç kodlama yöntemi sağlar.
application/x-www-form-urlencoded
(varsayılan)multipart/form-data
text/plain
Ekleme konusunda çalışmalar yapılıyordu application/json
, ama bu terk edildi.
(HTML form gönderimi dışında başka araçlar kullanılarak oluşturulan HTTP istekleri ile başka kodlamalar da mümkündür. JSON, web hizmetleriyle kullanım için yaygın bir biçimdir ve bazıları hala SOAP kullanır.)
Biçimlerin özellikleri çoğu geliştirici için önemli değildir. Önemli noktalar:
text/plain
.İstemci tarafı kodu yazarken:
multipart/form-data
formunuzda herhangi bir <input type="file">
öğe olduğunda kullanınmultipart/form-data
veya application/x-www-form-urlencoded
ancak application/x-www-form-urlencoded
daha verimli olacakSunucu tarafı kodu yazarken:
Çoğu (Perl'ler CGI->param
veya PHP'nin $_POST
süper küresi tarafından maruz kalanlar gibi ) sizin için farklılıklarla ilgilenecektir. Sunucu tarafından alınan ham girdiyi ayrıştırmaya çalışmayın.
Bazen her iki biçimi de işleyemeyen bir kütüphane bulabilirsiniz. Node.js'nin form verilerini işlemek için en popüler kütüphanesi, çok parçalı istekleri işleyemeyen (ancak yapabilen bazı alternatifleri öneren belgelere sahip) gövde ayrıştırıcısıdır .
Ham verileri ayrıştırmak veya oluşturmak için bir kitaplık yazıyorsanız (veya hata ayıklama yapıyorsanız), format hakkında endişelenmeye başlamanız gerekir. Ayrıca, ilgi uğruna bunu bilmek isteyebilirsiniz.
application/x-www-form-urlencoded
, URL'nin sonundaki bir sorgu dizesiyle aşağı yukarı aynıdır.
multipart/form-data
önemli ölçüde daha karmaşıktır ancak tüm dosyaların verilere dahil edilmesini sağlar. Sonuç için bir örnek HTML 4 spesifikasyonunda bulunabilir .
text/plain
HTML 5 tarafından tanıtıldı ve yalnızca hata ayıklama için kullanışlıdır - spesifikasyondan : Bunlar bilgisayar tarafından güvenilir bir şekilde yorumlanamaz - ve diğerlerinin araçlarla (çoğu tarayıcının geliştirici araçlarındaki Ağ Paneli gibi ) daha iyi olduğunu iddia ediyorum bunun için).
ne zaman kullanmalıyız
Quentin'in cevabı doğrudur: multipart/form-data
form bir dosya yüklemesi içeriyorsa kullanın , application/x-www-form-urlencoded
aksi takdirde atlarsanız varsayılan değerdir enctype
.
Şuna gidiyorum:
Orada üç olasılık için enctype
:
application/x-www-form-urlencoded
multipart/form-data
(spesifikasyon RFC7578'i gösterir )text/plain
. Bu "bilgisayar tarafından güvenilir bir şekilde yorumlanamaz", bu yüzden asla üretimde kullanılmamalıdır ve daha fazla araştırmayacağız.Her yöntemin bir örneğini gördüğünüzde, nasıl çalıştıklarını ve her birini ne zaman kullanmanız gerektiği açık hale gelir.
Aşağıdakileri kullanarak örnekler üretebilirsiniz:
nc -l
veya bir ECHO sunucusu: GET / POST isteklerini kabul eden HTTP test sunucusuFormu minimal bir .html
dosyaya kaydedin :
<!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>
Biz varsayılan metin değeri aωb
, araçlar aωb
nedeniyle ω
olduğunu U+03C9
bayt olan, 61 CF 89 62
UTF-8.
Yüklenecek dosyalar oluşturun:
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
Küçük yankı sunucumuzu çalıştırın:
while true; do printf '' | nc -l 8000 localhost; done
Tarayıcınızda HTML'yi açın, dosyaları seçin ve gönder'i tıklayın ve terminali kontrol edin.
nc
alınan isteği yazdırır.
Test tarihi: Ubuntu 14.04.3, nc
BSD 1.105, Firefox 40.
Firefox gönderdi:
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--
İkili dosya ve metin alanı için baytlar 61 CF 89 62
( aωb
UTF-8'de) kelimenin tam anlamıyla gönderilir. Bunu nc -l localhost 8000 | hd
, baytların söylediği ile doğrulayabilirsiniz :
61 CF 89 62
gönderildi ( 61
== 'a' ve 62
== 'b').
Bu nedenle açıktır:
Content-Type: multipart/form-data; boundary=---------------------------735323031399963166993862150
içerik türünü ayarlar ve multipart/form-data
alanların verilen boundary
dize ile ayrıldığını belirtir .
Ancak şunu unutmayın:
boundary=---------------------------735323031399963166993862150
--
asıl engelden daha az iki babası var
-----------------------------735323031399963166993862150
Bunun nedeni, standardın sınırın iki tire ile başlamasını gerektirmesidir --
. Diğer çizgiler, Firefox'un keyfi sınırı nasıl uyguladığını gösteriyor. RFC 7578, bu iki önde gelen tirenin --
gerekli olduğunu açıkça belirtmektedir :
4.1. "Sınır" Çok parçalı / form verisi parametresi
Diğer çok parçalı tiplerde olduğu gibi, parçalar da CRLF, "-" ve "sınır" parametresinin değeri kullanılarak oluşturulan bir sınır sınırlayıcı ile sınırlandırılır.
Her alan kendi verilerine önce bazı alt başlıklarını alır: Content-Disposition: form-data;
, alan name
, filename
verilerin ardından.
Sunucu, verileri bir sonraki sınır dizesine kadar okur. Tarayıcı, alanların hiçbirinde görünmeyecek bir sınır seçmelidir, bu nedenle sınır istekler arasında değişebilir.
Benzersiz sınırımız olduğu için, verilerin kodlanması gerekmez: ikili veriler olduğu gibi gönderilir.
YAPILACAKLAR: İdeal sınır boyutu ( log(N)
bahse girerim) ve onu bulan algoritmanın adı / çalışma süresi nedir? Sorulduğu yer: /cs/39687/find-the-shortest-sequence-that-is-not-a-sub-sequence-of-a-set-of-sequences
Content-Type
tarayıcı tarafından otomatik olarak belirlenir.
Tam olarak nasıl belirlendi: Şu şekilde yüklenen bir dosyanın mime türü tarayıcı tarafından nasıl belirlenir?
Şimdi değiştirmek enctype
için application/x-www-form-urlencoded
, tarayıcı ve yeniden gönderin yükleyin.
Firefox gönderdi:
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çıkça, dosya verileri gönderilmedi, sadece temel isimler. Yani bu dosyalar için kullanılamaz.
Metin alanına gelince, biz gibi o zamanki yazdırılabilir karakterleri görmek a
ve b
benzeri olmayan basılabilir olanlar ise, tek bayt gönderildi 0xCF
ve 0x89
aldı 3 bayt her: %CF%89
!
Dosya yüklemeleri genellikle yazdırılamayan çok sayıda karakter (örn. Resimler) içerirken metin formları neredeyse hiç yapmaz.
Örneklerden şunu gördük:
multipart/form-data
: mesaja birkaç bayt sınır ek yükü ekler ve bunu hesaplamak için biraz zaman harcamalıdır, ancak her baytı bir bayt olarak gönderir.
application/x-www-form-urlencoded
: alan başına tek bir bayt sınırına ( &
) sahiptir, ancak yazdırılamayan her karakter için 3x doğrusal bir ek yük faktörü ekler .
Bu nedenle, ile dosya gönderebilsek bile application/x-www-form-urlencoded
, istemezdik, çünkü bu çok verimsiz.
Ancak metin alanlarında bulunan yazdırılabilir karakterler için önemli değildir ve daha az ek yük oluşturur, bu yüzden sadece kullanırız.
%CF
uzun 3 bayt: %
, C
ve F
insan okunabilir yapma :-) Öyküsü.
nc
hem ve -l
hem de -p
bağımsız değişkenleri aynı anda kabul etmez . Ama bu benim için çalışıyor: while true; do printf '' | nc -l 8000; done
.
Content-Type
, iki kısa çizginin ( --
) daha az olması, yani mesaj gövdesinde aslında sınırı kullanırken, önek eklemeniz gerektiğidir --
. Ayrıca, son sınırın --
eklenmesi gerekir , ancak bunu fark etmek yeterince kolaydır. Bkz. Stackoverflow.com/questions/3508252/…
enctype='multipart/form-data
dosyaların bir POST yoluyla gönderilmesine izin veren bir kodlama türüdür . Oldukça basit, bu kodlama olmadan dosyalar POST yoluyla gönderilemez .
Kullanıcının form aracılığıyla dosya yüklemesine izin vermek istiyorsanız, bu şifreyi kullanmanız gerekir .
multipart/form-data
ikili olmayan dosyaları göndermek için kullanabilirsiniz , ancak verimsizdir. Kullanmanın application/x-www-form-urlencoded
ikili olmayan veri göndermenin doğru yolu olduğuna inanıyorum , ancak ikili olmayan dosyalarla daha fazla deneyime sahip birisinin beni düzeltmesi gerekebilir.
multipart/form-data
Bir dosyayı göndermek için kullanmanın ana avantajı, dosyanın hem ön uçta hem de arka uçta otomatik olarak çalışmasıdır. Özel bir işlem yapmanız gerekmez. Tüm dosyalar, yalnızca metin içermeleri gerekse bile ikilidir. application/x-www-form-urlencoded
ekli dosyaları olmayan bir formu POST etmenin standart yoludur. multipart/form-data
ekli dosya (lar) içeren bir formu POST ETMENİN standart yoludur. ( Sunucu ve istemci arasındaki iletişimde yaygın olan application/json
ve gibi çok sayıda başka kodlama da vardır application/json-patch+json
.)
multipart/form-data
. Yapamayacağınız şey , JavaScript olmadan sıradan bir HTML formu gönderimi kullanmaktır. Kullanılacak bir form ayarlamak multipart/form-data
, HTML'nin JavaScript kullanmadan POST dosyalarına izin vermesini sağlayan tek mekanizmadır . Bunun cevapta yeterince açık olmadığını ve saf bir okuyucunun dosya olmadan gönderilememesinin HTTP'ninmultipart/form-data
bir sınırlaması olduğunu düşünebileceğini hissediyorum ; konu bu değil.
Bir form gönderirken, tarayıcınıza HTTP protokolü üzerinden, bir TCP / IP protokolü mesaj yapısında düzgün bir şekilde zarflanmış bir mesaj göndermesini söylersiniz. Bir HTML sayfasının sunucuya veri göndermenin bir yolu vardır: <form>
s kullanarak .
Bir form gönderildiğinde, bir HTTP İsteği oluşturulur ve sunucuya gönderilir; ileti, formdaki alan adlarını ve kullanıcı tarafından doldurulan değerleri içerir. Bu iletim POST
veya GET
HTTP yöntemleriyle olabilir .
POST
tarayıcınıza bir HTTP mesajı oluşturmasını ve tüm içeriği mesajın gövdesine koymasını söyler (bir şeyler yapmanın çok yararlı bir yolu, daha güvenli ve aynı zamanda esnek).GET
form verilerini sorgu dizesinde gönderir . Veri gösterimi ve uzunluğu ile ilgili bazı kısıtlamaları vardır.Özniteliğin enctype
yalnızca POST
yöntemi kullanırken bir anlamı vardır . Belirtildiğinde, tarayıcıya formu içeriğini belirli bir şekilde kodlayarak göndermesi talimatını verir. Gönderen MDN'yi - Form enctype :
Method özniteliğinin değeri post olduğunda, enctype, formu sunucuya göndermek için kullanılan MIME içerik türüdür.
application/x-www-form-urlencoded
: Bu varsayılan ayardır. Form gönderildiğinde, tüm adlar ve değerler toplanır ve URL Kodlaması son dizgide gerçekleştirilir.multipart/form-data
: Karakterler kodlanmamış. Formda dosya yükleme denetimi varsa bu önemlidir. İkili dosyayı göndermek istiyorsunuz ve bu da bit akımının değiştirilmemesini sağlıyor.text/plain
: Boşluklar dönüştürülür, ancak başka kodlama yapılmaz.Formları gönderirken, RFC 7578 Bölüm 7: Çok parçalı form verileri - Güvenlikle ilgili konular :
Tüm form işleme yazılımları
, genellikle gizli veya kişisel olarak
tanımlayıcı bilgiler içerdiğinden, kullanıcı tarafından sağlanan form verilerini hassas bir şekilde ele almalıdır . Web tarayıcılarında form "otomatik doldurma" özelliklerinin yaygın kullanımı vardır; bunlar, kullanıcıları
aksi takdirde
zararsız görevleri tamamlarken bilmeden gizli bilgiler göndermeleri için kandırmak için kullanılabilir . çok parçalı / form verileri,
bütünlüğü denetlemek, gizliliği sağlamak, kullanıcı
karışıklığını veya diğer güvenlik özelliklerini önlemek için herhangi bir özellik sağlamaz ; bu endişeler
, form doldurma ve form-veri yorumlama uygulamaları tarafından ele alınmalıdır .Formları alan ve işleyen başvurular, gönderilmesi amaçlanmayan talep eden form işleme sitesine geri veri vermemeye dikkat etmelidir.
Content-
Disposition üstbilgisi alanının dosya adını ,
alıcının dosya alanındaki dosyaların üzerine yanlışlıkla yazmamak için yorumlarken önemlidir .
Bir geliştiriciyseniz ve sunucunuz kullanıcılar tarafından gönderilen ve hassas bilgiler içerebilecek formları işleyecekse bu sizi ilgilendirir.
enctype
. Kelimenin tam anlamıyla RFC'den olduğunu biliyorum multipart/form-data
, ancak yine de verinin application/x-www-form-urlencoded
veya olarak gönderilip gönderilmeyeceğine tamamen dik olan formların gönderilmesi ile ilgili keyfi bir güvenlik kayması multipart/form-data
.
Dosya içeriği form kullanılarak bir URL parametresinin içine yerleştirilemediğinden, yöntem niteliğini POST olarak ayarlayın.
Her bir dosya için bir tane ve onlarla gönderilebilecek form gövdesi metni için bir tane olmak üzere birden çok parçaya ayrılacağından, enctype değerini multipart / form-data olarak ayarlayın.
POST
bir form aracılığıyla bir dosya göndermek için yeterli olması ve eklemenin multipart/form-data
belli belirsiz bir şekilde bir bonus olduğu anlamına gelir . Konu bu değil. Çoğu dosya kesinlikle kullanılmasını gerektirir multipart/form-data
.
<head>
ve <body>
alakasız ve kafa karıştırıcı.
Enctype özniteliği, form verilerinin sunucuya gönderilirken nasıl kodlanması gerektiğini belirtir.
Enctype özniteliği yalnızca method = "post" olduğunda kullanılabilir.
Hiçbir karakter kodlanmamış. Dosya yükleme denetimi olan formları kullanırken bu değer gereklidir
Gönderen W3Schools'da
multipart/form-data
. Aynı zamanda oldukça belirsiz; "Hiçbir karakter kodlanmamış" cümlesi ne anlama geliyor? -1.