12

I want to make a multiple file-upload form.I use jQuery File Uploader. My server-side code:

@app.route("/new/photogallery",methods=["POST"])
def newPhotoGallery():
    print request.files

I tried two things:

  1. Submit form normally:

    When i submit my form normally,it prints:

    ImmutableMultiDict([('post_photo_gallery', FileStorage: u'' ('application/octet-stream'))])

  2. Submit form using AJAX:

    When i submit my form using AJAX,it prints:

    ImmutableMultiDict([])

My first question is: Why is there a difference between AJAX request and normal request.
My second question is: How can i handle this application/octet-streamrequest in Flask/Python My third question is: Is this a good way to use application/octet-stream ?

By the way i do not know much about application/octet-stream.Thank you very much.

8
  • If you're on Chrome, look at the Network tab of the developer tools and see what the two requests look like. Commented Apr 12, 2013 at 22:16
  • ------WebKitFormBoundaryxInpKfVFK8mUuqOv Content-Disposition: form-data; name="post_photo_gallery"; filename="" Content-Type: application/octet-stream lines are dont appeared on the AJAX request Commented Apr 12, 2013 at 22:20
  • This might be useful: github.com/blueimp/jQuery-File-Upload/wiki/Flask Commented Apr 12, 2013 at 22:22
  • when i data_file = request.files.get('data_file') print this one it prints None, i changed 'data_file' with name of my input in the form :( Commented Apr 12, 2013 at 22:26
  • What does your JS config look like? Commented Apr 12, 2013 at 22:30

2 Answers 2

3

Regardless of the the data encoding, you should be able to get the raw data with request.data. In the case of application/octet-stream, you can just write request.data to a binary file.

An example handler for various data types:

from flask import json

@app.route('/messages', methods = ['POST'])
def api_message():

    if request.headers['Content-Type'] == 'text/plain':
        return "Text Message: " + request.data

    elif request.headers['Content-Type'] == 'application/json':
        return "JSON Message: " + json.dumps(request.json)

    elif request.headers['Content-Type'] == 'application/octet-stream':
        with open('/tmp/binary', 'wb') as f:
            f.write(request.data)
            f.close()
        return "Binary message written!"

    else:
        return "415 Unsupported Media Type ;)"

The typical scenario of handling form data is already documented here.

Sign up to request clarification or add additional context in comments.

3 Comments

that didn't work for me when sending application/octet-stream, I get: File "...\lib\site-packages\werkzeug\test.py", line 884, in run_wsgi_app app_rv = app(environ, start_response) TypeError: 'int' object is not callable
@markmnl You can use request.stream.read as shown in izmailoff.github.io/web/flask-file-streaming
when using multipart/form-data or application/x-www-form-urlencoded to send files, flask stores the file comes in request.files as shown here flask.palletsprojects.com/en/1.1.x/patterns/fileuploads
2

I was unable to get a request working using application/octet-stream type posts, but have used multipart/form-data type forms in the past to upload images using flask.

I have extended what I have done in the past to support multiple upload files and this has worked leveraging werkzeug's FileStorage objects.

The key here is setting up a post based route that is looking for a request element from a form. This should allow you to POST to the route either via a standard form or an AJAX call.

Below is a simplified example that is using a form:

Template for the view:

<!DOCTYPE HTML>
<html>
<head>
<meta charset="utf-8">
<title>jQuery File Upload Example</title>
</head>
<body>
{% if err %}
    <h4>{{ err }}</h4>
{% endif %}

<form action="/" method=POST enctype=multipart/form-data id="fileupload">
    <input type="file" name="files" data-url="/" multiple>
    <input type=submit value=Post>
</form>

{% if files %}
{% for file in files %}
<p>Uploaded: <b>{{ file }}</b> </p>
{% endfor %}
{% endif %}
</body> 
</html>

Flask App

from flask import Flask, request, render_template
from werkzeug import secure_filename, FileStorage
import os

# Flask functions
app = Flask(__name__) 
app.config.from_object(__name__)
DEBUG = True 
# add this so that flask doesn't swallow error messages
app.config['PROPAGATE_EXCEPTIONS'] = True

@app.route('/', methods=['GET', 'POST'])
def uploader():
    if request.method =='POST' and request.files.getlist('files'):
        up_file_list = []

        # Iterate the through a list of files from the form input field
        for a_file in request.files.getlist('files'):
            if a_file.filename:
                # Validate that what we have been supplied with is infact a file
                if not isinstance(a_file, FileStorage):
                    raise TypeError("storage must be a werkzeug.FileStorage")
                # Sanitise the filename
                a_file_name = secure_filename(a_file.filename)
                # Build target
                a_file_target = os.path.join('/tmp/', a_file_name)
                # Save file 
                a_file.save(a_file_target)
                up_file_list.append(a_file_name)
        # Return template
        if up_file_list:
            return render_template('uploader.html', err=None, files=up_file_list)
        else:
            return render_template('uploader.html', err='No Files Uploaded', files=None)
    else:
        return render_template('uploader.html', err=None, files=None) 


# application execution 
if __name__ == '__main__': 
    app.run()

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.