Content-type header for file_stream

in response.py file_stream function sets up the headers before content-disposition and then if there is a filename it adds the key and value via headers.setdefault… i can’t get the content-type set in the file_stream function even it is sent in a dictionary as a parameter/argument when file_stream is called… is there something tricky about the file_stream method?

Can you post a snippet of what you are trying? I won’t be able to get you an answer back until next week. Maybe someone else will beat me to it.

Either way, it will be helpful to see a slimmed down version of what you are trying.

@app.route("/something/<k>/<v>")
def foobar(request, k, v):
    return response.file_stream("streamed_filename", mime_type="application/metalink4+xml",  chunk_size=1024, headers={"Content-Disposition": 'Attachment; filename="nicer_name.meta4"', "Content-Type": "application/metalink4+xml"})

i generate file on the fly. and everything works fine on the desktop but i noticed that on android the downloaded file doesn’t have the desired mime type. and then i checked the headers and realized that with the headers set as above doesn’t pass the content-type as it is there. it always does text/plain. so i wonder if it is possible in file_stream function to do chunked transfer, custom content-disposition and custom content-type header.

i hope this made it clearer…

@marcell Let me take a look and see what might be causing the issue. But based on a quick look mime_type passed to the method call as argument should be honored and the Content-Type should have been added to the response.

Let me reproduce the issue and get back to you

Regards, H

Here is my example:

from pathlib import Path
from sanic import Sanic, response


app = Sanic(__name__)


@app.route("/mp4")
async def handler_file_stream(request):
    return await response.file_stream(
        Path("./") / "sample.mp4",
        chunk_size=1024,
        mime_type="application/metalink4+xml",
        headers={
            "Content-Disposition": 'Attachment; filename="nicer_name.meta4"',
            "Content-Type": "application/metalink4+xml",
        },
    )


app.run(debug=True)

And, I am testing with a simple HTML:

<html>
    <head>
        <title>Sample Stream</title>
    </head>
    <body>
        <video width="1280" height="720" controls>
            <source src="http://localhost:8000/mp4" type="video/mp4" />
        </video>
    </body>
</html>

When I curl my endpoint:

$ curl localhost:8000/mp4 -i
HTTP/1.1 200 OK
Keep-Alive: 5
Content-Disposition: Attachment; filename="nicer_name.meta4"
Content-Type: application/metalink4+xml
Transfer-Encoding: chunked

The headers are set.

When I try in the browser…

image

Again, I see the headers as expected.


Do you have any proxies in front of Sanic? How are you running Sanic? Where are you not able to see the headers?

1 Like

it was totally my mistake. i’m so sorry you had to waste your time. thank you for helping me…

i forgot that request.args dictionary has its (first) value in a list and i was checking it in a wrong way. all other tests didn’t depend on that :frowning:

:grimacing: I think we have all been there. No worries. I think I might keep this little snippet I made anyway and upload it as an example.

Let us know if there is anything else we can help with.