2013-08-07 9 views
8

Staramy się napisać skrypt za pomocą Pythona (przy pomocy python-requests a.t.m.), aby wykonać żądanie POST do strony, której treścią musi być MultipartFormData. Kiedy ręcznie zrobić to żądanie POST (poprzez wypełnienie formularza na stronie i post), przy użyciu Wireshark to wpadł (krótka wersja):Żądanie POST z Multipart/form-data. Niepoprawny typ zawartości

Content-Type: multipart/form-data; 
Content-Disposition: form-data; name="name" 
Data (8 Bytes) 
    John Doe 

Kiedy staramy się korzystać z biblioteki python-wnioski o osiągnięcia tego samego rezultatu, to jest wysyłany:

Content-Type: application/x-pandoplugin 
Content-Disposition: form-data; name="name"; filename="name"\r\n 
Media type: application/x-pandoplugin (12 Bytes) 
    //and then in this piece is what we posted:// 
    John Doe 

dziwne jest to, że „ogólny typ” pakietu rzeczywiście jest wielowarstwowy form-data /, ale indywidualna pozycja wysłany („name” key =, wartość = 'John Doe') ma typ application/x-pandoplugin (domyślna aplikacja na moim komputerze).

Jest to kod używany:

response = s.post('http://url.com', files={'name': 'John Doe'}) 

Czy istnieje sposób, aby określić typ zawartości poszczególnych elementów zamiast używać argumentu nagłówki (który tylko zmienia typ pakietu „całego”) ?

Wydaje nam się, że serwer nie odpowiada poprawnie, ponieważ nie jest w stanie zrozumieć treści, które wysyłamy.

Mała zmiana: Myślę, że różne części wieloczęściowy treści są teraz identyczne do tych przesyłanych jeśli robię POST w przeglądarce, więc to jest dobre. Mimo to serwer faktycznie nie dokonuje zmian, które wysyłam ze skryptem. Jedyną rzeczą, która wciąż jest inna, jest kolejność poszczególnych części.

Na przykład to, co moja przeglądarka wysyła:

Boundary: \r\n------WebKitFormBoundary3eXDYO1lG8Pgxjwj\r\n 
Encapsulated multipart part: (text/plain) 
    Content-Disposition: form-data; name="file"; filename="ex.txt"\r\n 
    Content-Type: text/plain\r\n\r\n 
    Line-based text data: text/plain 
     lore ipsum blabbla 

Boundary: \r\n------WebKitFormBoundary3eXDYO1lG8Pgxjwj\r\n 
Encapsulated multipart part: 
    Content-Disposition: form-data; name="seq"\r\n\r\n 
    Data (2 bytes) 

Boundary: \r\n------WebKitFormBoundary3eXDYO1lG8Pgxjwj\r\n 
Encapsulated multipart part: 
    Content-Disposition: form-data; name="name"\r\n\r\n 
    Data (2 bytes) 

I to właśnie skrypt (przy użyciu Pythona żądań) wysyła:

Boundary: \r\n------WebKitFormBoundary3eXDYO1lG8Pgxjwj\r\n 
Encapsulated multipart part: 
    Content-Disposition: form-data; name="name"\r\n\r\n 
    Data (2 bytes) 

Boundary: \r\n------WebKitFormBoundary3eXDYO1lG8Pgxjwj\r\n 
Encapsulated multipart part: (text/plain) 
    Content-Disposition: form-data; name="file"; filename="ex.txt"\r\n 
    Content-Type: text/plain\r\n\r\n 
    Line-based text data: text/plain 
     lore ipsum blabbla 

Boundary: \r\n------WebKitFormBoundary3eXDYO1lG8Pgxjwj\r\n 
Encapsulated multipart part: 
    Content-Disposition: form-data; name="seq"\r\n\r\n 
    Data (2 bytes) 

Czy to możliwe, że liczy się serwer na kolejność części? Według Multipart upload form: Is order guaranteed?, najwyraźniej jest? A jeśli tak, czy możliwe jest wyraźne wymuszenie zamówienia za pomocą biblioteki żądań? A w tym przypadku rzeczy stają się jeszcze gorsze: istnieje mieszanka pliku i tylko wartości tekstowe.

Wymuszenie zamówienia wydaje się trudne. Jest obecny sposób to zrobić:

s.post('http://www.url.com', files=files,data = form_values) 

EDIT2: zrobiłem modyfikację we wnioskach plugin aby upewnić się, że kolejność elementów jest taka sama jak w pierwotnym wniosku. To nie rozwiązuje problemu, więc myślę, że nie ma prostego rozwiązania dla mojego problemu. Wyślę maila do twórców strony i mam nadzieję, że mogą mi pomóc!

Odpowiedz

7

Twój kod wygląda poprawnie.

requests.post('http://url.com', files={'name': 'John Doe'}) 

... i powinien wysłać post "wieloczęściowy/formularz danych".

i rzeczywiście, mam coś takiego pisał:

Accept-Encoding: gzip, deflate, compress 
Connection: close 
Accept: */* 
Content-Length: 188 
Content-Type: multipart/form-data; boundary=032a1ab685934650abbe059cb45d6ff3 
User-Agent: python-requests/1.2.3 CPython/2.7.4 Linux/3.8.0-27-generic 

--032a1ab685934650abbe059cb45d6ff3 
Content-Disposition: form-data; name="name"; filename="name" 
Content-Type: application/octet-stream 

John Doe 
--032a1ab685934650abbe059cb45d6ff3-- 

mam nie pojęcia dlaczego chcesz dostać tę dziwną nagłówka Content-Type:

Content-Type: application/x-pandoplugin 

chciałbym rozpocząć od usuwanie Pando Web Plugin z twojego komputera, a następnie spróbuj ponownie zapytać o kod Pythona. (lub spróbuj z innej maszyny)

+0

Staraliśmy się na różnych maszynach. Na innym był to application/x-uplaypc. Wydaje się, że losowe wtyczki przejmują "domyślny typ zawartości. Nie mam też pojęcia, dlaczego tak się dzieje. – HaS

+0

Jest wysoce wątpliwe, ale czy używacie Netrc? –

+0

Nie, nie o tym przynajmniej wiem. Myślę, że prawie rozwiązałem problem, więc proszę spojrzeć na zaktualizowany problem. Skoro jesteś w związku z prośbami, może znasz odpowiedź? Z góry dziękuję! – HaS

0

Python używa ogólnosystemowego pliku konfiguracyjnego do "odgadnięcia" typu MIME pliku. Jeśli te wtyczki rejestrują twoje rozszerzenie pliku z niestandardowym typem mime, to zamiast tego wstawisz to.

Najbezpieczniejszym podejściem jest zrobienie własnego zgadywania typu mime, które pasuje do konkretnego serwera, który wysyłasz, i używanie tylko macierzystego spekulowania typu myth dla rozszerzeń, o których nie myślałeś.

Jak dokładnie określasz typ zawartości ręcznie z python-requestami, których nie znam, ale oczekuję, że będzie to możliwe.

1

dzień dzisiejszy można zrobić:

response = s.post('http://url.com', files={'name': (filename, contents, content_type)})