Dsymbol
Dsymbol

Reputation: 29

how do i use FileResponse.set_headers() in my django application to enable .mp3 file download

I am trying to use FileResponse.set_header() to set Content-Disposition to attachment, so that Audio file can be downloaded rather than playing on the browser, in my python/django powered website. is there any way i can implement this code bellow to make it work?

song = models.song.objects.filter(id__exact=song_id).first()
file_name = ntpath.basename(song.songfile.url)
content_type = 'audio/mpeg'
with open(identify_song.songfile.path, 'rb') as my_f:
      file_like = my_f
response = FileResponse(my_f,  content_type=content_type, as_attachment=True, filename="{}".format(file_name))
response['Content-Disposition'] = 'attachment; filename="{}"'.format(file_name)
 size = response['Content-Length'] = os.path.getsize(identify_song.songfile.path)
 #print(file_name)
 return(response)
 

this code does not give me any error but it's not working.

So i discovered about FileResponse.set_header() in the django doc, so i tried using it like so.

`song = models.song.objects.filter(id__exact=song_id).first()
file_name = ntpath.basename(song.songfile.url)
FileResponse.set_headers(file_name, filelike='audio/mpeg', as_attachment=True)`

Then i got an error AttributeError: 'str' object has no attribute 'filename'. please can anyone help me out, or if there is another way to do that in django i will so much appreciate someone's help. Or any other possible way i can set my Content-Disposition, in django, Nginx or in Javascript.

Upvotes: 2

Views: 7060

Answers (4)

sfdurbano
sfdurbano

Reputation: 156

There is no need to explicitly set the headers, so long as you pass in a file stream like so:

song = models.song.objects.filter(id__exact=song_id).first()
file_name = ntpath.basename(song.songfile.url)
content_type = 'audio/mpeg'

return FileResponse(
    open(identify_song.songfile.path, 'rb'),
    content_type=content_type, 
    as_attachment=True, 
    filename=file_name
)

Here is the documentation from Django.

Upvotes: 0

user1491229
user1491229

Reputation: 699

There is no answer to this question as the method 'FileResponse.set_header()' can be called with a file like object only and it makes some guesses about the header which are not reliable if you use file types that are rather exotic. At least you can overwrite this function that returns nothing but only sets the header information or you can do this little task in your code yourself. Here is my example using an in-memory string buffer.

            filename = "sample.creole"
            str_stream = StringIO()
            str_stream.write("= Some Creole-formated text\nThis is creole content.")
            str_stream.seek(0)
            response = FileResponse(str_stream.read())
            response.headers['Content-Disposition'] = 'attachment; filename={}'.format(filename)
            response.headers['Content-Type'] = 'application/creole'
            return response

With that approach yo can still use the default 'FileResponse.set_header()' functionality to set the 'Content-Length' which works properly. As the other 'FileResponse' parameters such as 'as_attachment' and 'filename' don't work as reliable. Probably nobody noticed yet as 'FileResponse' is rarely used, and as a matter of fact the same functionality can be implemented using 'HttpResponse'.

            response = HttpResponse(content_type='application/creole')
            response.headers['Content-Disposition'] = 'attachment; filename={}'.format(filename)
            response.write(str_stream.read())
            return response

Upvotes: 2

Manuel Lazo
Manuel Lazo

Reputation: 862

The utldol it is a python file that contains a function, that generates a xls file. The function returns smth like these :

outcome, error = None, None
try:
     ........
     ........
     file = open(output.get("filedir"), 'rb')
     outcome = {
          "file": file, "filename": output.get("filename"),
      }
except Exception as ex:
    error = str(ex)
return [outcome, error]
  • output contains the fullpath of the xls file generated then it is read by "open" function.

Upvotes: 0

Manuel Lazo
Manuel Lazo

Reputation: 862

I have been working all day with this functionality in order to download a generated file, lemme share you how I did it, it worked like a charm.

documentation : https://docs.djangoproject.com/en/3.0/ref/request-response/

http header 'Content-Disposition': https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Content-Disposition

try:
    wdata = request.GET
    download = wdata.get("download") or ''
    allowed_params = [
        'template', 'bases',
    ]
    if download in allowed_params:
        out, err = utldol.download_file(download, request)
        if err:
            raise ValueError(str(err))
    else:
        raise ValueError(str('Parameter not recognized'))

    file = FileResponse(
        out.get("file"), filename=out.get("filename"),
    )
    file['Content-Disposition'] = 'attachment; filename="{}"'.format(
        out.get("filename")
    )
    return file

except Exception as ex:
    return HttpResponseBadRequest(str(ex))
  • The parameter "file" contains the file instance : open('file.txt','rb') :
out.get("file")
  • The parameter "filename" contains the name of the file
out.get("filename")
  • finally, when the file is throw by the browser :

enter image description here

Hope my experience would be helpful, any views, please just lemme know.

greetings,

Upvotes: 3

Related Questions