How to send file to response in Django?
Asked Answered
C

5

14

I have such php function which I try to rewrite in my Django project. What should be an analogue in python for php methods like header() and show_error()? Also how to send file to response?

php:

function waprfile($date=false) {
    if(!isset($date) || $date==false) $date = date("d.m.y");

    $timestmp = date2timestamp($date);

    $filepath = "https://www.example.com/files/".$this->lang_code."/";

    if(file_get_contents($filepath.date("dmy",$timestmp).".xls"))
    {
        header("Location: ".$filepath."wapr".date("dmy",$timestmp).".xls");
    }
    else
    {
        show_error(_langWrite("No file for specified date", "Файл на указанную дату отсутствует"));
    }
}

python:

import urllib.request
import datatime
import time
from django.utils import translation

def isset(variable):
    return variable in locals() or variable in globals()

def waprfile(request, date):
    if(not isset(date) or date==False):
        date = datetime.datetime.now().strftime('%d.%m.%Y')

    timestmp = time.mktime(datatime.datetime.strptime(date, "%d.%m.%Y").timetuple())

    filepath = "https://www.example.com/files/" + str(translation.get_language()) + "/"

    formatted_date = datetime.datetime.fromtimestamp(timestmp).strftime('%d%m%y')

    if(urllib.request.urlopen(filepath + formatted_date + '.xls')):
        # What must be here?
    else:
        # What must be here?

    response = HttpResponse(content_type='application/ms-excel')
    response['Content-Disposition'] = 'attachment; filename=' + fileName
    return response
Crustal answered 23/5, 2018 at 4:28 Comment(0)
P
25

Read file first and then send it in response.

from django.http import HttpResponse, HttpResponseNotFound

def waprfile(request, date):
    ...

    file_location = '/path/to/file/foo.xls'

    try:    
        with open(file_location, 'r') as f:
           file_data = f.read()

        # sending response 
        response = HttpResponse(file_data, content_type='application/vnd.ms-excel')
        response['Content-Disposition'] = 'attachment; filename="foo.xls"'

    except IOError:
        # handle file not exist case here
        response = HttpResponseNotFound('<h1>File not exist</h1>')

    return response

Read docs for more info: telling browser to treat the response as a file attachment and returning errors

Pharisee answered 23/5, 2018 at 5:11 Comment(5)
Thank you! Can I ask one more question. Lets say when we try to open file which is not exist what we need to send to response?Crustal
in that case, you must send JSON response or HTML response saying file does not exist.Pharisee
What do you think if I would use response = HttpResponse(status=204)?Crustal
204 means the request is successful and there is no content to send in the response body, This totally depends on your use case, you can send either Error or Success responsePharisee
Is there any package to do this easily?Ineffable
M
3

To return a PDF file in response in Django, use below code.

def index(request):
    data = dict()
    data["name"] = "https://www.pythoncircle.Com"
    data["DOB"] = "Jan 10, 2015"

    template = get_template('testapp/test.html')
    html = template.render(data)
    pdf = pdfkit.from_string(html, False)

    filename = "sample_pdf.pdf"

    response = HttpResponse(pdf, content_type='application/pdf')
    response['Content-Disposition'] = 'attachment; filename="' + filename + '"'
    return response

[1] https://www.pythoncircle.com/post/470/generating-and-returning-pdf-as-response-in-django/

Myrt answered 23/5, 2018 at 5:33 Comment(0)
D
2
from django.http import FileResponse
def download_file():
  return FileResponse(open('/path/to/file','rb'),
                        filename=file_name,
                        as_attachment=True,
                        content_type='application/vnd.openxmlformats-officedocument.spreadsheetml.sheet',
                        status=status,
                        )

Note: content-type should be set as per what type of file you are trying to send. the value set here is for excel type of file

Drolet answered 26/1 at 18:38 Comment(0)
V
1

If you want to return an image don't forget to format it as png or jpeg and return the bytes with getvalue()

img = "Suppose I am a pil image"
fomatted_img = BytesIO()
img.save(fomatted_img, format="png")
response = HttpResponse(fomatted_img.getvalue(),content_type='image/png')
response['Content-Disposition'] = 'attachment; filename="output.png"'
return response

Or you can save the formatted image directly into the response

img = "Suppose I am a pil image"
response = HttpResponse(content_type='image/png')
response['Content-Disposition'] = 'attachment; filename="output.png"'
img.save(response,"PNG")
return response
Virgilio answered 23/8, 2022 at 14:37 Comment(0)
H
0

Django has a FileResponse class that accepts an IO object in its constructor. So in your view:

buffer = BytesIO(excel.blob)
response = FileResponse(buffer, as_attachment=True, filename=excel.name)
response["Content-Type"] = "application/vnd.ms-excel"
return response
Hubsher answered 25/1 at 14:6 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.