1

S3インスタンスにファイルを投稿するクライアントアプリケーションを作成していますが、以下のコードを使用すると、応答がなく、ファイルが投稿されません。サーバーにクレデンシャルを入力することで機能し、クライアントはその詳細を使用してs3インスタンスに接続し(またはこれが機能している場合は)、ファイルをアップロードします。

import httplib, urllib, json

setup_headers = {"Content-Type": "application/json", "Accept": "text/plain"}
conn = httplib.HTTPSConnection("www.server.address")
conn.request("GET", "/api/data/upload-request/", '', setup_headers)

response = conn.getresponse()

response_data = response.read()
print response_data

aws_setup = json.loads(response_data)

aws_setup.update({'filename':'fname.zip', 'file': open('fname.zip', 'rb').read()})

aws_params = urllib.urlencode(aws_setup)
aws_headers = {'Content-Type':'multipart/form-data'}
aws_conn = httplib.HTTPSConnection("address.s3.amazonaws.com")
aws_conn.request("POST", "", aws_params, aws_headers)

aws_conn.close()
conn.close()

最初の接続要求オブジェクトから返されるもの:

{"AWSAccessKeyId": "correct key", "success_action_redirect": "http://our.web.address/api/upload-success/", "acl": "private", "key": "${filename}", "signature": "signature", "policy": "encoded policy", "Content-Type": "application/zip"}

マルチパートフォームデータに問題があるため、これは失敗していました。私が遭遇している新しい問題は、encode_multipart_formdataでエラーが発生していることです。ファイルタイプオブジェクトを渡すと、文字列結合が試行され、失敗します。文字列を渡すと、明らかにファイルの内容が取り込まれず、ファイルの内容全体をメモリに読み込んで渡したくありません。コードと両方のエラーレポートは以下のとおりです。

import httplib
import json
import mimetypes

def post_multipart(host, selector, fields, files):
    """
    Post fields and files to an http host as multipart/form-data.
    fields is a sequence of (name, value) elements for regular form fields.
    files is a sequence of (name, filename, value) elements for data to be uploaded as files
    Return the server's response page.
    """
    content_type, body = encode_multipart_formdata(fields, files)
    h = httplib.HTTPSConnection(host)
    header = {
        'User-Agent': 'Mozilla/5.0',
        'Content-Type': content_type
        }
    h.request('POST', selector, body, header)
    res = h.getresponse()
    return res.status, res.reason, res.read()

def encode_multipart_formdata(fields, files):
    """
    fields is a sequence of (name, value) elements for regular form fields.
    files is a sequence of (name, filename, value) elements for data to be uploaded as files
    Return (content_type, body) ready for httplib.HTTP instance
    """
    BOUNDARY = '----------ThIs_Is_tHe_bouNdaRY_$'
    CRLF = '\r\n'
    L = []
    for key, value in fields.iteritems():
        L.append('--' + BOUNDARY)
        L.append('Content-Disposition: form-data; name="%s"' % key)
        L.append('')
        L.append(value)
    for (key, filename, value) in files:
        L.append('--' + BOUNDARY)
        L.append('Content-Disposition: form-data; name="%s"; filename="%s"' % (key, filename))
        L.append('Content-Type: %s' % get_content_type(filename))
        L.append('')
        L.append(value)
    L.append('--' + BOUNDARY + '--')
    L.append('')
    body = CRLF.join(L)
    content_type = 'multipart/form-data; boundary=%s' % BOUNDARY
    return content_type, body

def get_content_type(filename):
    return mimetypes.guess_type(filename)[0] or 'application/octet-stream'

setup_headers = {"Content-Type": "application/json", "Accept": "text/plain"}
conn = httplib.HTTPSConnection("our.server.address")
conn.request("GET", "/api/data/upload-request/", '', setup_headers)

response = conn.getresponse()

response_data = response.read()

aws_setup = json.loads(response_data)
status, reason, data = post_multipart("address.s3.amazonaws.com", "", aws_setup, [['upload_file.zip', 'upload_file.zip', open("upload_file.zip")]])
print status
print reason
print data
conn.close() 

上記のコードに示されているファイルタイプオブジェクトのエラー:

TypeError: sequence item 32: expected string or Unicode, file found

代わりに文字列が渡されるとエラーが発生します:

400
Bad Request
<?xml version="1.0" encoding="UTF-8"?>
<Error><Code>InvalidArgument</Code><Message>POST requires exactly one file upload per request.</Message><ArgumentValue>0</ArgumentValue><ArgumentName>file</ArgumentName><RequestId>9AA6411E13792EC6</RequestId><HostId>EkkcNUkIWIVk8wbhEplhp0L+Rqsa089TD0VusgMUQsQJo3rUUf/zbP+k67fEzolc</HostId></Error>

boto(私が仕事に取り掛かった)でこれを行うには、クライアント側に秘密鍵を表示する必要がありました。

4

0 に答える 0