Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Flask-RESTful: Using GET to download a file with REST

I am trying to write a file sharing application that exposes a REST interface.

The library I am using, Flask-RESTful only supports returning JSON by default. Obviously attempting to serve binary data over JSON is not a good idea at all.

What is the most "RESTful" way of serving up binary data through a GET method? It appears possible to extend Flask-RESTful to support returning different data representations besides JSON but the documentation is scarce and I'm not sure if it's even the best approach.

like image 502
Ayrx Avatar asked Nov 10 '13 10:11

Ayrx


2 Answers

The approach suggested in the Flask-RESTful documentation is to declare our supported representations on the Api object so that it can support other mediatypes. The mediatype we are looking for is application/octet-stream.

First, we need to write a representation function:

from flask import Flask, send_file, safe_join
from flask_restful import Api

app = Flask(__name__)
api = Api(app)

@api.representation('application/octet-stream')
def output_file(data, code, headers):
    filepath = safe_join(data["directory"], data["filename"])

    response = send_file(
        filename_or_fp=filepath,
        mimetype="application/octet-stream",
        as_attachment=True,
        attachment_filename=data["filename"]
    )
    return response

What this representation function does is to convert the data, code, headers our method returns into a Response object with mimetype application/octet-stream. Here we use send_file function to construct this Response object.

Our GET method can be something like:

from flask_restful import Resource

class GetFile(Resource):
    def get(self, filename):
        return {
            "directory": <Our file directory>,
            "filename": filename
        }

And that's all the coding we need. When sending this GET request, we need to change the Accept mimetype to Application/octet-stream so that our API will call the representation function. Otherwise it will return the JSON data as by default.

There's an xml example on github

I know this question was asked 7 years ago so it probably doesn't matter any more to @Ayrx. Hope it helps to whoever drops by.

like image 128
AlpacaMax Avatar answered Oct 22 '22 13:10

AlpacaMax


As long as you're setting the Content-Type header accordingly and respecting the Accept header sent by the client, you're free to return any format you want. You can just have a view that returns your binary data with the application/octet-stream content type.

like image 43
Pedro Werneck Avatar answered Oct 22 '22 14:10

Pedro Werneck