简体   繁体   中英

I'm unable to upload a file whose name has a space in it to Google Cloud Storage using Python. What am I doing wrong?

I'm new to Python and Google Cloud. Using Flask I have created a web page where a user can choose a file from their computer and upload it to a GCS bucket that I have already created. I'm following Google's documentation example which uses the Google Python API library. I'm able to upload files whose names are just a single word, like 'image' but if my file is named 'image one' then I get the following error- FileNotFoundError: [Errno 2] No such file or directory: 'image one.jpg'

Here's my code:

@app.route('/upload', methods = ['GET'  , 'POST'])
def upload():
    if request.method == "POST":
        f = request.files['file']
        f.save(secure_filename(f.filename))
        gcs_upload(f.filename)

def gcs_upload(filename):
    storage_client = storage.Client()   # instantiate a client
    bucket = storage_client.bucket('bucket_name')
    blob=bucket.blob(filename)      # file name at the destination should be the same
    blob.upload_from_filename(filename)     # file to be uploaded

if __name__ == '__main__':
    os.environ['OAUTHLIB_INSECURE_TRANSPORT'] = '1'
    app.run(port=8080, debug=True)

If I'm writing a production level application then I would want a user to upload a file even if it has spaces in its name.

I reproduced the issue on my own project and the problem you face arise from the use of secure_filename function. According to werkzeug documentation the function secure_filename will replace any whitespace of the user provided filename with an underscore. Adding some logging you might see that:

f.filename # 'foo bar.png'
secure_filename(f.filename) # 'foo_bar.png'

So, when you call the gcs_upload function you're passing the original filename instead of the one returned by secure_filename and as the error message points out such file does not exist.

To solve the issue just change your upload function to:

def upload():
    if request.method == "POST":
        f = request.files['file']
        filename = secure_filename(f.filename)
        f.save(filename)
        gcs_upload(filename)

Try to quote filename (by using urllib ) before. This is an example by using python3 :

import urllib.parse
filename = "files name.jpg"
new_file = str(urllib.parse.quote(filename))

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM