从python将blob上传到BlobStore会在http上返回500

时间:2015-09-14 13:25:52

标签: python google-app-engine blobstore google-app-engine-python

我正在尝试从python上传blob到BlobStore,它在https://...appspot.comhttps://...com/时有效但是当从http执行完全相同的代码时它不起作用而BlobStore返回500错误。

即使没有连接,我也尝试使连接始终保持安全。

这是我的代码:

@staticmethod
def save_to_blobstore(_request, id, file_contents, file_type, file_name = 'fixmeh.png'):
    upload_url  = blobstore.create_upload_url('/upload-item/blob-key/{}'.format(id))

    if upload_url.startswith('http://') and 'localhost.com' not in _request.get_host():
        upload_url = 'https' + upload_url[4:]

    # ----- CREATING FORMDATA -----
    boundary = 'WebKitFormBoundaryE19zNvXGzXaLvS5C'
    body = '\r\n'.join([
        '--' + boundary,
        'Content-Disposition: form-data; name="file"; filename="{}"'.format(file_name),
        'Content-Type: {}'.format(file_type),
        '',
        file_contents,
        '',
        '--' + boundary + '--',
        '',
    ])

    headers = {
        'Content-Type'  : 'multipart/form-data; boundary={}'.format(boundary),
        'User-Agent'    : 'Mozilla/5.0 (X11; Linux x86_64; rv:31.0) Gecko/20100101 Firefox/31.0',
    }

    logging.critical('blobstore save')

    # TODO Why the hell do we receive deadline limit exceeded?
    request = urllib2.Request(upload_url)

    # ----- FORCING SECURE CONNECTION EXCEPT ON LOCALHOST -----
    if 'localhost.com' in _request.get_host():
        conn = httplib.HTTPConnection(request.get_host(), timeout = 50)
    else:
        conn = httplib.HTTPSConnection(request.get_host(), timeout = 50)

    conn._follow_redirects = True

    logging.info(['upload_url', upload_url ])
    logging.info(['get_host', request.get_host() ])
    logging.info(['get_selector', request.get_selector() ])
    conn.request('POST', request.get_selector(), body, headers)

    try:
        response = conn.getresponse()
        response_body = response.read()

        logging.info(response_body)

        # TODO we need to have an exception if the response is not 200
    except DeadlineExceededError:
        logging.exception('Saving blob - DeadlineExceededError')
    except:
        logging.exception('Saving blob')

当通过HTTP执行时,这是从BlobStore返回的,虽然它没有多大帮助。有没有办法在https://console.developers.google.com/project/.../logs或其他任何地方记录blobstore错误。

<html><head>
<meta http-equiv="content-type" content="text/html;charset=utf-8">
<title>500 Server Error</title></head>
<body text=#000000 bgcolor=#ffffff>
<h1>Error: Server Error</h1>
<h2>The server encountered an error and could not complete your request.
<p>Please retry your last submission.</p>
<p>If the problem persists, please contact the person responsible for the application you're using, or, if you are that person,
<a href="http://code.google.com/appengine/community.html">report</a> your
problem and mention this error message and the query that caused it.</h2>
</body></html>

你能帮助我解决为什么它可能不适用于http但适用于https。 (注意它适用于SDK上的http - 没有ssl,这只发生在appspot上)

2 个答案:

答案 0 :(得分:1)

我使用webapp2路由将此代码用于完整上传网址:

upload_url = create_upload_url(webapp2.uri_for('blob_update', _full=True))

处理程序使用名为route的webapp2:'blob_update'

class BlobUpdate(blobstore_handlers.BlobstoreUploadHandler):
    """ has named route : blob_update : 
    webapp2.Route(r'/blob_update', handler='....BlobUpdate', name='blob_update') """

    def post(self):
        """ blob upload handler returns the new blobkey"""

    blob_info = self.get_uploads('file')[0]
    ....

更多信息:App Engine update blob

答案 1 :(得分:0)

Thanks a lot for the directions and the speedy response. I have taken some ideas from your code and tweaked mine.

I really wished not to use google.appengine.api.urlfetch, sadly I have no time to experiment now at the moment.

Here is the final code just in case any one stumbles upon stuff (also please refer to voscausa's url "App Engine update blob":

    back_url = '{}{}/upload-item/blob-key/{}'.format(_request.protocol, _request.get_host(), id)
    # logging.info(back_url)

    upload_url  = blobstore.create_upload_url(back_url)

    BNDR = b'WebKitFormBoundaryE19zNvXGzXaLvS5C'  # '--PythonBlobstorevarBoundaryVXGzXaLvS5C'
    CRLF = b'\r\n'
    DD   = b'--'

    body = b''.join([
        DD + BNDR + CRLF,
        b'Content-Disposition: form-data; name="file"; filename="{}"'.format(file_name) + CRLF,
        b'Content-Type: {}'.format(file_type) + CRLF,
        CRLF,
        file_contents + CRLF,
        DD + BNDR + DD + CRLF,
    ])

    headers = {
        b'Content-Type' : b'multipart/form-data; boundary={}'.format(BNDR),
        # b'User-Agent' : b'Mozilla/5.0 (X11; Linux x86_64; rv:31.0) Gecko/20100101 Firefox/31.0',
    }

    try:
        response = urlfetch.fetch(
            url                 = upload_url,
            payload             = body,
            method              = urlfetch.POST,
            deadline            = 40,
            follow_redirects    = False,
            headers             = headers
        )

        if response.status_code == 200:
            logging.info(response.content)
        else:
            logging.info(response)
            logging.error(response.content)
            logging.exception('URL : {} fetch ERROR : {}'.format(upload_url, response.status_code))
    except (urlfetch.DownloadError, DeadlineExceededError), e:
        logging.exception('fetch {} download or deadline error, exception : {}'.format(upload_url, str(e)))