Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Uploading files to Google Cloud Storage with Flask

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 ?

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})

Thanks for your help !!

like image 725
merqurio Avatar asked Oct 13 '14 18:10

merqurio


People also ask

How do I import a CSV file into Google Cloud Storage?

Find your app and select your app options caret ( ^ ). Select All Settings > Raw Data Export > CSV Upload. Select Google Cloud Storage from the dropdown menu. Upload your Service Account Key credential file.

Can I upload files to Google Cloud Storage from URL?

It is not possible to upload a file to Google Cloud Storage directly from an URL. Since you are running the script from a local environment, the file contents that you want to upload, need to be in that same environment. This means that the contents of the url need to either be stored in the memory, or in a file.

How do I upload files to my Flask?

Python for web development using Flask Handling file upload in Flask is very easy. It needs an HTML form with its enctype attribute set to 'multipart/form-data', posting the file to a URL. The URL handler fetches file from request. files[] object and saves it to the desired location.


1 Answers

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

try this:

@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})

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/

like image 68
Rafael Barros Avatar answered Nov 14 '22 06:11

Rafael Barros