To make Dropzone Django-compliant set Dropzone's paramName option to:
paramName: (index) => 'file',
That documentation is outdated or misleading because Dropzone does more than that according to its source code:
// @options.paramName can be a function taking one parameter rather than a string.
// A parameter name for a file is obtained simply by calling this with an index number.
_getParamName(n) {
if (typeof this.options.paramName === "function") {
return this.options.paramName(n);
} else {
return `${this.options.paramName}${
this.options.uploadMultiple ? `[${n}]` : ""
}`;
}
}
JS, Dropzone option
paramName: (n) => 'my_param_name',
To make Dropzone Django-compliant set Dropzone's paramName option to:,The reason for that is Dropzone's way of handling the FormData name.,Fortunately, as you can see in the comment for the function above (and that is missing from the doc), paramName can also be a function.,The Django way of doing multiple files upload would be adding all the files into the FormData with the same name "file" (or whatever name you gave to Dropzone paramName option) that would end up in a single MultiValueDict called "file" in request.FILES
To make Dropzone Django-compliant set Dropzone's paramName option to:
paramName: (index) => 'file',
That documentation is outdated or misleading because Dropzone does more than that according to its source code:
// @options.paramName can be a function taking one parameter rather than a string.
// A parameter name for a file is obtained simply by calling this with an index number.
_getParamName(n) {
if (typeof this.options.paramName === "function") {
return this.options.paramName(n);
} else {
return `${this.options.paramName}${
this.options.uploadMultiple ? `[${n}]` : ""
}`;
}
}
JS, Dropzone option
paramName: (n) => 'my_param_name',
Here are the examples of the python api flask.request.files.getlist taken from open source projects. By voting up you can indicate which examples are most useful and appropriate., flask.request.files
@app.route('/', methods = ['POST']) def postIndex(): "" " File upload happens here. We get your filename and convert it to our hash with your extension. Then we redirect to the file itself. As we are using javascript upload, this is left for noscript users. "" " uploaded = request.files.getlist("file[]") for f in uploaded: handleUpload(f, js = False) return redirect(url_for('getIndex'))
@app.route('/js', methods = ['POST']) def indexJS(): "" " File upload for the js happens here. the normal one acts as a fallback. "" " uploaded = request.files.getlist("file[]") # handling value this way allows for multiple uploads to work # not that the web gui does this at the moment, but it 's nice through curl value = [] for f in uploaded: v = handleUpload(f) value.append(v) # it will return the return values delimited by a newline # doesn 't break existing functionality return '\n'.join(value)
def _process(self):
files = request.files.getlist('file')
for f in files:
filename = secure_filename(f.filename, 'paper')
content_type = mimetypes.guess_type(f.filename)[0] or f.mimetype or 'application/octet-stream'
paper_file = PaperFile(filename = filename, content_type = content_type, contribution = self.contrib)
paper_file.save(f.file)
db.session.flush()
# TODO: logger logger.info('Paper file %s uploaded by %s', paper_file, session.user)
# TODO: add signal
flash(ngettext("The paper file has been uploaded", "{count} paper files have been uploaded", len(files))
.format(count = len(files)), 'success')
return jsonify_data(html = _render_paper_file_list(self.contrib))
@app.route('/api/upload', methods = ['POST']) def postIndexAPI(): "" " This will handle uploads to the API, returning a JSON consisting of a list of uploaded files, with their respective statuses and uploaded URLs. "" " uploaded = request.files.getlist("file[]") res = [] for f in uploaded: v = handleUpload(f, js = False, api = True) res.append(v) return json.dumps(res)
@admin.route("/course/<int:cid>/assignments/<int:aid>/template",
methods=['GET', 'POST'])
@is_staff(course_arg='cid')
def templates(cid, aid):
courses, current_course = get_courses(cid)
assignment = Assignment.query.filter_by(id=aid, course_id=cid).one_or_none()
if not Assignment.can(assignment, current_user, 'edit'):
flash('Insufficient permissions', 'error')
return abort(401)
form = forms.AssignmentTemplateForm()
if assignment.course != current_course:
return abort(401)
if form.validate_on_submit():
files = request.files.getlist("template_files")
if files:
templates = {}
for template in files:
try:
templates[template.filename] = str(template.read(), 'utf-8')
except UnicodeDecodeError:
flash(
'{} is not a UTF-8 text file and was '
'not uploaded'.format(template.filename), 'warning')
assignment.files = templates
cache.delete_memoized(Assignment.name_to_assign_info)
db.session.commit()
flash("Templates Uploaded", "success")
# TODO: Use same student facing code rendering/highlighting
return render_template('staff/course/assignment/assignment.template.html',
assignment=assignment, form=form, courses=courses,
current_course=current_course)
def upload_backup_files(self, backup): "" "Update a Backup's attributes based on form contents. If successful, return True; otherwise, add errors to the form and return False. "" " assignment = backup.assignment templates = assignment.files files = {} for upload in request.files.getlist(self.name): data = upload.read() if len(data) > 10 * 1024 * 1024: # file is too large(over 8 MB) self.errors.append( '{} is larger than the maximum file size ' 'of 8MB'.format(upload.filename)) return False try: files[upload.filename] = str(data, 'utf-8') except UnicodeDecodeError: self.errors.append( '{} is not a UTF-8 text file'.format(upload.filename)) return False template_files = assignment.files or[] missing = [ template for template in template_files if template not in files ] if missing: self.errors.append( 'Missing files: {}. The following files are required: {}' .format(', '.join(missing), ', '.join(templates))) return False message = Message(kind = 'file_contents', contents = files) backup.messages.append(message) return True
request.files['name'] # single required file,request.files.getlist('name') # list of zero or more files posted,request.files.get('name') # None if not posted,CombinedMultiDict((request.files, request.form)) # combine form and file data
- Use a
file
type input and the browser will provide a field that lets the user select a file to upload. - Only forms with the
post
method can send file data. - Make sure to set the form's
enctype=multipart/form-data
attribute. Otherwise the file's name will be sent but not the file's data. - Use the
multiple
attribute on the input to allow selecting multiple files for the single field.
<form method=post enctype=multipart/form-data>
<!-- single file for the "profile" field -->
<input type=file name=profile>
<!-- multiple files for the "charts" field -->
<input type=file multiple name=charts>
<input type=submit>
</form>
- Open the files to read in binary mode.
- There are multiple data structures that
files
takes. This demonstrates a list of(name, data)
tuples, which allows multiple files like the form above.
import requests
with open('profile.txt', 'rb') as f1, open('chart1.csv', 'rb') as f2, open('chart2.csv', 'rb') as f3:
files = [
('profile', f1),
('charts', f2),
('charts', f3)
]
requests.post('http://localhost:5000/upload', files = files)
Uploaded files are available in request.files
, a MultiDict
mapping field names to file objects. Use getlist
— instead of []
or get
— if multiple files were uploaded with the same field name.
request.files['profile'] # single file(even if multiple were sent) request.files.getlist('charts') # list of files(even if one was sent)
WTForms provides a FileField
to render a file type input. It doesn't do anything special with the uploaded data. However, since Flask splits the form data (request.form
) and the file data (request.files
), you need to make sure to pass the correct data when creating the form. You can use a CombinedMultiDict
to combine the two into a single structure that WTForms understands.
form = ProfileForm(CombinedMultiDict((request.files, request.form)))
Suppose our CSV has a header row and looks like the following:
h1, h2, h3
'yellow', 'orange', 'blue'
'green', 'white', 'black'
'orange', 'pink', 'purple'
Regarding Empty File Storage Object, anycodings_flask means if File field is left empty while anycodings_flask submitting form and you are getting a anycodings_flask empty file storage object ,and want to anycodings_flask filter it.you can apply the below anycodings_flask mentioned check.,But there's always an empty FileStorage anycodings_python object even when no files are submitted:,Why is it there? How can I check that no anycodings_python files were uploaded if the list is never anycodings_python empty?,for no files uploaded, FileStorage anycodings_flask objects filename attribute is like anycodings_flask field.data.file.filename = '', so that anycodings_flask we can filter it based on this anycodings_flask condition.
I want to check if no files are submitted by anycodings_python doing:
if not photos: pass
But there's always an empty FileStorage anycodings_python object even when no files are submitted:
request.files.getlist("photo")
[<FileStorage: '' ('application/octet-stream')>]
FileStorage will be considered False if anycodings_flask it has no name. Flask-WTF considers a anycodings_flask FileStorage with no name to be empty for anycodings_flask validation.
photo = request.files["photo"] if not photo: # no photo
photo = request.files["photo"]
if not photo:
# no photo
photos = request.files["photo"].getlist() if not photos or not any(f for f in photos): # no photos
Regarding Empty File Storage Object, anycodings_flask means if File field is left empty while anycodings_flask submitting form and you are getting a anycodings_flask empty file storage object ,and want to anycodings_flask filter it.you can apply the below anycodings_flask mentioned check.
if not(all(isinstance(item, FileStorage) for item in field.data) and field.data and all((item.filename != '') for item in field.data)):
return
Note that request.FILES will only contain data if the request method was POST, at least one file field was actually posted, and the <form> that posted the request has the attribute enctype="multipart/form-data". Otherwise, request.FILES will be empty.,If you are constructing an object manually, you can assign the file object from request.FILES to the file field in the model:,If you are using a class-based view, you will need to use csrf_exempt() on its dispatch() method and csrf_protect() on the method that actually processes the request. Example code:,Notice that we have to pass request.FILES into the form’s constructor; this is how file data gets bound into a form.
from django
import forms
class UploadFileForm(forms.Form):
title = forms.CharField(max_length = 50)
file = forms.FileField()
from django.http import HttpResponseRedirect from django.shortcuts import render from.forms import UploadFileForm # Imaginary function to handle an uploaded file. from somewhere import handle_uploaded_file def upload_file(request): if request.method == 'POST': form = UploadFileForm(request.POST, request.FILES) if form.is_valid(): handle_uploaded_file(request.FILES['file']) return HttpResponseRedirect('/success/url/') else: form = UploadFileForm() return render(request, 'upload.html', { 'form': form })
def handle_uploaded_file(f):
with open('some/file/name.txt', 'wb+') as destination:
for chunk in f.chunks():
destination.write(chunk)
from django.http import HttpResponseRedirect from django.shortcuts import render from.forms import ModelFormWithFileField def upload_file(request): if request.method == 'POST': form = ModelFormWithFileField(request.POST, request.FILES) if form.is_valid(): # file is saved form.save() return HttpResponseRedirect('/success/url/') else: form = ModelFormWithFileField() return render(request, 'upload.html', { 'form': form })
from django.http
import HttpResponseRedirect
from django.shortcuts
import render
from.forms
import UploadFileForm
from.models
import ModelWithFileField
def upload_file(request):
if request.method == 'POST':
form = UploadFileForm(request.POST, request.FILES)
if form.is_valid():
instance = ModelWithFileField(file_field = request.FILES['file'])
instance.save()
return HttpResponseRedirect('/success/url/')
else:
form = UploadFileForm()
return render(request, 'upload.html', {
'form': form
})
from django.core.management.base
import BaseCommand
from django.core.files.base
import ContentFile
class MyCommand(BaseCommand):
def handle(self, * args, ** options):
content_file = ContentFile(b 'Hello world!', name = 'hello-world.txt')
instance = ModelWithFileField(file_field = content_file)
instance.save()
The Django Form will map the fields to form on your template file. In the above template or view file I have kept only one field called file which is used to select a file. A view handling this form will receive data into request.FILES.,Hope you got idea how to upload single and multiple files using Django framework. You may also read of other ways of uploading files into server.,Ideally the function handle_uploaded_file() should be put into common utility file, but just for the sake of this example I have kept into the same file filesupload/views.py.,request.FILES will only contain data if the HTTP request method is POST, at least one file is posted and the corresponding form has an attribute enctype="multipart/form-data", because dealing with forms that have FileField and ImageField fields are more complex.
The first thing you need to create project directory. The project name is djangofilesupload which you will create using the following command.
django - admin startproject djangofilesupload
Next step is to create an app inside the above project directory to perform files upload operations. Create an app called filesupload using the following command. Make sure you execute the following command from the project’s root directory djangofilesupload, because you are going to create the following app directory under the project’s root directory.
django - admin startapp filesupload
Now you need to add this filesupload app into the project settings. So edit the file djangofilesupload/djangofilesupload/settings.py and add the following line into INSTALLED_APPS
section at the end:
INSTALLED_APPS = [
...
'filesupload.apps.FilesuploadConfig',
]
Let’s say if your server is sending response as shown below:
<span style="color: green;">File successfully uploaded</span>
The another important thing is you need to set CSRF token on the form using {% csrf_token %}
otherwise you won’t be able to upload file and you would get the following errors:
CSRF token is not set CSRF Token missing or incorrect
The application accesses the file from the files dictionary on the request object.,Assuming the number of ../ is correct and you would join this with the UPLOAD_FOLDER the user might have the ability to modify a file on the server’s filesystem he or she should not modify. This does require some knowledge about how the application looks like, but trust me, hackers are patient :),So you’re interested in what that secure_filename() function does and what the problem is if you’re not using it? So just imagine someone would send the following information as filename to your application:,So what does that secure_filename() function actually do? Now the problem is that there is that principle called “never trust user input”. This is also true for the filename of an uploaded file. All submitted form data can be forged, and filenames can be dangerous. For the moment just remember: always use that function to secure a filename before storing it directly on the filesystem.
import os
from flask
import Flask, flash, request, redirect, url_for
from werkzeug.utils
import secure_filename
UPLOAD_FOLDER = '/path/to/the/uploads'
ALLOWED_EXTENSIONS = {
'txt',
'pdf',
'png',
'jpg',
'jpeg',
'gif'
}
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 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>
'''
filename = "../../../../home/username/.bashrc"
>>> secure_filename('../../../../home/username/.bashrc')
'home_username_.bashrc'
from flask import send_from_directory
@app.route('/uploads/<name>')
def download_file(name):
return send_from_directory(app.config["UPLOAD_FOLDER"], name)
app.add_url_rule(
"/uploads/<name>", endpoint="download_file", build_only=True
)