how to upload multiple files using flask in python - python

Here is my code for multiple files upload:
HTML CODE:
Browse <input type="file" name="pro_attachment1" id="pro_attachment1" multiple>
PYTHON CODE:
pro_attachment = request.files.getlist('pro_attachment1')
for upload in pro_attachment:
filename = upload.filename.rsplit("/")[0]
destination = os.path.join(application.config['UPLOAD_FOLDER'], filename)
print "Accept incoming file:", filename
print "Save it to:", destination
upload.save(destination)
But it uploads a single file instead of multiple files.

How to
In the template, you need to add mulitple attribute in upload input:
<form method="POST" enctype="multipart/form-data">
<input type="file" name="photos" multiple>
<input type="submit" value="Submit">
</form>
Then in view function, the uploaded files can get as a list through request.files.getlist('photos'). Loop this list and call save() method on each item (werkzeug.datastructures.FileStorage) will save them at given path:
import os
from flask import Flask, request, render_template, redirect
app = Flask(__name__)
app.config['UPLOAD_PATH'] = '/the/path/to/save'
#app.route('/upload', methods=['GET', 'POST'])
def upload():
if request.method == 'POST' and 'photo' in request.files:
for f in request.files.getlist('photo'):
f.save(os.path.join(app.config['UPLOAD_PATH'], f.filename))
return 'Upload completed.'
return render_template('upload.html')
Furthermore, you may need to use secure_filename() to clean filename:
# ...
from werkzeug.utils import secure_filename
# ...
for f in request.files.getlist('photo'):
filename = secure_filename(f.filename)
f.save(os.path.join(app.config['UPLOAD_PATH'], filename))
# ...
You can also generate a random filename with this method.
Full demo
View:
import os
from flask import Flask, request, render_template
from werkzeug.utils import secure_filename
app = Flask(__name__)
app.config['UPLOAD_PATH'] = '/the/path/to/save'
#main.route('/upload', methods=['GET', 'POST'])
def upload():
form = UploadForm()
if form.validate_on_submit() and 'photo' in request.files:
for f in request.files.getlist('photo'):
filename = secure_filename(f.filename)
f.save(os.path.join(app.config['UPLOAD_PATH'], filename))
return 'Upload completed.'
return render_template('upload.html', form=form)
Form:
from flask_wtf import FlaskForm
from wtforms import SubmitField
from flask_wtf.file import FileField, FileAllowed, FileRequired
class UploadForm(FlaskForm):
photo = FileField('Image', validators=[
FileRequired(),
FileAllowed(photos, 'Image only!')
])
submit = SubmitField('Submit')
Template:
<form method="POST" enctype="multipart/form-data">
{{ form.hidden_tag() }}
{{ form.photo(multiple="multiple") }}
{{ form.submit }}
</form>
More
For better upload experience, you can try Flask-Dropzone.

Your code looks perfect.
I think the only mistake your making is splitting and taking the first value.
And also i dont know about the rsplit(), but the split() works perfect for me.
HTML CODE
<input id="upload_img" name="zip_folder" type="file" multiple webkitdirectory >
PYTHON CODE
#app.route('/zipped',methods = ['GET', 'POST'])
def zipped():
if request.method == 'POST':
f = request.files.getlist("zip_folder")
print f
for zipfile in f:
filename = zipfile.filename.split('/')[1]
print zipfile.filename.split('/')[1]
zipfile.save(os.path.join(app.config['ZIPPED_FILE'], filename))
return render_template('final.html')

Related

Method not allowed 405 Error in Flask Api

I am currently trying to upload a picture and later on process it. But I am getting an 405 error and I don't know how to fix it.
#app.route('/upload')
def upload():
return render_template('upload.html')
#app.route('/uploader', methods = ['GET', 'POST'])
def upload_f():
if request.method == 'POST':
f = request.files['file']
f.save(f.filename)
return 'file uploaded successfully'
The html form
<html>
<body>
<form action = "http://localhost:5000/uploader" method = "POST"
enctype = "multipart/form-data">
<input type = "file" name = "file" />
<input type = "submit"/>
</form>
</body>
</html>
From Miguel Grinberg's Handling File Uploads With Flask tutorial:
import imghdr
import os
from flask import Flask, render_template, request, redirect, url_for, abort, \
send_from_directory
from werkzeug.utils import secure_filename
app = Flask(__name__)
app.config['MAX_CONTENT_LENGTH'] = 1024 * 1024
app.config['UPLOAD_EXTENSIONS'] = ['.jpg', '.png', '.gif']
app.config['UPLOAD_PATH'] = 'uploads'
def validate_image(stream):
header = stream.read(512) # 512 bytes should be enough for a header check
stream.seek(0) # reset stream pointer
format = imghdr.what(None, header)
if not format:
return None
return '.' + (format if format != 'jpeg' else 'jpg')
#app.route('/')
def index():
files = os.listdir(app.config['UPLOAD_PATH'])
return render_template('index.html', files=files)
#app.route('/', methods=['POST'])
def upload_files():
uploaded_file = request.files['file']
filename = secure_filename(uploaded_file.filename)
if filename != '':
file_ext = os.path.splitext(filename)[1]
if file_ext not in app.config['UPLOAD_EXTENSIONS'] or \
file_ext != validate_image(uploaded_file.stream):
abort(400)
uploaded_file.save(os.path.join(app.config['UPLOAD_PATH'], filename))
return redirect(url_for('index'))
#app.route('/uploads/<filename>')
def upload(filename):
return send_from_directory(app.config['UPLOAD_PATH'], filename)
<html>
<head>
<title>File Upload</title>
</head>
<body>
<h1>File Upload</h1>
<form method="POST" action="" enctype="multipart/form-data">
<p><input type="file" name="file"></p>
<p><input type="submit" value="Submit"></p>
</form>
<hr>
{% for file in files %}
<img src="{{ url_for('upload', filename=file) }}" style="width: 64px">
{% endfor %}
</body>
</html>

Uploading and reading a CSV file with Flask

I'm currently in the process of making a program to upload and read csv files. I'm throwing a key error when submitting a file to be uploaded and can't really seem to figure out why and was hoping for some help. It uploaded and saved the file before I tried adding the read file functionality but after that, it started having issues. The error is saying that 'filename' is a key error even though it seemed to work fine before I tried reading the file. Help or leading me down the right path would be greatly appreciated. Thanks so much!
Views.py
from flask import render_template, request, redirect
from app import app
import os
import csv
#app.route('/', methods=["GET", "POST"])
def index():
data = []
if request.method == 'POST':
if request.files:
uploaded_file = request.files['filename'] # This line uses the same variable and worked fine
uploaded_file.save(os.path.join(app.config['FILE_UPLOADS'], uploaded_file.filename))
f = request.form['filename'] # This is the line throwing the error
with open(f) as file:
csv_file = csv.reader(file)
for row in csv_file:
data.append(row)
return redirect(request.url)
return render_template('index.html', data=data)
#app.route('/help')
def help():
return render_template('help.html')
app.config['FILE_UPLOADS'] = "C:\\Users\\Zachary\\Documents\\VSCode_Projects\\monday_webapp\\app\\static\\file\\uploads"
Index.html
{% extends "base.html" %}
{% block title %}Home{% endblock %}
{% block body %}
<div class="jumbotron">
<h1 style='text-align: center'>Zach's Web Application</h1>
</div>
<div>
<p class="lead">Upload a csv file to view its data.</p>
<form method="POST" enctype="multipart/form-data" action="/">
<input type="file" id="myFile" name="filename" accept=".csv">
<input type="submit">
</form>
</div>
<div>
{{ data }}
</div>
<div>
{% endblock %}
In flask request.form["input_name"] is used to get the input data, but not for input type=files which are accesible through request.files["input_name"], always using enctype=multipart/form-data in the form. You can get more info in the oficial documentation:
https://flask.palletsprojects.com/en/1.1.x/patterns/fileuploads/
On the other hand, request.files['filename'] is a FileStorage type, the function open(f) expects str, bytes or os.PathLike object, not FileStorage.
The following code should works:
from flask import render_template, request, redirect
from app import app
import os
import csv
#app.route('/', methods=["GET", "POST"])
def index():
data = []
if request.method == 'POST':
if request.files:
uploaded_file = request.files['filename'] # This line uses the same variable and worked fine
filepath = os.path.join(app.config['FILE_UPLOADS'], uploaded_file.filename)
uploaded_file.save(filepath)
with open(filepath) as file:
csv_file = csv.reader(file)
for row in csv_file:
data.append(row)
return redirect(request.url)
return render_template('index.html', data=data)
#app.route('/help')
def help():
return render_template('help.html')
app.config['FILE_UPLOADS'] = "C:\\Users\\Zachary\\Documents\\VSCode_Projects\\monday_webapp\\app\\static\\file\\uploads"

Display Submitted Image on Redirected Page via Flask and html [duplicate]

This question already has answers here:
Post values from an HTML form and access them in a Flask view
(2 answers)
Closed 5 years ago.
I'm attempting to create a page that takes in a user-submitted image, and automatically redirects them to a new page where the image is rendered. Much of my code is borrowed from here: How to pass uploaded image to template.html in Flask. But I can't seem to get it to work; I run into a 400: Bad Request. It seems to me that the image is not saving under /static/images, but I am not sure why.
Here is the submission form in index.html:
<form method="POST" action="{{ url_for('predict') }}" enctype="multipart/form-data">
<label for="file-input" class="custom-file-upload">
<i class="fa fa-cloud-upload"></i> Upload Image
</label>
<input name="image-input" id="file-input" type="file" align="center" onchange="this.form.submit();">
</form>
Here is my app.py code:
from flask import Flask, render_template, request, url_for, send_from_directory, redirect
from werkzeug import secure_filename
import os
UPLOAD_FOLDER = '/static/images/'
ALLOWED_EXTENSIONS = set(['png', 'jpg', 'jpeg', 'tiff'])
def allowed_file(filename):
return '.' in filename and \
filename.rsplit('.', 1)[1] in ALLOWED_EXTENSIONS
app = Flask(__name__)
app.config['UPLOAD_FOLDER'] = UPLOAD_FOLDER
#app.route('/')
def index():
return render_template("index.html")
#app.route('/predict/', methods=['POST', 'GET'])
def predict():
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))
return redirect(url_for('uploaded_file', filename=filename))
return '''
<!doctype html>
<title>Upload new File</title>
<h1>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('/show/<filename>')
def uploaded_file(filename):
return render_template('classify.html', filename=filename)
#app.route('/uploads/<filename>')
def send_file(filename):
return send_from_directory(UPLOAD_FOLDER, filename)
if __name__ == '__main__':
app.run(debug=True)
And finally, I try to render it in classify.html, with the following code:
{% if filename %}
<h1>some text<img src="{{ url_for('send_file', filename=filename) }}"> more text!</h1>
{% else %}
<h1>no image for whatever reason</h1>
{% endif %}
Where am I going wrong here?
Looks like I was missing an argument in my input: name=file in index.html. Adding that fixed the error. Altogether, the input line looks like this:
<input id="file-input" name=file type="file" align="center" onchange="this.form.submit();">

Why is if request.method == 'POST' and 'photo' in request.files

I have this little example script. It gets a file from a HTML an uploads it to the server. That part works just fine. Please see the script below.
I would like to take some action if no file is selected in the form. I thought the following would evaluate to false if no file was selected in the HTML form, but it seams to be always true.
if request.method == 'POST' and 'photo' in request.files:
Either a file is selected or not 'Text to print' is returned.
What am I missing here?
Any hint is appreciated.
Best regards
Kresten
from flask import Flask, render_template, request
from flask_uploads import UploadSet, configure_uploads, IMAGES
app = Flask(__name__)
photos = UploadSet('photos', IMAGES)
app.config['UPLOADED_PHOTOS_DEST'] = 'static'
configure_uploads(app, photos)
#app.route('/upload', methods=['GET', 'POST'])
def upload():
if request.method == 'POST' and 'photo' in request.files:
filename = photos.url(request.files['photo'])
fil = request.files['photo']
return 'Text to print'
return render_template('upload.html')
if __name__ == '__main__':
app.run(debug=True)
app.run(host='0.0.0.0')
The HTML template:
<html>
<head>
<title>Upload</title>
</head>
<body>
<form method=POST enctype=multipart/form-data action="{{ url_for('upload') }}">
<input type=file name=photo>
<input type="submit">
</form>
</body>
</html>
(Thanks to Danila for saving my day)
In your case photo always will be in request.files, but filename not(can be empty string). Just change condition to:
#app.route('/upload', methods=['GET', 'POST'])
def upload():
if request.method == 'POST' and request.files['photo'].filename:
filename = photos.url(request.files['photo'])
fil = request.files['photo']
return 'Text to print'
return render_template('upload.html')

Flask, How can I response the picture on the page

I am new to Flask and web development, I want to upload a picture and process it by my deep learning application and then response the processed picture on the page, here is my frame work code
# coding: utf-8
import os
import uuid
import PIL.Image as Image
from werkzeug import secure_filename
from flask import Flask, url_for, render_template, request, url_for, redirect, send_from_directory
ALLOWED_EXTENSIONS = set(list(['png', 'jpg', 'jpeg']))
UPLOAD_FOLDER = '/tmp'
app = Flask(__name__)
app.config['UPLOAD_FOLDER'] = UPLOAD_FOLDER
def process_image(file_path):
"""
resize image to 32x32
:param file_path: file path
:return:
"""
img = Image.open(file_path, mode='r')
return img.resize([32,32], Image.ANTIALIAS)
def allowed_file(filename):
return '.' in filename and filename.rsplit('.', 1)[1] in ALLOWED_EXTENSIONS
#app.route('/', methods=['GET', 'POST'])
def upload_file():
_path = None
if request.method == 'POST':
_file = request.files['file']
print(_file)
if _file and allowed_file(_file.filename):
filename = secure_filename(_file.filename)
_path = os.path.join(app.config['UPLOAD_FOLDER'], filename)
_file.save(_path)
return show_pic(deep_learning(_path))
return '''
<!DOCTYPE html>
<title>Web App/title>
<h1>Deep Learning Web App</h1>
<form action="/" method="POST" enctype="multipart/form-data">
<input type="file" name="file" />
<input type="submit" value="submit" />
</form>
'''
#app.route('/uploads/<filename>')
def uploaded_file(filename):
return send_from_directory(app.config['UPLOAD_FOLDER'], filename)
if __name__ == '__main__':
app.run()
As you can see it, I have implemented upload picture function and the function deep_learning(path), and it return the path of processed picture, I need to implement function show_pic(), how can I do that?
Create a template with your html skeleton and pass the image path to the render_template() function.
result.html
<html>
<img src="{{ image_path }}">
</html>
Add this to your view function:
return render_template('result.html', image_path=deep_learning(_path))
For this to work your files need to be located in the staticdirectory or a subdirectory.
Or you can define _file(processed file) with None value below form tag check if file not none then show it:
#app.route('/', methods=['GET', 'POST'])
def upload_file():
_path = None
_file = None
if request.method == 'POST':
_file = request.files['file']
print(_file)
if _file and allowed_file(_file.filename):
filename = secure_filename(_file.filename)
_path = os.path.join(app.config['UPLOAD_FOLDER'], filename)
_file.save(_path)
return '''
<!DOCTYPE html>
<title>Web App/title>
<h1>Deep Learning Web App</h1>
<form ...>
...
</form>
{% if _file%}
<img src="{{url_for('uploaded_file', filename=_file) }}" >
{% endif %}
'''

Categories

Resources