Flask-Uploads IOError: [Errno 2] No such file or directory
Asked Answered
J

4

15

So, I've been trying to add an image uploader to my code, but I've been running into issues. Even though I thought I had my upload_folder configured properly, I keep getting errors like: IOError: [Errno 2] No such file or directory: '/static/uploads/compressor.jpg' even though the file/directory exists.

Here's the code:

in config.py

UPLOAD_FOLDER = 'static/uploads'

in init.py

app.config['UPLOAD_FOLDER'] = UPLOAD_FOLDER

in views.py

@app.route('/fileupload', methods=['GET', 'POST'])
def upload_file():
    if request.method == 'POST':
        #check if the post request has the file part
        if 'file' not in request.files:
            flash('No file part')
            return redirect(request.url)
        file = request.files['file']
        # if user does not select file, browser also
        #submit an empty part without filename
        if file.filename == '':
            flash('No selected file')
            return redirect(request.url)
        if file and allowed_file(file.filename):
            filename = secure_filename(file.filename)
            file.save(os.path.join(app.config['UPLOAD_FOLDER'], filename))
            return redirect(url_for('uploaded_file',
                                    filename=filename))
    return '''
    <!doctype html>
    <title>Upload new File</title>
    <h>UPload new file</h1>
    <form action="" method=post enctype=multipart/form-data>
        <p><input type=file name=file>
            <input type=submit value=Upload>
    </form>
    '''

@app.route('/uploads/<filename>')
def uploaded_file(filename):
    return send_from_directory(app.config['UPLOAD_FOLDER'],
                               filename)

My folder structure is as follows

  /project folder
   --/app
   ----/static
   --------/uploads
   ----/templates
   ----_init__.py
   ----views.py
   --config.py

When I use /tmp/ to store it in memory the uploader works no problem. I assume it's not looking in the proper path for my folder. Can anyone help here? I'm a very amateur python developer.

Jabon answered 18/6, 2016 at 21:17 Comment(0)
R
19

Both /tmp and /static/uploads/.., are absolute paths. And your code is looking in the / folder instead of looking in your project's folder. You should use the absolute path to point at your folder /path/to/your/project/static/uploads/.. or use a path relative to the code being executed such as ./static/uploads.

You can also use the following snippet to generate the absolute path:

from os.path import join, dirname, realpath

UPLOADS_PATH = join(dirname(realpath(__file__)), 'static/uploads/..')
Rebba answered 18/6, 2016 at 21:28 Comment(8)
I've seen this suggestion before, but maybe I'm implementing it wrong? For example, I just changed my UPLOAD_FOLDER to UPLOAD_FOLDER = './static/uploads/' and this is the error it's returning: IOError: [Errno 2] No such file or directory: './static/uploads/Bathroom_Kitchen_Home_Decor_Outdoor__More_-_Google_Chrome_2016-06-18_13.32.14.png'Jabon
Made some changes to my code just to test. Ended up getting the exact same errors: upload_form = UCGUploadForm() if upload_form.validate_on_submit(): filename = secure_filename(upload_form.photo.data.filename) upload_form.photo.data.save(UPLOAD_FOLDER + filename) else: filename = None I also adjusted Forms.py. class UCGUploadForm(Form): photo = FileField('image', validators=[ FileRequired(), FileAllowed(['jpg', 'jpeg', 'png'], 'Images only!') ]) Jabon
Just to be sure, does it work properly on /tmp? if so, it should be a path problem: weather it's the wrong path, or the wrong permission. In the debugging process, print the value of the path from within the function and try to access it with the same user. I'm going to edit my answer to add a more pythonic way to get the correct path to your resource.Rebba
Just saw your second comment about OS path. That changed the error message! IOError: [Errno 2] No such file or directory: '/home/ubuntu/workspace/static/uploads/..IMG_0334.jpg' So now I just have to find the right folder within my workspace. Alternatively, how would I set this path to relative so that I can use the ./static option?Jabon
I tried adjusting it from realpath to relpath, but was encountering the same error as before.Jabon
Sorry for so many comments here. I adjusted my code for the upload folder to be basedir + filename (basedir is basedir = os.path.abspath(os.path.dirname(__file__)) which didn't return an error after testing! It grabbed workspaceurl/uploads/filename, but returned a "file not found"Jabon
In my case, putting a '/' in front of 'static' had caused the problem in os.path.join function. Putting '/' in front of the second parameter omits the first parameter of the join and directly behaves like the root folder 'c:\static\'.Douche
Thank you, wasted two hours on this problemNatalee
C
16

This worked for me:

basedir = os.path.abspath(os.path.dirname(__file__))

file.save(os.path.join(basedir, app.config['UPLOAD_FOLDER'], filename))
Coel answered 30/9, 2016 at 18:3 Comment(1)
upvoted. Also wanted to add that best use os.path.join("path", "to", "your", "folder") as this is OS independent opposed to path/to/your/folder which is notMatelda
B
0

@jidesakin's solutions works but here is another solution:

Move your uploads folder from static directory back to your project directory where your app folder is, the folder where your app and environment folders are.

Your structure will be like:

'projectfolder
--/app
      --config.py
      --__init__.py
------/static
------/templates
------config
--uploads

Then change the content of you upload folder from 'static/uploads' to 'uploads' ...

Bignonia answered 26/6, 2021 at 17:6 Comment(0)
O
0

In init.py

app.config.from_mapping(
    SECRET_KEY='dev',
    DATABASE=os.path.join(app.instance_path, 'database.sqlite'),
    UPLOAD_FOLDER= os.path.join(app.static_folder, 'uploads'),
    ALLOWED_EXTENSIONS=set(['.png', '.jpg', '.jpeg', '.gif']),
)
Obfuscate answered 11/2 at 7:9 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.