I'm writing a small web-shop using Python and web-framework Flask.
I'm trying to add image file in SQLite database using this
#app.route('/new_product_reg', methods=['POST', 'GET'])
def new_product_reg():
if request.method == 'POST':
img_name = request.form['product_img']
product_img = readImage(img_name)
product_img_binary = lite.Binary(product_img)
product_data = NewProduct(product_img=product_img_binary)
try:
db.session.add(product_data)
db.session.commit()
return redirect('/new_product_reg')
except:
return "ERROR!"
Where readImage is
def readImage(img_name):
try:
fin = open(img_name, 'rb')
img = fin.read()
return img
except:
print("ERROR!!")
Form where I taked the image:
<form enctype="multipart/form-data" method="post">
<input type="file" name=product_img id="product_img"><br>
<input type="submit" value="Submit">
</from>
And the class of database where I want to add image looks like that:
class NewProduct(db.Model):
product_img = db.Column(db.BLOB())
def __repr__(self):
return '<NewProduct %r>' % self.id
So, the problem is, when I added image by pressing "Add Image" button in form and pressed "Submit" button I get the BadRequestKeyError 400. The debugger said that the problem is in img_name = request.form['product_img']. So how can I fix that and what I'm doing wrong?
At first I want to say that storing large and medium pictures directly in SQLite is not a very good solution. Learn more here: https://www.sqlite.org/intern-v-extern-blob.html
For your problem, try to do as in the documentation:
https://flask.palletsprojects.com/en/1.1.x/patterns/fileuploads/
Note there is used:
# 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)
And perhaps this article will also help you:
Python SQLite BLOB to Insert and Retrieve file and images
Related
So I've been working on a Flask application where the user submits a file to a form, the server takes it and manipulates it, then returns the edited file back to the user. I am new to Flask and web dev in general, so bear with me. I have already set up the website with the form and a filefield, but Im not exactly sure how I can get the data from the file. Do i have to store it on the server? If I do, do I have to delete after im done?
Here is what I've got so far in my routes
#app.route('/mysite', methods=['post', 'get'])
def mysite():
form = mysiteform()
if request.method == 'POST' and form.validate():
file = form.file.data.read()
filename = secure_filename(file.filename)
return render_template('mysite.html', title = 'hello world!', form=form)
In Flask official documentation site, there is a file uploader example as below:
#app.route('/', 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 the user does not select a file, the browser submits an
# empty file without a 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('download_file', name=filename))
return '''
<!doctype html>
<title>Upload new File</title>
<h1>Upload new File</h1>
<form method=post enctype=multipart/form-data>
<input type=file name=file>
<input type=submit value=Upload>
</form>
'''
Here is how you can get the file content: file = request.files['file'] and of course you can do further manipulation on the file.
Here is how you can save the file file.save(os.path.join(app.config['UPLOAD_FOLDER'], filename)). It's really up to you if you want to save the file and return the file later or just modify it in memory and return it immediately.
I have a Flask app that works the first time, after that the html always show the first predicted image even though the new predicted image is written to the folder
I have tried deleting the image from the upload folder, but the original prediction is staying.
Below is my flask app
UPLOAD_FOLDER = ''
ALLOWED_EXTENSIONS = set(['jpg', 'png'])
app = Flask(__name__)
app.config['UPLOAD_FOLDER'] = UPLOAD_FOLDER
def allowed_file(filename):
return '.' in filename and filename.rsplit('.', 1)[1].lower() in
ALLOWED_EXTENSIONS
#app.route('/', 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)
#filename = file.filename
file.save(os.path.join(app.config['UPLOAD_FOLDER'], filename))
image = open_image(filename)
image_url = url_for('uploaded_file', filename=filename)
think = learn.predict(image)
think_np = np.array(think[1])
think_np.shape = (256,256)
think_np = think_np.astype(int)
think_np[think_np > 0] = 255
think_im = Image.fromarray((think_np).astype('uint8'), mode='L')
think_im.save(os.path.join(app.config['UPLOAD_FOLDER'], 'think2_im.png'))
think_im_url = url_for('uploaded_file', filename='think2_im.png')
print(think_im_url)
#image.show(y=learn.predict(image)[0])
return '''<h1>The cell image is:</h1>
<img src= "{}" height = "85" width="200"/>
<h1>The cell segmentation is:</h1>
<img src= "{}" height = "85" width="200"/>'''.format(image_url, think_im_url)
return '''
<!doctype html>
<title>Upload new File</title>
<h1>Upload an image of Cells</h1>
<form method=post enctype=multipart/form-data>
<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)
The first time I run this everything works great. But, if I run again, the think_im_url always shows the first predicted image. Even if I restart the kernel. Even if I go into the upload folder and delete the image. Also, though, the predicted image written to the upload folder is the correct (new) predicted image. Just what is showing in the HTML always stays the same.
If I go into the code and change the name, i.e. change "think2_img.png" to "think3_img.png", then the process starts again. The first time works great, but even though new predictions overwrite the "think" prediction in the upload folder, the HTML only shows the original prediction.
The image_URL changes each time like it is supposed to.
trying to place my text classification model into flask applications using CSV file upload to read data without saving the uploaded .csv file and throw it into my classifier model print it on the result pages. below example code of my attempt :
#app.route('/', methods=['GET', 'POST'])
def upload_file():
if request.method == 'POST':
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))
file.stream.seek(0)
myfile = file.file
dataframe = pd.read_csv(myfile)
return
else:
return "Not Allowed"
return render_template("home.html")
This is my form
<form action="" method=post enctype=multipart/form-data>
<input type=file name="file[]" multiple>
<input type=submit value=Upload>
</form>
exception occurred here
NameError: name 'allowed_file' is not defined
Any idea about this kind of issue ?
I think you are using this part of documentation : (http://flask.pocoo.org/docs/0.12/patterns/fileuploads/)
But you have to add the function :
def allowed_file(filename):
return '.' in filename and filename.rsplit('.', 1)[1].lower() in ALLOWED_EXTENSIONS`
Have you created a function called allowed_file() in your module? Or have you created it in another module and forgotten to import it? You’re feeding your filename into the function allowed_file() so that it can check whether the filename is permitted, but the NameError indicates that the function allowed_file() cannot be found.
I need to upload profile images into diferent folders in Django. So, I have a folder for each account, and the profile image have to go to the specific folder. How can I do that?
Here is my uploadprofile.html
<form action="{% url 'uploadimage' %}" enctype="multipart/form-data" method="POST">
{% csrf_token %}
<input type="file" name="avatar" accept="image/gif, image/jpeg, image/png">
<button type="submit">Upload</button>
</form>
And here is my view in views.py
def uploadimage(request):
img = request.FILES['avatar'] #Here I get the file name, THIS WORKS
#Here is where I create the folder to the specified profile using the user id, THIS WORKS TOO
if not os.path.exists('static/profile/' + str(request.session['user_id'])):
os.mkdir('static/profile/' + str(request.session['user_id']))
#Here is where I create the name of the path to save as a VARCHAR field, THIS WORKS TOO
avatar = "../../static/profile/" + str(request.session['user_id']) + "/" + str(img)
#THEN I HAVE TO COPY THE FILE IN img TO THE CREATED FOLDER
return redirect(request, 'myapp/upload.html')
You can pass a callable to upload_to. Basically, what it means is whatever value that callable returns, the image will be uploaded in that path.
Example:
def get_upload_path(instance, filename):
return "%s/%s" % (instance.user.id, filename)
class MyModel:
user = ...
image = models.FileField(upload_to=get_upload_path)
There's more information in the docs and an example too, though similar to what I posted above.
By looking at Django docs what you get when you do img = request.FILES['avatar'] you get a file descriptor that points to an open file with your image.
Then you should to dump the contents in your actual avatar path, right?
#Here is where I create the name of the path to save as a VARCHAR field, THIS WORKS TOO
avatar = "../../static/profile/" + str(request.session['user_id']) + "/" + str(img)
# # # # #
with open(avatar, 'wb') as actual_file:
actual_file.write(img.read())
# # # # #
return redirect(request, 'myapp/upload.html')
Beware: the code is untested.
from django.shortcuts import render
from django.conf import settings
from django.core.files.storage import FileSystemStorage
def uploadimage(request):
if request.method == 'POST' and request.FILES['avatar']:
img = request.FILES['avatar']
fs = FileSystemStorage()
#To copy image to the base folder
#filename = fs.save(img.name, img)
#To save in a specified folder
filename = fs.save('static/profile/'+img.name, img)
uploaded_file_url = fs.url(filename) #To get the file`s url
return render(request, 'myapp/upload.html', {
'uploaded_file_url': uploaded_file_url
})
return render(request, 'myapp/upload.html')
Is there a way to receive multiple uploaded files with Flask? I've tried the following:
<form method="POST" enctype="multipart/form-data" action="/upload">
<input type="file" name="file[]" multiple="">
<input type="submit" value="add">
</form>
And then printed the contents of request.files['file']:
#app.route('/upload', methods=['POST'])
def upload():
if not _upload_dir:
raise ValueError('Uploads are disabled.')
uploaded_file = flask.request.files['file']
print uploaded_file
media.add_for_upload(uploaded_file, _upload_dir)
return flask.redirect(flask.url_for('_main'))
If I upload multiple files, it only prints the first file in the set:
<FileStorage: u'test_file.mp3' ('audio/mp3')>
Is there a way to receive multiple files using Flask's built-in upload handling? Thanks for any help!
You can use method getlist of flask.request.files, for example:
#app.route("/upload", methods=["POST"])
def upload():
uploaded_files = flask.request.files.getlist("file[]")
print uploaded_files
return ""
#app.route('/upload', methods=['GET','POST'])
def upload():
if flask.request.method == "POST":
files = flask.request.files.getlist("file")
for file in files:
file.save(os.path.join(app.config['UPLOAD_FOLDER'], file.filename))
It works for me.
for UPLOAD_FOLDER if you need add this just after app = flask.Flask(name)
UPLOAD_FOLDER = 'static/upload'
app.config['UPLOAD_FOLDER'] = UPLOAD_FOLDER
Using Flask 1.0.2+:
files = request.files.getlist("images")
Where images is the key of the key/value pair. With the Value being the multiple images.
this is a working solution for flask version '1.0.2':
images = request.files.to_dict() #convert multidict to dict
for image in images: #image will be the key
print(images[image]) #this line will print value for the image key
file_name = images[image].filename
images[image].save(some_destination)
basically, images[image] has an image file with save function added to it
Now do whatever you like to do with the data.