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
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!
My code for upload in views.py is
def upload(request):
context = {}
if request.method == 'POST':
uploaded_file = request.FILES['document']
timestr = time.strftime("%Y%m%d-%H%M%S")
fs = FileSystemStorage()
uploaded_file.name = timestr+"_"+uploaded_file.name
name = fs.save(uploaded_file.name, uploaded_file)
context['url'] = fs.url(name)
return render(request, 'upload.html', context)
And my HTML webpage looks like this:
I am building an API and want to return JSON response when a user clicks on the upload button after choosing their file. I am using Django and new to web development.
You can return JSON response in three different ways in Django.
HttpResponse()
# using pure Django
from django.http import HttpResponse
return HttpResponse(json.dumps(context), content_type="application/json")
JsonResponse()
# using pure Django
from django.http import JsonResponse
return JsonResponse(context)
Response()
# using Django Rest Framework
from rest_framework.response import Response
return Response(context)
I need to return generated file download as a Django REST Framework response. I tried the following:
def retrieve(self, request, *args, **kwargs):
template = webodt.ODFTemplate('test.odt')
queryset = Pupils.objects.get(id=kwargs['pk'])
serializer = StudentSerializer(queryset)
context = dict(serializer.data)
document = template.render(Context(context))
doc = converter().convert(document, format='doc')
res = HttpResponse(
FileWrapper(doc),
content_type='application/msword'
)
res['Content-Disposition'] = u'attachment; filename="%s_%s.zip"' % (context[u'surname'], context[u'name'])
return res
But it returns a msword document as json.
How do I make it start downloading as file instead?
Here's an example of returning a file download directly from DRF. The trick is to use a custom renderer so you can return a Response directly from the view:
from django.http import FileResponse
from rest_framework import viewsets, renderers
from rest_framework.decorators import action
class PassthroughRenderer(renderers.BaseRenderer):
"""
Return data as-is. View should supply a Response.
"""
media_type = ''
format = ''
def render(self, data, accepted_media_type=None, renderer_context=None):
return data
class ExampleViewSet(viewsets.ReadOnlyModelViewSet):
queryset = Example.objects.all()
#action(methods=['get'], detail=True, renderer_classes=(PassthroughRenderer,))
def download(self, *args, **kwargs):
instance = self.get_object()
# get an open file handle (I'm just using a file attached to the model for this example):
file_handle = instance.file.open()
# send file
response = FileResponse(file_handle, content_type='whatever')
response['Content-Length'] = instance.file.size
response['Content-Disposition'] = 'attachment; filename="%s"' % instance.file.name
return response
Note I'm using a custom endpoint download instead of the default endpoint retrieve, because that makes it easy to override the renderer just for this endpoint instead of for the whole viewset -- and it tends to make sense for list and detail to return regular JSON anyway. If you wanted to selectively return a file download you could add more logic to the custom renderer.
This may work for you:
file_path = file_url
FilePointer = open(file_path,"r")
response = HttpResponse(FilePointer,content_type='application/msword')
response['Content-Disposition'] = 'attachment; filename=NameOfFile'
return response.
For FrontEnd code refer this
I am using DRF and i found a view code to download file, which would be like
from rest_framework import generics
from django.http import HttpResponse
from wsgiref.util import FileWrapper
class FileDownloadListAPIView(generics.ListAPIView):
def get(self, request, id, format=None):
queryset = Example.objects.get(id=id)
file_handle = queryset.file.path
document = open(file_handle, 'rb')
response = HttpResponse(FileWrapper(document), content_type='application/msword')
response['Content-Disposition'] = 'attachment; filename="%s"' % queryset.file.name
return response
and url.py will be
path('download/<int:id>/',FileDownloadListAPIView.as_view())
I am using React.js in frontend and i get a response like
handleDownload(id, filename) {
fetch(`http://127.0.0.1:8000/example/download/${id}/`).then(
response => {
response.blob().then(blob => {
let url = window.URL.createObjectURL(blob);
let a = document.createElement("a");
console.log(url);
a.href = url;
a.download = filename;
a.click();
});
});
}
and after i got successful in downloading a file which also opens correctly and i hope this gonna work. Thanks
For me, using Python 3.6, Django 3.0, and DRF 3.10, The problem came from using the wrong type of response. I needed to use a django.http.HttpResponse, as seen below:
from django.http import HttpResponse
...
with open('file.csv', 'r') as file:
response = HttpResponse(file, content_type='text/csv')
response['Content-Disposition'] = 'attachment; filename=file.csv'
return response
I solved my problem by saving file in media folder and sending of the link of it to front-end.
#permission_classes((permissions.IsAdminUser,))
class StudentDocxViewSet(mixins.RetrieveModelMixin, viewsets.GenericViewSet):
def retrieve(self, request, *args, **kwargs):
template = webodt.ODFTemplate('test.odt')
queryset = Pupils.objects.get(id=kwargs['pk'])
serializer = StudentSerializer(queryset)
context = dict(serializer.data)
document = template.render(Context(context))
doc = converter().convert(document, format='doc')
p = u'docs/cards/%s/%s_%s.doc' % (datetime.now().date(), context[u'surname'], context[u'name'])
path = default_storage.save(p, doc)
return response.Response(u'/media/' + path)
And handled this like in my front-end (AngularJS SPA)
$http(req).success(function (url) {
console.log(url);
window.location = url;
})
In models.py
class Attachment(models.Model):
file = models.FileField(upload_to=attachment_directory_path, blank=True, null=True)
...
#property
def filename(self):
return self.file.name.split('/')[-1:][0]
in views.py
import mimetypes
from django.http import FileResponse
class AttachmentViewSet(ModelViewSet):
...
#action(methods=['GET'], detail=True)
def download(self, request, **kwargs):
att = self.get_object()
file_handle = att.file.open()
mimetype, _ = mimetypes.guess_type(att.file.path)
response = FileResponse(file_handle, content_type=mimetype)
response['Content-Length'] = att.file.size
response['Content-Disposition'] = "attachment; filename={}".format(att.filename)
return response
and in frontend, I used axios for download files. api is axios client.
export function fileDownload(url, filename){
return api.get(url, { responseType: 'blob' })
.then((response)=>{
const url = window.URL.createObjectURL(new Blob([response.data]));
const link = document.createElement('a');
link.href = url;
link.setAttribute('download', filename);
document.body.appendChild(link);
link.click();
})
}
hope that it helps
Using django-downloadview this can be done like so:
from rest_framework.decorators import action
from django_downloadview import ObjectDownloadView
class DocumentViewSet(viewsets.ReadOnlyModelViewSet):
#action(detail=True)
def download(self, request, pk):
return ObjectDownloadView.as_view(
model=, # your model here
)(request, pk=pk)
The viewset can then be registered via DRF routers.