Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Flask: How to handle application/octet-stream

Tags:

python

flask

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.

like image 263
saidozcan Avatar asked Apr 12 '13 22:04

saidozcan


People also ask

What is application octet-stream?

The application/octet-stream MIME type is used for unknown binary files. It preserves the file contents, but requires the receiver to determine file type, for example, from the filename extension. The Internet media type for an arbitrary byte stream is application/octet-stream .

How do you handle file uploads in flask?

Handling file upload in Flask is very easy. It needs an HTML form with its enctype attribute set to 'multipart/form-data', posting the file to a URL. The URL handler fetches file from request. files[] object and saves it to the desired location.

What is application octet-stream Java?

APPLICATION/OCTET-STREAM stands for binary data. It may be more precise by specifing the actual filetype. For images it coud be image/png . If the browser knows the exact filetype it may show the file directly.


2 Answers

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()
like image 124
puredistortion Avatar answered Oct 25 '22 03:10

puredistortion


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.

like image 3
Yibo Yang Avatar answered Oct 25 '22 04:10

Yibo Yang