2013-03-19 2 views
2

파이썬의 Requests 라이브러리를 사용하여 Amazon S3 엔드 포인트로 요청을 POST하려고한다. 요청은 실제 파일의 게시를 포함하기 때문에 multipart/form-data 종류의 요청입니다.Python-Requests가 OrderedDicts를 지원합니까? 아니면 여기에 뭔가 잘못되었습니다.

내가 맞서고있는 API 요구 사항 중 하나는 file 매개 변수가 마지막이어야한다는 것입니다. Requests는 사전을 사용하여 multipart/form-data를 POST하고, 사전은 지시에 따르지 않기 때문에 이것을 payload이라는 OrderedDict로 변환했습니다. 그것은을 게시하기 전에 다음과 같은 :

{'content-type': 'text/plain', 
'success_action_redirect':  'https://ian.test.instructure.com/api/v1/files/30652543/create_success?uuid=<opaque_string>', 
'Signature': '<opaque_string>', 
'Filename': '', 
'acl': 'private', 
'Policy': '<opaque_string>', 
'key': 'account_95298/attachments/30652543/log.txt', 
'AWSAccessKeyId': '<opaque_string>', 
'file': '@log.txt'} 

을 그리고 이것은 내가 POST 방법입니다

r = requests.post("https://instructure-uploads.s3.amazonaws.com/", files = payload) 

응답이 500 오류입니다, 그래서 정말 문제가 여기 모르겠어요 . 나는 그것이 단지 Request의 OrderedDict를 사용하는 것과 관련이 있다고 생각하고있다. Requests가 OrderedDicts를 지원하는지 또는 지원하지 않는지를 알 수있는 문서를 찾을 수 없다. 그것은 완전히 다른 무언가 일 수 있습니다.

요청이 실패하게하는 원인은 무엇입니까? 필요한 경우 세부 정보를 제공 할 수 있습니다. 마티 피에 터스 '이전 의견에 따라

좋아, 업데이트 :

나는 이런 식으로 이미 생성 upload_data 사전에 추가하여 나는 log.txt에 파일을 참조하고있어 방법을 변경 :

{'AWSAccessKeyId': '<opaque_string>', 
'key': '<opaque_string>', 
'Policy': '<opaque_string>', 
'content-type': 'text/plain', 
'success_action_redirect': 'https://ian.test.instructure.com/api/v1/files/30652688/create_success?uuid=<opaque_string>', 
'Signature': '<opaque_string>', 
'acl': 'private', 
'Filename': '', 
'file': <_io.TextIOWrapper name='log.txt' mode='r' encoding='UTF-8'>} 
,691 :
upload_data['file'] = open("log.txt") 

결과 사전을 pprinting 나는이 얻을

file 키의 값이 정확합니까? 나는 마틴의 예와 매우 비슷 나는이를 얻을 RequestBin,에 게시 할 때

: 나는 https://instructure-uploads.s3.amazonaws.com/에 게시하려고 할 때

POST /1j92n011 HTTP/1.1 
User-Agent: python-requests/1.1.0 CPython/3.3.0 Darwin/12.2.0 
Host: requestb.in 
Content-Type: multipart/form-data; boundary=e8c3c3c5bb9440d1ba0a5fe11956e28d 
Content-Length: 2182 
Connection: close 
Accept-Encoding: identity, gzip, deflate, compress 
Accept: */* 

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

<opaque_string> 
--e8c3c3c5bb9440d1ba0a5fe11956e28d 
Content-Disposition: form-data; name="key"; filename="key" 
Content-Type: application/octet-stream 

<opaque_string> 
--e8c3c3c5bb9440d1ba0a5fe11956e28d 
Content-Disposition: form-data; name="Policy"; filename="Policy" 
Content-Type: application/octet-stream 

<opaque_string> 
--e8c3c3c5bb9440d1ba0a5fe11956e28d 
Content-Disposition: form-data; name="content-type"; filename="content-type" 
Content-Type: application/octet-stream 

text/plain 
--e8c3c3c5bb9440d1ba0a5fe11956e28d 
Content-Disposition: form-data; name="success_action_redirect"; filename="success_action_redirect" 
Content-Type: application/octet-stream 

https://ian.test.instructure.com/api/v1/files/30652688/create_success?uuid=<opaque_string> 
--e8c3c3c5bb9440d1ba0a5fe11956e28d 
Content-Disposition: form-data; name="Signature"; filename="Signature" 
Content-Type: application/octet-stream 

<opaque_string> 
--e8c3c3c5bb9440d1ba0a5fe11956e28d 
Content-Disposition: form-data; name="acl"; filename="acl" 
Content-Type: application/octet-stream 

private 
--e8c3c3c5bb9440d1ba0a5fe11956e28d 
Content-Disposition: form-data; name="Filename"; filename="Filename" 
Content-Type: application/octet-stream 


--e8c3c3c5bb9440d1ba0a5fe11956e28d 
Content-Disposition: form-data; name="file"; filename="log.txt" 
Content-Type: text/plain 

This is my awesome test file. 
--e8c3c3c5bb9440d1ba0a5fe11956e28d-- 

그러나, 나는 아직 도착 500이 돌아왔다. 나는 열린 파일 객체를 files에 추가 한 다음 data을 통해 별도의 dict에있는 다른 모든 값을 제출하려고 시도했지만 그 중 하나도 작동하지 않았습니다.

답변

0

dict, 또는 두 개의 값이있는 튜플 시퀀스를 전달할 수 있습니다.

그리고 OrderedDict은 하찮게 같은 순서로 변환됩니다

r = requests.post("https://instructure-uploads.s3.amazonaws.com/", files=payload.items()) 

그러나, collections.OrderedDict() 유형 그래서 전달, items()은 후드 아래에 무엇을 requests정확히입니다 전화, dict의 서브 클래스이기 때문에 OrderedDict 인스턴스가 직접 작동합니다.

이와 같이 다른 문제가 있습니다.대신 http://httpbin/post에 게시하여 게시되고 있는지 확인할 수 있습니다

import pprint 
pprint.pprint(requests.post("http://httpbin.org/post", files=payload.items()).json()) 

불행하게도, httpbin.org이 순서를 보존하지 않습니다. 또는 http://requestb.in/에 전용 HTTP 포스트 보관함을 만들 수도 있습니다. 계속 진행되는 것을 자세히 알려줄 것입니다.

requestb.in 사용과 같은 오픈 파일 객체 '@log.txt' 대체하여 요청에서 POST가 기록되어 그 순서가 정확하게 유지되고 도시

POST /tlrsd2tl HTTP/1.1 
User-Agent: python-requests/1.1.0 CPython/2.7.3 Darwin/11.4.2 
Host: requestb.in 
Content-Type: multipart/form-data; boundary=7b12bf345d0744b6b7e66c7890214311 
Content-Length: 1601 
Connection: close 
Accept-Encoding: gzip, deflate, compress 
Accept: */* 

--7b12bf345d0744b6b7e66c7890214311 
Content-Disposition: form-data; name="content-type"; filename="content-type" 
Content-Type: application/octet-stream 

text/plain 
--7b12bf345d0744b6b7e66c7890214311 
Content-Disposition: form-data; name="success_action_redirect"; filename="success_action_redirect" 
Content-Type: application/octet-stream 

https://ian.test.instructure.com/api/v1/files/30652543/create_success?uuid=<opaque_string> 
--7b12bf345d0744b6b7e66c7890214311 
Content-Disposition: form-data; name="Signature"; filename="Signature" 
Content-Type: application/octet-stream 

<opaque_string> 
--7b12bf345d0744b6b7e66c7890214311 
Content-Disposition: form-data; name="Filename"; filename="Filename" 
Content-Type: application/octet-stream 


--7b12bf345d0744b6b7e66c7890214311 
Content-Disposition: form-data; name="acl"; filename="acl" 
Content-Type: application/octet-stream 

private 
--7b12bf345d0744b6b7e66c7890214311 
Content-Disposition: form-data; name="Policy"; filename="Policy" 
Content-Type: application/octet-stream 

<opaque_string> 
--7b12bf345d0744b6b7e66c7890214311 
Content-Disposition: form-data; name="key"; filename="key" 
Content-Type: application/octet-stream 

account_95298/attachments/30652543/log.txt 
--7b12bf345d0744b6b7e66c7890214311 
Content-Disposition: form-data; name="AWSAccessKeyId"; filename="AWSAccessKeyId" 
Content-Type: application/octet-stream 

<opaque_string> 
--7b12bf345d0744b6b7e66c7890214311 
Content-Disposition: form-data; name="file"; filename="log.txt" 
Content-Type: text/plain 

some 
data 

--7b12bf345d0744b6b7e66c7890214311-- 

.

requests은 Curl 관련 @filename 구문을 지원하지 않습니다. 대신, 열린 파일 객체를 전달 : 'Content-Type': .. : 또한 제목 케이스를 사용하도록 content-type 필드를 설정 할 수 있습니다

'file': open('log.txt', 'rb') 

.

아직 500 명이 응답하는 경우 r.text 응답 텍스트를 확인하여 Amazon이 잘못 생각한 부분을 확인하십시오.

+0

그렇다면 문제는 OrderedDict를 올바르게 사용하지 않았다고 말하는 것입니까? –

+0

@IanMorris : 맞습니다. 죄송합니다. 전 중간 게시판에서 전화가 왔습니다. –

+0

@IanMorris : 파일 필드에''@log.txt ''가 들어 있습니까? 'log.txt'라는 이름의 로컬 파일을 스트리밍해야한다면, 열린 파일 객체로 바꿔야합니다. –

2

당신이 보낸 내용을 data으로 전달 된 OrderedDict로 나눠야하고 하나는 files으로 전송해야합니다. 현재 AWS는 형식 매개 변수가 아닌 파일로 데이터 매개 변수를 (올바르게) 해석합니다. 다음과 같이 표시되어야합니다.

data = OrderedDict([ 
    ('AWSAccessKeyId', '<opaque_string>'), 
    ('key', '<opaque_string>'), 
    ('Policy', '<opaque_string>'), 
    ('content-type', 'text/plain'), 
    ('success_action_redirect', 'https://ian.test.instructure.com/api/v1/files/30652688/create_success?uuid=<opaque_string>'), 
    ('Signature', '<opaque_string>'), 
    ('acl', 'private'), 
    ('Filename', ''), 
]) 

files = OrderedDict([('file', open('log.txt'))]) 

requests.post(url, data=data, files=files) 
관련 문제