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 !!
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.
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.
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.
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/
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With