Downloadable docx file on button click - python

I have files(docx file) which I need to let users download by clicking on a button.
These files were uploaded to a Model FileField.
This is my views.py
def files_view(request):
files = FileModel.objects.filter(user=request.user)
return render(request, template_name='folder/files_list.html')
and this is my template.html
{% for serving_files in user.files.all %}
<button>Download</button>
I'm doing this but the files are unable to download. What changes do I need to make?

So onclick of button call this function, the code is untested but with minor tweaks this should work.
import os
from django.conf import settings
from django.http import HttpResponse, Http404
def download(request, path):
file_path = os.path.join(settings.MEDIA_ROOT, path)
if os.path.exists(file_path):
with open(file_path, 'rb') as fh:
response = HttpResponse(fh.read(), content_type='application/vnd.openxmlformats-officedocument.wordprocessingml.document')
response['Content-Disposition'] = 'inline; filename=' + os.path.basename(file_path)
return response
raise Http404

I tweaked the code from #ans2human, and this worked for me in firefox and chrome:
def download_viewing_agreement_view(request):
file_path = pathlib.Path(settings.MEDIA_ROOT, 'filename.docx')
if os.path.exists(file_path):
with open(file_path, 'rb') as fh:
response = HttpResponse(fh.read(), content_type='application/vnd.openxmlformats-officedocument.wordprocessingml.document')
filename = 'filename.docx'
file_expr = "filename*=utf-8''{}".format(quote(filename)) # Handle a non-ASCII filename
response['Content-Disposition'] = 'attachment; {}'.format(file_expr)
return response

Related

Django How to download existing file?

in my Django 'views, I create a pdf file and I want to download it.
The file exist (path: /app/data/4.pdf) and i launch this command:
def download_line(request):
if not request.is_ajax() and not request.method == 'GET':
raise Http404
try:
fs =FileSystemStorage('/app/data')
with fs.open('4.pdf') as pdf:
response =HttpResponse(pdf,content_type='application/pdf')
response['Content-Disposition']='attachment; filename="4.pdf"'
except Exception as e:
logger.warning("Download Line | Erreur : " + e.message)
return response
But the download doesn't start and no error. Have you got a solution?
Thanks.
You can download existing file in your app by a link and static, like this
<a href="{% static 'questions/import_files/import_questions.xlsx' %}" download>Excel Format File </a>
I use FileResponse to serve file download, when the file already exists. FileResponse has been around since Django 1.7.4.
from django.core.files.storage import FileSystemStorage
from django.http import FileResponse
def download_line(request):
fs = FileSystemStorage('/absolute/folder/name')
FileResponse(fs.open('filename.pdf', 'rb'), content_type='application/force-download')
response['Content-Disposition'] = 'attachment; filename="filename.pdf"'
return response
Try this, I use this lines to download files
from django.http import HttpResponse
from wsgiref.util import FileWrapper
import os
def download(request, file_path):
"""
e.g.: file_path = '/tmp/file.pdf'
"""
try:
wrapper = FileWrapper(open(file_path, 'rb'))
response = HttpResponse(wrapper, content_type='application/force-download')
response['Content-Disposition'] = 'inline; filename=' + os.path.basename(file_path)
return response
except Exception as e:
return None
def sample_download_client_excel(request):
"""
e.g.: file_path = '/tmp/file.pdf'
"""
try:
obj = SampleFile.objects.all().first()
file_path = obj.file_name.url.strip('/')
wrapper = FileWrapper(open(file_path, 'rb'))
response = HttpResponse(
wrapper,
content_type='application/force-download'
)
response['Content-Disposition'] = 'inline; filename=' + os.path.basename(file_path)
return response
except Exception as e:
return None

Serving pdf files by link, downloaded as pdf.html

Crated function to allow users download pdf files by link. Works fine, the only problem that what user save is .html. So all files are file.pdf.html.
def download(request,ticket_id):
ticket_path = str(Ticket.objects.get(id=ticket_id).upload)
with open('files/media/' + ticket_path, 'rb') as pdf:
response = HttpResponse(pdf.read())
response['content_type'] = 'application/pdf'
response['Content-Disposition'] = 'attachment;filename="file.pdf"'
return response
Why?
You should move content_type into HttpResponse(pdf.read(), content_type='application/pdf'), it's an attribute of HttpResponse

Download a file with Django

This might perhaps be a simple question, but I somehow just can not find the solution. Django offers a lot about uploading file, but how do I do to download a file.
Let's assume we have a button on HTML on uploads/something.txt as a file.
I tried with django.views.static.serve, however what this did it would open a file on webpage.
My question is simple: What is the best and most pythonic way for user of our website to download a file?
You need to read that file.
Serve it using HttpResponse along with proper content type.
Here's some sample code:
content = open("uploads/something.txt").read()
return HttpResponse(content, content_type='text/plain')
This should serve a text file.
But as you described, on some browser, it will not ask to download the file, rather, it would show it in the browser. If you want to show a download prompt, use this:
response = HttpResponse(open("uploads/something.txt", 'rb').read())
response['Content-Type'] = 'text/plain'
response['Content-Disposition'] = 'attachment; filename=DownloadedText.txt'
return response
However, please note that it might be a better idea to serve static contents or uploaded files via nginx or the reverse proxy of your choice. Sending large files through Django might not be the most optimum way of doing that.
import os
from django.conf import settings
from django.http import HttpResponse, Http404
def download(request, path):
file_path = os.path.join(settings.MEDIA_ROOT, path)
if os.path.exists(file_path):
with open(file_path, 'rb') as fh:
response = HttpResponse(fh.read(), content_type="application/vnd.ms-excel")
response['Content-Disposition'] = 'inline; filename=' + os.path.basename(file_path)
return response
raise Http404
Maybe a little late but here is my solution:
def render(self, value):
return format_html('<a href="/media/{0}" download>{0}</a>', value)

Django - permission denied for text file created on the fly

I am trying to make a downloadable text file on the fly, i think i have achieved this but when i run the code i get a permission denied error.
also when i open this text file, does it get created anywhere in the file system? as i dont want to store these files, just create them and have them downloaded to users machine
IOError at /networks/configs/STR-RTR-01/7
[Errno 13] Permission denied: u'STR-CARD-RTR-01.txt'
config:
def configs(request, device, site_id):
site = get_object_or_404(ShowroomConfigData, pk=site_id)
config_template = get_object_or_404(ConfigTemplates, device_name=device)
file_name = device[:4] + site.location.upper()[:4] + "-" + device[4:] + ".txt"
device_config = None
with open(file_name, 'w') as config_file:
device_config = env.from_string(config_template.config)
device_config.stream(
STR = site.location.upper()[:4],
IP = site.subnet,
BGPASNO = site.bgp_as,
LOIP = site.r1_loopback_ip,
Location = site.location,
Date = site.opening_date,
).dump(config_file)
return render(request, file_name, {
})
If the goal is to provide a link where the user can download a file which is automatically generated, there's no need to write anything to disk.
You can just build the desired content in a Python string, and use the Content-Disposition header to suggest that a user's browser should download the file rather than display it, and its filename parameter to specify a default filename for the user to save the file as.
A slightly simpler example of a view function which does this...
from django.http import HttpResponse
def get_config_file(request):
filename = 'config.txt'
content = 'This is the content of my config file'
content_type = 'text/plain'
content_disposition = 'attachment; filename=%r' % filename
response = HttpResponse(content, content_type=content_type)
response['Content-Disposition'] = content_disposition
return response

HttpResponse content type for csv and other extentions doesn't work in firefox but works in Chrome and IE

I am using PYTHON+DJANGO to implement a file sharing system. When a user attempts to download a file it works well in Chrome and IE but not Firefox, Firefox returns part of the file name and no extension if it does not recognize the extension (e.g. .pl and .csv)
View
filename = os.path.join(MEDIA_ROOT, entry.myfile.url)
wrapper = FileWrapper(file(filename,'rb'))
response = HttpResponse(wrapper, content_type='application/octet-stream')
response['Content-Length'] = os.path.getsize(filename)
response['Content-Disposition'] = "attachment; filename=" + entry.name
I tried content_type=mimetypes.guess_type(filename) but this didn't solve the problem
I also tried replacing any spaces within the filename with periods, that did work! But I'm a sure there is a clean solution!!
Answer to an old question, I know, but the actual issue is that you didn't enclose the filename with double quotes (and it has to be double, not single). IE and Chrome will read until the end of the line, but Firefox will read until the first space and stop.
So just change response['Content-Disposition'] = "attachment; filename=" + entry.name to response['Content-Disposition'] = 'attachment; filename="%s"'%(entry.name) and you're set.
Based on django.views.static:
import mimetypes
import os
import stat
from django.http import HttpResponse
statobj = os.stat(fullpath)
mimetype, encoding = mimetypes.guess_type(fullpath)
mimetype = mimetype or 'application/octet-stream'
with open(fullpath, 'rb') as f:
response = HttpResponse(f.read(), mimetype=mimetype)
if stat.S_ISREG(statobj.st_mode):
response["Content-Length"] = statobj.st_size
if encoding:
response["Content-Encoding"] = encoding
response['Content-Disposition'] = 'inline; filename=%s'%os.path.basename(fullpath)
return response

Categories