【问题标题】:Must be called from a blob upload callback request必须从 Blob 上传回调请求中调用
【发布时间】:2016-12-02 16:13:27
【问题描述】:

我已经在 J​​ava 中为 blobstore API 实现了这个 GWT 示例: https://cloud.google.com/appengine/docs/java/blobstore/

当通过客户端表单(在浏览器内)进行 POST 时,它可以正常工作。

但是,现在我将文件(图像)发送到同一个 /upload 服务处理程序,但来自我的离线程序(不是浏览器)内的 python 请求:

r = requests.post(url+'upload', files= {'myFile': open('fig.jpeg', 'rb')})

我得到以下异常

必须从 blob 上传回调请求中调用

在(服务器端)的第一行:

Map<String, List<BlobKey>> blobs = blobstoreService.getUploads(req);
List<BlobKey> blobKeys = blobs.get("myFile");

我做错了什么??

【问题讨论】:

    标签: java python google-app-engine gwt


    【解决方案1】:

    找到下面的示例代码来理解flask和python的回调

    项目> app.py

    import datetime
    import time
    import requests # to make get and post requests
    import json
    from flask import Flask, Response, request, render_template  #  request : is not same as requests its flask request on url
    
    app = Flask(__name__)
    app.config['JSONIFY_PRETTYPRINT_REGULAR'] = True
    
    # 3. no need to give any url mapping for callback function,
    # this will get call once demo() return back to hello() at post request call.
    def callbacks(response, *args, **kwargs):
        print(" -- callbacks starts -- : ", datetime.datetime.now().time())
    
        if response.status_code == 200:
            #print(response.text)
            print(" -- callback end -- : ", datetime.datetime.now().time());
            #return response
            # return Response(response, status=200)   do not return response here this will cause problem when
    
    
    # 2. on post request call made from hello(): resp = requests.post(......)
    @app.route('/demo' , methods=['POST']) # validate request of type methods=['POST']
    def demo():
        print("Post request received : ", datetime.datetime.now().time())
    
        if request.method == 'POST':  # check request of type post
            time.sleep(5)   # some sleep time to check if callback is working
            print("Post response sent to callback : ", datetime.datetime.now().time())
            # return response with data received from request.data  and status = 200
            return Response(request.data, headers={'Content-Type': 'application/json'}, status=200)
    
    
    
    # 1. run this file and hit url localhost:5000/  to execute ( GET request)
    @app.route('/', methods=['GET'])
    def hello():
        print("Hello start : ", datetime.datetime.now().time())
        url = 'http://jsonplaceholder.typicode.com/users';         # url will return json list
    
        data = requests.get(
                                url=url,
                                headers={'Content-Type': 'application/json'}
                            )   # get request to get json data from url using requests lib
    
        # check if flask request is get
        if request.method == 'GET':
    
            # post request to another url /demo with data as a json as argument ,
            # imp : hooks to link callback function once /demo url returns response callback will start execute
            resp = requests.post( url = 'http://localhost:5000/demo',
                                  headers = {'Content-Type': 'application/json'},
                                  json = data.json(),
                                  hooks={'response': callbacks }
                                )
    
        print("Hello End : ",datetime.datetime.now().time())
        # render with html template with argument as data and result
        return render_template('index.html', result=resp.json(), data=data.json())
        #                OR
        # return Response(response='OK', status=resp.status_code) # return response with 200 or 'OK'
    
    
    if __name__ == '__main__':
        app.run(debug=False)
    

    创建文件 index.html 并复制以下代码

    项目/模板> index.html

    <!DOCTYPE html>
        <html lang="en">
        <head>
            <meta charset="UTF-8">
            <title>JSON OUTPUT</title>
        </head>
        <body>
        <table border="1">
            <tr><td>ID</td><td>Name</td><td>Email</td></tr>
                {% for d in data %}
                    <tr><td>{{ d['id'] }}</td><td>{{ d['name'] }}</td><td>{{ d['email'] }}</td></tr>
                {% endfor %}
        </table>
        <div>{{ result }}</div>
        </body>
        </html>
    

    使用 cmd 运行 > python app.py

    【讨论】:

      【解决方案2】:

      /upload 处理程序并不意味着您可以直接调用,无论是从浏览器还是 python 应用程序。相反,您的应用程序将需要进行两次调用:第一次调用您的服务器以获取临时 URL,然后第二次调用该 URL,该 URL 将直接与 blobstore 连接。您的服务器应使用 blobstoreService.createUploadUrl 生成该临时 URL,如您链接的文档的 this section 的第 1 步所述。

      在第二次调用(上传)的过程中,blobstore 将直接调用您的上传处理程序以通知您的应用有关新 blob 的信息。这就是blobstoreService.getUploads(req) 知道如何解释的。

      因此,您的 python 应用程序将进行 2 次调用,并且您的服务器还将处理 2 个请求。第一个请求直接来自简单地请求 url 的 python 应用程序。第二个请求将在上传期间发生,但实际上将直接来自 blobstore。

      【讨论】:

      • 亲爱的埃里克!这是有道理的:)感谢您的快速回复。我会详细介绍!
      • 有没有更好的方法将文件(图像)从我的 python 应用程序上传到 blobstore?
      • 不,这是最好的方法。这是谷歌自己在我们链接的文档中概述的方式。您可以考虑改用 Google Cloud Storage,您可以以同样的方式将其上传到(请参阅文档中的 this section),但也提供其他选项。不过,我对其他选项不太熟悉,所以恐怕这是我能提供的最大帮助。
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2014-06-05
      • 2021-09-16
      • 1970-01-01
      • 1970-01-01
      • 2018-12-31
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多