Kiedy przesyłam prosty formularz taki jak ten z załączonym plikiem:
<form enctype="multipart/form-data" action="http://localhost:3000/upload?upload_progress_id=12344" method="POST">
<input type="hidden" name="MAX_FILE_SIZE" value="100000" />
Choose a file to upload: <input name="uploadedfile" type="file" /><br />
<input type="submit" value="Upload File" />
</form>
Jak wysyła plik wewnętrznie? Czy plik jest wysyłany jako część treści HTTP jako dane? W nagłówkach tego żądania nie widzę nic związanego z nazwą pliku.
Chciałbym tylko znać wewnętrzne działanie HTTP podczas wysyłania pliku.
http
file-upload
0xSina
źródło
źródło
MAX_FILE_SIZE
w PHP - o co chodzi” na stackoverflow.com/q/1381364/632951Odpowiedzi:
Rzućmy okiem na to, co się dzieje, gdy wybierzesz plik i prześlesz formularz (skróciłem nagłówki dla zwięzłości):
UWAGA: każdy ciąg graniczny musi być poprzedzony dodatkowym
--
, tak jak na końcu ostatniego ciągu granicznego. Powyższy przykład już to obejmuje, ale łatwo go przeoczyć. Zobacz komentarz @Andreas poniżej.Zamiast adresu URL kodującego parametry formularza, parametry formularza (w tym dane pliku) są wysyłane jako sekcje w dokumencie wieloczęściowym w treści żądania.
W powyższym przykładzie można zobaczyć dane wejściowe
MAX_FILE_SIZE
o wartości ustawionej w formularzu, a także sekcję zawierającą dane pliku. Nazwa pliku jest częściąContent-Disposition
nagłówka.Pełne szczegóły są tutaj .
źródło
Format jest wywoływany
multipart/form-data
zgodnie z pytaniem: Co oznacza enctype = 'multipart / form-data'?Zamierzam:
Odnośniki HTML5
Istnieją trzy możliwości dla
enctype
:x-www-urlencoded
multipart/form-data
(spec wskazuje na RFC2388 )text-plain
. Nie jest to „niezawodnie interpretowalne przez komputer”, więc nigdy nie powinno się go stosować w produkcji i nie będziemy się temu zagłębiać.Jak wygenerować przykłady
Gdy zobaczysz przykład każdej metody, staje się oczywiste, jak działają i kiedy powinieneś użyć każdej z nich.
Możesz tworzyć przykłady, używając:
nc -l
lub serwer ECHO: serwer testowy HTTP akceptuje żądania GET / POSTZapisz formularz do minimalnego
.html
pliku:Ustawiamy domyślną wartość tekstową na
aωb
, co oznacza,aωb
żeω
jestU+03C9
, czyli bajtów61 CF 89 62
w UTF-8.Utwórz pliki do przesłania:
Uruchom nasz mały serwer echa:
Otwórz HTML w przeglądarce, wybierz pliki, kliknij prześlij i sprawdź terminal.
nc
drukuje otrzymane żądanie.Testowane na: Ubuntu 14.04.3,
nc
BSD 1.105, Firefox 40.multipart / form-data
Firefox wysłał:
W przypadku pliku binarnego i pola tekstowego bajty
61 CF 89 62
(aωb
w UTF-8) są wysyłane dosłownie. Możesz to sprawdzić za pomocąnc -l localhost 8000 | hd
, co oznacza, że bajty:zostały wysłane (
61
== 'a' i62
== 'b').Dlatego jasne jest, że:
Content-Type: multipart/form-data; boundary=---------------------------735323031399963166993862150
ustawia typ zawartości namultipart/form-data
i mówi, że pola są oddzielone danymboundary
ciągiem.Pamiętaj jednak, że:
ma dwa mniej ojców
--
niż rzeczywista barieraWynika to z faktu, że norma wymaga, aby granica zaczynała się od dwóch myślników
--
. Inne myślniki wydają się być tym, w jaki sposób Firefox wybrał implementację arbitralnej granicy. RFC 7578 wyraźnie wspomina, że te dwa wiodące myślniki--
są wymagane:Każde pole dostaje kilka nagłówków podrzędnych przed jego danych:
Content-Disposition: form-data;
polename
, tymfilename
, po której następuje danych.Serwer odczytuje dane do następnego ciągu granicznego. Przeglądarka musi wybrać granicę, która nie pojawi się w żadnym z pól, dlatego granica może się różnić w zależności od żądania.
Ponieważ mamy unikalną granicę, kodowanie danych nie jest konieczne: dane binarne są wysyłane w niezmienionej postaci.
DO ZROBIENIA: jaki jest optymalny rozmiar granicy (
log(N)
założę się) i nazwa / czas działania algorytmu, który ją znajduje? Pytanie zadane na: /cs/39687/find-the-shortest-sequence-that-is-not-a-sub-sequence-of-a-set-of-sequencesContent-Type
jest automatycznie określany przez przeglądarkę.Jak to dokładnie ustalić, zapytano na stronie: W jaki sposób typ MIME przesłanego pliku jest określany przez przeglądarkę?
application / x-www-form-urlencoded
Teraz zmienić
enctype
sięapplication/x-www-form-urlencoded
, załaduj przeglądarkę, i ponownie.Firefox wysłał:
Najwyraźniej dane pliku nie zostały wysłane, tylko nazwy basename. Nie można tego użyć do plików.
Co do pola tekstowego, widzimy, że zwykłe znaki druku jak
a
ib
wysłano w jednym bajcie, a niedrukowalne te, jak0xCF
i0x89
zajął 3 bajty każda:%CF%89
!Porównanie
Przesyłane pliki często zawierają wiele znaków niedrukowalnych (np. Obrazy), podczas gdy formularze tekstowe prawie nigdy tego nie robią.
Z przykładów, które widzieliśmy, że:
multipart/form-data
: dodaje do wiadomości kilka bajtów narzutu granicznego i musi poświęcić trochę czasu na jego obliczenie, ale wysyła każdy bajt w jednym bajcie.application/x-www-form-urlencoded
: ma granicę jednego bajtu na pole (&
), ale dodaje liniowy współczynnik obciążenia 3x dla każdego znaku, który nie może być wydrukowany.Dlatego nawet gdybyśmy mogli przesyłać pliki
application/x-www-form-urlencoded
, nie chcielibyśmy, ponieważ jest to tak nieefektywne.Ale w przypadku znaków drukowalnych znalezionych w polach tekstowych nie ma to znaczenia i generuje mniejszy narzut, więc po prostu go używamy.
źródło
Content-Disposition
i,Content-Type
ale jak obsługiwać „treść”?Wyślij plik jako treść binarną (prześlij bez formularza lub FormData)
W podanych odpowiedziach / przykładach plik jest (najprawdopodobniej) przesłany za pomocą formularza HTML lub interfejsu API FormData . Plik jest tylko częścią danych wysłanych w żądaniu, stąd
multipart/form-data
Content-Type
nagłówek.Jeśli chcesz wysłać plik jako jedyną treść, możesz bezpośrednio dodać go jako treść żądania i ustawić
Content-Type
nagłówek na typ MIME wysyłanego pliku. Nazwę pliku można dodać wContent-Disposition
nagłówku. Możesz przesłać w ten sposób:Jeśli nie chcesz (używasz) formularzy i jesteś zainteresowany przesłaniem tylko jednego pliku, jest to najprostszy sposób na dołączenie pliku do żądania.
źródło
Content-Type
nagłówka.Mam ten przykładowy kod Java:
i mam ten plik test.html:
i wreszcie plik, którego będę używać do celów testowych, o nazwie a.dat, ma następującą zawartość:
jeśli interpretujesz powyższe bajty jako znaki ASCII lub UTF-8, będą one w rzeczywistości reprezentować:
Więc uruchommy nasz kod Java, otwórzmy Uruchommy test.html w naszej ulubionej przeglądarce, prześlij
a.dat
i prześlij formularz i zobacz, co otrzymuje nasz serwer:Nie jestem zaskoczony, widząc bohaterów 9ie, ponieważ powiedzieliśmy Javie, aby je wydrukowało, traktując je jak znaki UTF-8. Równie dobrze możesz przeczytać je jako surowe bajty ..
jest tak naprawdę ostatnim nagłówkiem HTTP tutaj. Następnie pojawia się treść HTTP, w której można zobaczyć meta i zawartość przesłanego pliku.
źródło
http://www.tutorialspoint.com/http/http_messages.htm
źródło