2013-08-07 57 views
8

Chúng tôi đang cố gắng viết một tập lệnh bằng python (sử dụng lệnh python-requests a.t.m.) để thực hiện yêu cầu POST tới trang web nơi nội dung phải là MultipartFormData. Khi chúng tôi yêu cầu POST này bằng tay (bằng cách điền vào mẫu trên trang web và bưu điện), sử dụng Wireshark, điều này đã đưa ra (phiên bản ngắn):Yêu cầu POST với Multipart/form-data. Loại nội dung không chính xác

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

Khi chúng tôi cố gắng sử dụng thư viện python-yêu cầu đạt được cùng một kết quả, điều này được gửi:

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 

Điều kỳ lạ là 'loại chung' của gói thực sự là nhiều phần/biểu mẫu dữ liệu, nhưng mục riêng lẻ được gửi (key = 'name', value = 'John Doe') có loại ứng dụng/x-pandoplugin (một ứng dụng ngẫu nhiên trên máy tính của tôi tôi đoán).

Đây là mã được sử dụng:

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

Có cách nào để xác định các content-type của từng mục thay vì sử dụng các luận cứ tiêu đề (mà chỉ thay đổi kiểu của 'toàn bộ' gói) ?

Chúng tôi cho rằng máy chủ không phản hồi chính xác do thực tế là nó không thể hiểu được loại nội dung chúng tôi gửi.

Cập nhật nhỏ: Tôi nghĩ rằng các phần khác nhau của nội dung nhiều phần bây giờ giống với nội dung được gửi nếu tôi thực hiện POST trong trình duyệt. Tuy nhiên, máy chủ không thực sự thực hiện các thay đổi mà tôi gửi cùng với tập lệnh. Điều duy nhất vẫn khác biệt là thứ tự của các phần khác nhau.

Ví dụ đây là những gì trình duyệt của tôi gửi:

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) 

Và đây là những gì kịch bản (sử dụng python-yêu cầu) gửi:

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) 

Nó có thể được có thể thấy số lần máy chủ trên thứ tự của các bộ phận? Theo số Multipart upload form: Is order guaranteed?, nó rõ ràng là? Và nếu có, có thể buộc một lệnh rõ ràng bằng cách sử dụng thư viện yêu cầu không? Và để làm cho mọi thứ tồi tệ hơn trong trường hợp đó: Có một hỗn hợp của một tập tin và chỉ các giá trị văn bản.

Vì vậy, việc đặt hàng có vẻ khá khó khăn. Đây là cách hiện tại tôi làm điều đó:

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

EDIT2: tôi đã làm một sửa đổi trong yêu cầu cắm để đảm bảo trật tự các bộ phận cũng giống như trong yêu cầu ban đầu. Điều này không khắc phục được sự cố vì vậy tôi đoán không có giải pháp đơn giản nào cho vấn đề của tôi. Tôi sẽ gửi thư cho các nhà phát triển trang web và hy vọng họ có thể giúp tôi!

Trả lời

7

mã của bạn có vẻ chính xác.

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

... và cần gửi một bài viết 'multipart/form-data'.

và thực sự, tôi nhận được một cái gì đó như thế này gửi:

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-- 

Tôi có không ý tưởng tại sao bạn muốn có được điều đó lạ Content-Type header:

Content-Type: application/x-pandoplugin 

tôi sẽ bắt đầu bằng cách loại bỏ Pando Web Plugin khỏi máy của bạn hoàn toàn, và sau đó thử lại mã yêu cầu python của bạn. (hoặc thử từ một máy khác)

+0

Chúng tôi đã thử trên máy khác nhau. Trên một số khác, nó là application/x-uplaypc. Có vẻ như các plugin ngẫu nhiên 'chiếm đoạt' loại nội dung mặc định. Tôi cũng không biết tại sao điều này lại xảy ra. – HaS

+0

Rất nghi ngờ, nhưng các bạn có sử dụng netrc không? –

+0

Không, không phải tôi biết ít nhất. Tôi nghĩ rằng tôi gần như đã giải quyết được vấn đề, vì vậy hãy xem xét vấn đề cập nhật. Vì bạn là một cộng tác cho các yêu cầu, có thể bạn biết câu trả lời? Cảm ơn trước! – HaS

0

Python sử dụng tệp cấu hình toàn hệ thống để "đoán" loại mime của tệp. Nếu các plugin đó đang đăng ký phần mở rộng tệp của bạn với loại mime tùy chỉnh, bạn sẽ kết thúc việc đó.

Cách tiếp cận an toàn nhất là làm cho loại mime của riêng bạn đoán phù hợp với máy chủ cụ thể mà bạn đang gửi và chỉ sử dụng kiểu mime python tự nhiên cho các tiện ích mà bạn không nghĩ đến.

Bạn xác định chính xác kiểu nội dung theo cách thủ công với các yêu cầu python mà tôi không biết, nhưng tôi hy vọng nó có thể thực hiện được.

1

Tính đến hôm nay bạn có thể làm:

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