Django output csv file, filename is not setting as the value of Content-Disposition - django

I want to download a csv file with custom filename in a django project, but somehow the downloaded filename just display as "download.csv" instead of using the value of filename in Content-Disposition. I also tried to print csv_response['Content-Disposition'] out, but I'm getting a very strange string =?utf-8?b?YXR0YWNobWVudDsgZmlsZW5hbWU9Iuivvueoi+aKpeWQjeaDheWGtV8yMDE5MTEyODA3NDI0Ny5jc3Yi?=
the code snippet is :
#action(detail=False, methods=['GET'])
def download(self, request):
registrations = self.filter_queryset(self.get_queryset())
csv_response = HttpResponse(content_type='text/csv')
csv_response['Content-Disposition'] = 'attachment; filename="some_custom_name_{time}.csv"'.format(
time=time.strftime("%Y%m%d%H%M%S", time.localtime())
)
writer = csv.writer(csv_response)
writer.writerow([
some content,
])
for registration in registrations:
term_title = '{order} th'.format(order=registration.term.order)
course_title = registration.course.title
writer.writerow([
registration.user.email,
course_title,
term_title,
str(registration.confirmation_code),
str(registration.payment_due),
str(registration.payment_paid),
str(registration.source),
str(registration.created_at),
str(registration.updated_at),
str(registration.payment_source),
])
return csv_response
the django I am using is 2.2
any ideas why this is happening? I am a newb.
Thx in advance
The response header in chrome Dev tools:

I resolved the problem, by following the answer in the below post:
HttpResponse Django does not change file name
I guess that it is that because the string of Content-Disposition needs to be encoded, and if no, then somehow cannot operate on that, by using urlquote, it is solved.
Explanation about urlquote is here
UPDATE:
Also, a simpler way to resolve this without importing urlquote is to add encode(), like below:
csv_response['Content-Disposition'] = 'attachment; filename="some_custom_name_{time}.csv"'.format(
time=time.strftime("%Y%m%d%H%M%S", time.localtime())
).encode()

Change to this:
csv_response['Content-Disposition'] = 'attachment; filename="some_custom_name_{}.csv"'.format(
time.strftime("%Y%m%d%H%M%S", time.localtime())
)

Related

In django, how can i upload file via url?

Hi i'm making my own webserver using django.
i just want to upload local file to django server.
i google every method but i can't get answer.
every method using form or html but i don't want to using form and html
example : from www.localfolder/example.txt to /media/examplefolder.
i don't know how to do.. any help?
this is my code.
#csrf_exempt
def download_file(request, file):
fl_path = 'media/'
filename = str(file)
fl = open(fl_path, 'r')
mime_type, _ = mimetypes.guess_type(fl_path)
response = HttpResponse(fl, content_type=mime_type)
response['Content-Disposition'] = "attachment; filename = %s" % filename
return response
What did you search for when you googled? These were the top 2 results for Django files
https://docs.djangoproject.com/en/3.0/topics/http/file-uploads/
https://docs.djangoproject.com/en/3.0/topics/files/
Seems to have everything you are looking for.

error serving pdf in django 1.8

In django 1.8 I have a couple of functions that read pdf files and return them, and that generate a pdf with reportlab and return it.
In some cases the file is served correctly, but sometimes the PDF is opened by the browser as if it were html and what is even more strange, pdf source is displayed in my django base template.
In this case, if reloading the page after the error, the pdf is served.
This is the code of a view:
fpdf = open (path, 'rb')
return HttpResponse (FileWrapper (fpdf), content_type = 'application/pdf')
and this is the code of the other:
pdf = pisa.CreatePDF (StringIO.StringIO (html.encode ("UTF-8")), result)
if not pdf.err:
response = HttpResponse (result.getvalue (), content_type = 'application / pdf')
response ['Content-Disposition'] = 'attachment; filename =% S.pdf '% (doc.name.replace ("", "_"))
return response
#Return HttpResponse (result.getvalue (), content_type = 'application/pdf')
Returning the PDF as an attachment is a test that I made to see if solved, because the desired behavior would be directly open the file.
Unfortunately, the error still occurs even so.
Change this line
response = HttpResponse (result.getvalue (), content_type = 'application / pdf')
To this line
response = HttpResponse (result.getvalue (), content_type = 'application/octet-stream')
This will make the file to be treated as a binary, and downloaded to the user instead of opening it in the browser.
If you view it inside the browser, follow Igor Pomaranskiy advice, and remove the space inside your content_type variable by doing the following
Change this
content_type = 'application / pdf'
to this
content_type = 'application/pdf'

Files downloaded from django don't have file's extension

I'm writing a view on my Django 1.5 progect that make the user download a file.
This is the code:
import mimetypes
from django.http import HttpResponse
def filedownload(request, file_name):
down_file = File.objects.get(name = file_name)
file_path = MEDIA_ROOT+str(down_file.file) #down_file.file is something like folder/name_file.extension
response = HttpResponse(mimetype='application/force-download')
response['Content-Disposition'] = 'attachment; filename=%s' % file_name
response['X-Sendfile'] = file_path
return response
It work just fine but the file is downloaded without the extension. Why? How can I solve this? I know that I can let the webserver do this but it's a dummy project and has to works only in Django.
EDIT:
I solved thanks the answer of sk1p and using a more elaborate code found here
You are specifying the filename to be displayed in the browser with this line:
response['Content-Disposition'] = 'attachment; filename=%s' % file_name
so if file_name doesn't contain the extension, the download won't either. So: make sure the Content-Disposition header contains the right filename and extension!

Downloading a file with Chinese characters in the name in Django with HttpResponse

I want to download a file with Django's httpresponse method. The name of the file has some special characters, like Chinese. I can download the file with the following code, but the file name appears as "%E6%B8%B8%E6%88%8F%E6%B5%8F%E8%A7%88%E5%99%A8%E6%B3%A8%E5%86%8C%E9%A1%B5%E9%9D%A2.jpg".
Could anyone tell me how to convert the file name?
response = HttpResponse(attachment.file, content_type='text/plain',mimetype='application/octet-stream')
response['Content-Disposition'] = "attachment; filename="+urlquote(filename)
return response
Edit:
Another problem comes out when using smart_str, the file name can be displayed normally in Firefox and Chrome, but not in IE: in IE it's still displaying some unknown characters. Does anyone know how to fix this problem?
Thanks in advance!
---solved by use urlquote and smart_str differently in IE and other browsers.
I think it may have something to do with Encoding Translated Strings
Try this:
from django.utils.encoding import smart_str, smart_unicode
response['Content-Disposition'] = 'attachment; filename=%s' % smart_str(filename)
return response
The following code works for me to solve your problem.
from django.utils.encoding import escape_uri_path
response = HttpResponse(attachment.file, content_type='text/plain',mimetype='application/octet-stream')
response['Content-Disposition'] = "attachment; filename*=utf-8''{}".format(escape_uri_path(filename))
return response
There is no interoperable way to encode non-ASCII names in Content-Disposition. Browser compatibility is a mess.
/real_script.php/fake_filename.doc
/real_script.php/mot%C3%B6rhead # motörhead
please look at https://stackoverflow.com/a/216777/1586797
Thanks to bronze man and Kronel, I have come to an acceptable solution to this problem:
urls.py:
url(r'^customfilename/(?P<filename>.+)$', views.customfilename, name="customfilename"),
views.py:
def customfilename(request, *args, filename=None, **kwds):
...
response = HttpResponse(.....)
response['Content-Type'] = 'your content type'
return response
your_template.html (links to the view providing the file)
link to your file
Please note that filename doesn't really need to be a parameter. However, the above code will let your function know what it is. Useful if you handle multiple different Content-Types in the same function.

Django download file empty

I am writing a simple function for downloading a certain file, from the server, to my machine.
The file is unique represented by its id. The file is locatd corectly, and the download is done, but the downloaded file (though named as the one on the server) is empty.
my download function looks like this:
def download_course(request, id):
course = Courses.objects.get(pk = id).course
path_to_file = 'root/cFolder'
filename = __file__ # Select your file here.
wrapper = FileWrapper(file(filename))
content_type = mimetypes.guess_type(filename)[0]
response = HttpResponse(wrapper, content_type = content_type)
response['Content-Length'] = os.path.getsize(filename)
response['Content-Disposition'] = 'attachment; filename=%s/' % smart_str(course)
return response
where can i be wrong? thanks!
I answered this question here, hope it helps.
Looks like you're not sending any data (you don't even open the file).
Django has a nice wrapper for sending files (code taken from djangosnippets.org):
def send_file(request):
"""
Send a file through Django without loading the whole file into
memory at once. The FileWrapper will turn the file object into an
iterator for chunks of 8KB.
"""
filename = __file__ # Select your file here.
wrapper = FileWrapper(file(filename))
response = HttpResponse(wrapper, content_type='text/plain')
response['Content-Length'] = os.path.getsize(filename)
return response
so you could use something like response = HttpResponse(FileWrapper(file(path_to_file)), mimetype='application/force-download').
If you are really using lighttpd (because of the "X-Sendfile" header), you should check the server and FastCGI configuration, I guess.
Try one of these approaches:
1) Disable GZipMiddleware if you are using it;
2) Apply a patch to django/core/servers/basehttp.py described in
https://code.djangoproject.com/ticket/6027