I wrote a really simple django project to test xlsxwriter. I can open the excel file, but when I name the file 'filename.xlsx', the file is downloaded as 'filename.xlsx.xls'. How can I fix this?
from django.shortcuts import render
from django.http import HttpResponse
from .excel import get_excel
def home_view(request):
response = HttpResponse(content_type='application/vnd.ms-excel')
response['Content-Disposition'] = 'attachment; filename=filename.xlsx'
excel_data = get_excel()
response.write(excel_data)
return response
XSLX is an OpenXML format, so the mimetype is different, it uses:
application/vnd.openxmlformats-officedocument.spreadsheetml.sheet
you thus should change this to:
def home_view(request):
response = HttpResponse(
content_type='application/vnd.openxmlformats-officedocument.spreadsheetml.sheet'
)
response['Content-Disposition'] = 'attachment; filename=filename.xlsx'
excel_data = get_excel()
response.write(excel_data)
return response
Related
I am given a zip file that I need to send to UI from where it should be downloaded for the user.
While testing on POSTMAN, using Send & Download button associated with POST, I am able to download the file. But when opening it, it says:
Windows cannot open the folder. The Compressed(zipped) folder <zip path> is invalid
Here's the code I am trying:
from django.response import Response
from rest_framework.views import APIView
def get_response():
with open(zip_file_path.zip, 'r', encoding='ISO-8859-1') as f:
file_data = f.read()
response = Response(file_data, content_type='application/zip')
response['Content-Disposition'] = 'attachment; filename="ReportTest.zip"'
return response
class GenerateZIP(APIView):
def post(self, request):
zip_file_response = get_response()
return zip_file_response
The zip file read is valid as it's already on the local.
Any ideas?
Rather than generate the response yourself, you can use a FileResponse which does it for you
from django.http import FileResponse
from rest_framework.views import APIView
class GenerateZIP(APIView):
def post(self, request):
return FileResponse(
open('zip_file_path.zip', 'rb'),
as_attachment=True,
filename='ReportTest.zip'
)
Django==1.11.12
If the file exists, the view function creates StreamingHttpResponse and all is fine. But if the file does not exist, the view function should redirect. The problem is, it does not redirect but instead prompt up to ask to save as a file, which has the content of redirected html.
import os
from wsgiref.util import FileWrapper
import mimetypes
from django.http import StreamingHttpResponse
from django.shortcuts import render, redirect
def download(request, file_path):
try:
response = StreamingHttpResponse(
FileWrapper(open(file_path, 'rb'), chunk_size),
content_type=mimetypes.guess_type(file_path)[0])
response['Content-Length'] = os.path.getsize(file_path)
response['Content-Disposition'] = "attachment; filename=a_file.xlsx")
except FileNotFoundError as e:
response = redirect("home")
return response
It turns out that the problem lays in template, where the download link is <a href="xxx" download> and the download attribute force the download.
I have been following this tutorial which helped me in generating pdf files in Django using xhtml2pdf. Now what I want is to save the generated file to disk without having to prompt the user to download the file.
Below is the code I am using to generate the pdf file in utils.py file and views.py file.
#utils.py file
from io import BytesIO
from django.http import HttpResponse
from django.template.loader import get_template
from xhtml2pdf import pisa
def render_to_pdf(template_src, context_dict={}):
template = get_template(template_src)
html = template.render(context_dict)
result = BytesIO()
pdf = pisa.pisaDocument(BytesIO(html.encode("ISO-8859-1")), result)
if not pdf.err:
return HttpResponse(result.getvalue(), content_type='application/pdf')
return None
#views.py snippet of code
html = template.render(context)
pdf = render_to_pdf('tdn.html', context)
if pdf:
response = HttpResponse(pdf, content_type='application/pdf')
filename = "TDN_%s.pdf" %("12341231")
content = "inline; filename='%s'" %(filename)
download = request.GET.get("download")
if download:
content = "attachment; filename='%s'" %(filename)
response['Content-Disposition'] = content
TDN.objects.filter(id=tdn_no).update(printed=1)
return response
return HttpResponse("Not found")
Any pointers on how I can write to disk the generated pdf will be greatly appreciated
Tried this?
with open('mypdf.pdf', 'wb+') as output:
pdf = pisa.pisaDocument(StringIO.StringIO(html.encode("UTF-8")), output)
If you want to save it to ImageField use ContentFile in Django!
Question similar to this
django rest framework return file
Trying to apply a similar solution to return an executable python binary in Django Rest ApiView:
from wsgiref.util import FileWrapper
bin_file = open(f'cli/builds/dist/cli', 'rb')
response = Response(FileWrapper(bin_file), content_type='application/octet-stream')
response['Content-Disposition'] = f'attachment; filename="cli"'
response.status_code = status.HTTP_200_OK
return response
getting Object of type 'FileWrapper' is not JSON serializable error.
Referring to the previously mentioned SO topic - this solution is warking for a zip file.
Question - why doesn't it work for my setting, returning the python executable?
python 3.6.5,
djangorestframework==3.8.2
tried both Response and HttpResponse classes
Try to use HttpResponse instead of DRF's Response,
from wsgiref.util import FileWrapper
from django.http.response import HttpResponse
bin_file = open(f'cli/builds/dist/cli', 'rb')
response = HttpResponse(FileWrapper(bin_file), content_type='application/octet-stream')
response['Content-Disposition'] = f'attachment; filename="cli"'
response.status_code = status.HTTP_200_OK
return response
I have a django project and I've created an excel file using xlwt(end snippet of file generation).
export_wb.save(output)
output.seek(0)
response = HttpResponse(output.getvalue())
response['Content-Type'] = 'application/vnd.ms-excel'
response['Content-Disposition'] = 'attachment; filename='+filename
return response
Now in my view I want to generate this file and attach it to a new object and save it, so I have a new object in the admin with an attached excel file. I'm trying something like this
def test(request):
exported_ingredients = export(request, app_name='ingredients', model_name='ingredient')
new_export = IngredientExportItem(file_name="x", slug="x", file=exported_ingredients)
new_export.save()
return HttpResponseRedirect('/')
I keep getting this error though: 'HttpResponse' object has no attribute '_committed'
Doesn't seem to like the object I'm setting to 'file' property(file is a fileupload field). If I just return the object then my browser downloads the file correctly so the file is OK.
Your response is not a django file object, it's a django HttpResponse object.
Check out ContentFile if you want to create a django file object from a string.
from django.core.files.base import ContentFile
def test(request):
http_response = export(request, app_name='ingredients', model_name='ingredient')
file_ = ContentFile(http_response.content)
file_.name = http_response['Content-Disposition'].split('=')[-1]
new_export = IngredientExportItem(file_name="x", slug="x", file=file_)
new_export.save()
return HttpResponseRedirect('/')