使用 Flask 将文件上传到 Google Cloud Storage

问题描述

我正在尝试使用 Flask 通过 App Engine 实例将一些图像上传到 GCS,但是每次上传文件时,当我下载它时,我都会得到一个损坏的文件.我做错了什么?

I'm trying to upload some images to GCS via an App Engine instance using Flask, but every time the file it's uploaded, when I download it I get a corrupt file. What am I doing wrong ?

我已经按照文档中的方式下载并使用了 Google Cloud Storage 客户端.

I've downloaded and used the Google Cloud Storage client the way is in the docs.

@app.route('/upload', methods=['POST'])
def upload():
    if request.method == 'POST':
        file = request.files['file']
        extension = secure_filename(file.filename).rsplit('.', 1)[1]
        options = {}
        options['retry_params'] = gcs.RetryParams(backoff_factor=1.1)
        options['content_type'] = 'image/' + extension
        bucket_name = "gcs-tester-app"
        path = '/' + bucket_name + '/' + str(secure_filename(file.filename))
        if file and allowed_file(file.filename):
            try:
                with gcs.open(path, 'w', **options) as f:
                    f.write(str(file))
                    print jsonify({"success": True})
                return jsonify({"success": True})
            except Exception as e:
                logging.exception(e)
                return jsonify({"success": False})

感谢您的帮助!!


解决方案

您正在上传(写入 gcs 流)文件对象的 str 表示,而不是文件内容.

You're uploading (writing to the gcs stream) the str representation of the file object, not the file contents.

试试这个:

@app.route('/upload', methods=['POST'])
def upload():
    if request.method == 'POST':
        file = request.files['file']
        extension = secure_filename(file.filename).rsplit('.', 1)[1]
        options = {}
        options['retry_params'] = gcs.RetryParams(backoff_factor=1.1)
        options['content_type'] = 'image/' + extension
        bucket_name = "gcs-tester-app"
        path = '/' + bucket_name + '/' + str(secure_filename(file.filename))
        if file and allowed_file(file.filename):
            try:
                with gcs.open(path, 'w', **options) as f:
                    f.write(file.stream.read())# instead of f.write(str(file))
                    print jsonify({"success": True})
                return jsonify({"success": True})
            except Exception as e:
                logging.exception(e)
                return jsonify({"success": False})

但这不是最有效的方法,而且,直接从应用程序引擎上传文件有 32mb 的上限,避免这种情况的方法是使用 GCS 签署上传 url 并直接从GCS 的前端,或者您可以使用 blobstore 和处理程序创建文件上传 url 来执行上传后处理,如下所示:https://cloud.google.com/appengine/docs/python/blobstore/

But this is not the most efficient way to do this, also, there is a 32mb cap on file uploads straight from app engine, the way to avoid this is by signing an upload url with GCS and upload the file directly from the front-end to GCS, or you can create a file upload url with blobstore and a handler to do the post-upload processing, as specified here: https://cloud.google.com/appengine/docs/python/blobstore/

相关文章