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

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!

Related

the filename of pdf file doesnt work correctly with wkhtmltopdf

I have a button download in my Django project, where I can export the report for a certain date in a pdf format. Everything works fine on my laptop with Linux, but when I set the project in the local server of our company, the name of the file is showing without a date.
Here is my code:
template_name = 'pdf.html'
template = get_template(template_name)
html = template.render({"data": data, "date":date, "index":index})
if 'DYNO' in os.environ:
print('loading wkhtmltopdf path on heroku')
WKHTMLTOPDF_CMD = subprocess.Popen(
['which', os.environ.get('WKHTMLTOPDF_BINARY', 'wkhtmltopdf-pack')],
stdout=subprocess.PIPE).communicate()[0].strip()
else:
print('loading wkhtmltopdf path on localhost')
WKHTMLTOPDF_CMD = ('/usr/local/bin/wkhtmltopdf/bin/wkhtmltopdf')
config = pdfkit.configuration(wkhtmltopdf=WKHTMLTOPDF_CMD)
options = {
'margin-bottom': '10mm',
'footer-center': '[page]'
}
pdf = pdfkit.from_string(html, False, configuration=config, options=options)
response = HttpResponse(pdf, content_type='application/pdf')
response['Content-Disposition'] = 'attachment; filename="otchet-{}.pdf"'.format(date)
return response
when I download locally, the name of the file is - otchet-2021-06-30.pdf
but on server, it looks like - otchet%20.pdf
I have no idea, how to fix it...
Just a thought. Use an f string.
response['Content-Disposition'] = f'attachment; filename="otchet-{date}.pdf"'

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

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())
)

Cannot download file in Django

I am trying to figure out how to download files in Django.I went through a couple of answers on stackoverflow and tried out this:
views.py
def download():
file = open("DemoCSV.csv", "r")
response = HttpResponse(file,content_type='application/vnd.ms-excel')
response['Content-Disposition'] = 'attachment; filename="DemoCSV.csv"'
return response
The file DemoCSV.csv is in the same folder as my app.
When I hit the url from the browser,I cannot download the file.This error message is shown:
TypeError at /resources/download_files
download() takes 0 positional arguments but 1 was given
What am I missing?
It looks like download is a view, as such it's expected to take a single parameter, an HttpRequest object. so change as follows
def download(request):
file = open("DemoCSV.csv", "r")
response = HttpResponse(file,content_type='application/vnd.ms-excel')
response['Content-Disposition'] = 'attachment; filename="DemoCSV.csv"'
return response

How to serve a django-webodt file to users?

I'm trying to allow users to export some of their database data. I am using django-webodt to create a .odt file from their data. I then am trying to allow them to download it. The file is created just fine, but when it downloads it seems to download a blank file. I think there is some difference between where the server is looking for the file and where it actually is. I was wondering how to get this to work properly? I'm relatively new to django so any help would be appreciated. The code I have is below:
def downloadBook(request, val):
template = webodt.ODFTemplate('conversion.odt')
context = dict(ideas=Book.objects.getIdeaSet(int(val)))
document = template.render(Context(context))
file_name = os.path.basename(document.name)
path_to_file = os.path.dirname(document.name)
response = HttpResponse(mimetype='application/force-download')
response['Content-Disposition'] = 'attachment; filename=%s' % smart_str(file_name)
response['X-Sendfile'] = smart_str(path_to_file)
return response
I did the following and it works:
from django.template import Context
from webodt import ODFTemplate
template = ODFTemplate('template_file.odt')
context = { 'some_dict': '' }
document = template.render(Context(context))
response = HttpResponse(document.read(), mimetype='application/vnd.oasis.opendocument.text')
response['Content-Disposition'] = "attachment; filename=fancy-filename-as-you-like.odt"
document.close() # delete the document on /tmp
return response

returning zip for download from view in django

I try to download a zip file in my Django application.
How should I return it from the view?
I tried the code below, but I get some kind of alert in the browser with the content of the file inside my zip.
What am I doing wrong?
def download_logs(request):
date = datetime.datetime.now().__str__().replace(" ", "_").split(".")[0]
os.system("df -h . > /tmp/disk_space")
response = HttpResponse(mimetype='application/zip')
response['Content-Disposition'] = 'filename=logs_%s.zip' % date
files = []
files.append("/tmp/disk_space")
buffer = StringIO()
zip = zipfile.ZipFile(buffer, "w", zipfile.ZIP_DEFLATED)
for name in files:
file = open(name, "r")
zip.writestr(name, file.read())
file.close()
zip.close()
buffer.flush()
ret_zip = buffer.getvalue()
buffer.close()
response.write(ret_zip)
return response
You should tell the browser to treat the response as a file attachment.
From the docs, you should do something like:
>> response = HttpResponse(my_data, mimetype='application/vnd.ms-excel')
>>> response['Content-Disposition'] = 'attachment; filename=foo.xls'
Here is a link to actual working code for building a ZipFile in memory and returning it to the user as a file to download: django-rosetta's view.py