Change upload path (UPLOAD_FOLDER) during the runtime - python

How to change the upload folder during the runtime? I'd like to be able to change the location where file will be uploaded to, but I don't know how.
I tried something like this, but I get KeyError:
#app.route('/upload', methods=['POST'])
def upload():
file = request.files['file']
path = 'uploads/text'
if file and allowed_file(file.filename):
filename = secure_filename(file.filename)
UPLOAD_FOLDER = path
file.save(os.path.join(app.config['UPLOAD_FOLDER'], filename))
return redirect(url_for('uploaded_file',
filename=filename))

You can try this
file.save(os.path.join(/path/to/save/, filename))
In yours
UPLOAD_FOLDER = path
file.save(os.path.join(UPLOAD_FOLDER, filename))

You can try the code below. It worked perfectly for me.
base_path = os.path.abspath(os.path.dirname(__file__))
upload_path = os.path.join(base_path, app.config['UPLOAD_FOLDER'])
f.save(os.path.join(upload_path, secure_filename(f.filename)))

Related

Flask FileStorage, load image from folder path

Refereed to this question I created flask API with POST image method to predict image with OpenCV, but I'm having trouble how to load and read image from image path folder.
My code is like this
app.config['UPLOAD_FOLDER'] = 'uploads/'
app.config['ALLOWED_EXTENSIONS'] = set(['png', 'jpg', 'jpeg'])
def allowed_file(filename):
return '.' in filename and filename.rsplit('.', 1)[1] in app.config['ALLOWED_EXTENSIONS']
def load_images_from_folder(folder):
images = []
for filename in os.listdir(folder):
img = cv2.imread(os.path.join(folder,filename))
if img is not None:
images.append(img)
return images
#app.route('/predict', methods=['POST'])
def predict():
file = request.files['file']
if file and allowed_file(file.filename):
filename = secure_filename(file.filename)
file.save(os.path.join(app.config['UPLOAD_FOLDER'], filename))
image_np = load_images_from_folder(str(file))
That code gives this error
File "E:\cvob\app.py", line 87, in load_images_from_folder
for filename in os.listdir(folder):
OSError: [WinError 123] The filename, directory name, or volume label syntax is incorrect: "<FileStorage: 'real-testing2.jpeg' ('image/jpeg')>"
What is the correct code? because I just learned to make this API

How to upload a file to your website hosted by Heroku?

I developed a website that would take a user provided file and extract relevant data out of it, I used Python/Flask for the backend and the website is stored in Heroku.
The application is working fine on my local machine, but when I run it in Heroku, whenever I attempt to upload/process a file I get this message on Heroku's logs:
2022-02-14T17:27:48.000421+00:00 app[web.1]: FileNotFoundError: [Errno 2] No such file or directory: '/application/uploads/report.html'
My python code that goes around the file uploading is:
app.config['UPLOAD_PATH'] = './application/uploads'
#app.route('/read', methods=['GET', 'POST'])
def read():
form = ReadForm()
if form.validate_on_submit():
if request.method == 'POST':
files = request.files.getlist('read')
for file in files:
if file and allowed_file(file.filename):
filename = secure_filename(file.filename)
file.save(os.path.join(app.config['UPLOAD_PATH'], filename))
return redirect(url_for('show'))
return render_template('read.html', form=form)
How do I make the uploaded files available to my application? After reading the file, the application just delete it.
I saw a question with a very similar title as mine, here:
How to upload file on website hosted by Heroku?
And one of the answers there, suggests using Amazon's S3, is it the only solution?
#buran pointed me to another post here which helped me solving the issue: Python Flask upload file to app folder on server (heroku)
I added the following to my path definition:
base_path = os.path.dirname(__file__)
So the final one would be:
# Path for the files upload part
app.config['UPLOAD_PATH'] = '/uploads'
base_path = os.path.dirname(__file__)
Then when uploading a file I refer to the path like this:
if file and allowed_file(file.filename):
filename = secure_filename(file.filename)
file.save(os.path.join(base_path + "/" + app.config['UPLOAD_PATH'], filename))
So, instead of:
file.save(os.path.join(app.config['UPLOAD_PATH'], filename))
I used:
file.save(os.path.join(base_path + "/" + app.config['UPLOAD_PATH'], filename))

Issues getting file extensions using os.path.splitext() method

I am working on a Flask blog application, and I am trying to separate a file extension from a filename. For example, for the filename "IMG_0503.jpg," I would like to get "IMG_0503" and ".jpg" separately. I tried the pathlib module and the os.path.splitext() method, but both return an empty file extension instead of ".jpg"
Here is my code with os.path.splitext():
uploaded_file = request.files['file']
print("UPLOADED_FILE:", uploaded_file)
filename = secure_filename(uploaded_file.filename)
print("FILENAME:", filename)
filename = os.path.splitext(filename)[0]
file_ext = os.path.splitext(filename)[1]
print("OS.PATH.SPLITEXT:", os.path.splitext(filename))
print("FILE_EXT:", file_ext)
This is the output of print statements:
UPLOADED_FILE: <FileStorage: 'IMG_0503.jpg' ('image/jpeg')>
FILENAME: IMG_0503.jpg
OS.PATH.SPLITEXT: ('IMG_0503', '')
FILE_EXT:
With the pathlib, the output is exactly the same, but I am using file_ext = pathlib.Path(filename).suffix to get the extension.
Can someone please help me to resolve this issue?
Alternate solution:
import pathlib
# function to return the file extension
file_extension = pathlib.Path('my_file.txt').suffix
print("File Extension: ", file_extension)
Output:
File Extension: .txt

Delete temporary folder after returning using send_file() of flask python on Windows Server

I am trying to delete a temporary folder where I save an image and do some processing on it and then return some results. I used shutil.rmtree(filepath) and it works correctly on Mac OS. However when I run it on Windows server, it fails with an error saying file is still in use.
I referred this question on stack overflow How to clean up temporary file used with send_file?
This answer using weak references helps in removing the error that was thrown on Windows, but the folder is still not deleted. Though it still works correctly on Mac OS.
How can I delete the temporary folder after the request has been completed on Windows system?
Here is my code snippet for your reference.
def post(self):
try:
if 'photo' not in request.files:
raise NoFilesError
file = request.files['photo']
print('file = ', file)
if file.filename == '':
raise NoFilesError
if file and self._allowed_file(file.filename):
filename = secure_filename(file.filename)
dir_path = os.path.join(BaseAPIConfig.UPLOAD_FOLDER, get_timestamp())
create_directory(dir_path)
file_path = os.path.join(dir_path, filename)
file.save(file_path)
img_proc_main(dir_path, filename)
image_filename = filename.rsplit('.', 1)[0]
image_format = filename.rsplit('.', 1)[1]
result_file = os.path.join(dir_path, image_filename + '_bb.' + image_format)
response = make_response(send_file(result_file))
file_remover = FileRemover()
file_remover.cleanup_once_done(response, dir_path)
return response
...
FileRemover class
class FileRemover(object):
def __init__(self):
self.weak_references = dict() # weak_ref -> filepath to remove
def cleanup_once_done(self, response, filepath):
wr = weakref.ref(response, self._do_cleanup)
self.weak_references[wr] = filepath
def _do_cleanup(self, wr):
filepath = self.weak_references[wr]
print('Deleting %s' % filepath)
shutil.rmtree(filepath, ignore_errors=True)
You are using ignore_errors=True, which hides away any exception that shutil.rmtree encounters.
There are many reasons why shutil.rmtree might fail to remove the directory—perhaps you simply don't have the correct permission on Windows. Setting ignore_errors to false will give you more indications of what's going on.

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

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.
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/..')
This worked for me:
basedir = os.path.abspath(os.path.dirname(__file__))
file.save(os.path.join(basedir, app.config['UPLOAD_FOLDER'], filename))
#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' ...

Categories

Resources