How to save response to file? - django

on serverside I have function which generate pdf document:
def get_pdf(template, context_dict):
context = Context(context_dict)
html = template.render(context)
import subprocess
wkhtml2pdf = subprocess.Popen((settings.WKHTML2PDF_COMMAND,
"--encoding",
"UTF-8",
"-",
"-"),
stdin=subprocess.PIPE,
stdout=subprocess.PIPE)
wkdata = wkhtml2pdf.communicate(html.encode('utf8'))
pdf = wkdata[0];
response = HttpResponse(mimetype='application/pdf')
response['Content-Disposition'] = 'attachment; filename=%s.pdf' % (
timezone.now().strftime('%Y_%m_%d_%H_%M_%S')
)
response.write(pdf)
return response
And I want to save this file on serverside before return response. How to do it?

Where do you want to save this file? I suppose that in the MEDIA_ROOT:
import os
from django.conf import settings
...
pdf = wkdata[0];
file_name = os.path.join(settings.MEDIA_ROOT,
timezone.now().strftime('%Y_%m_%d_%H_%M_%S.pdf'))
with open(file_name, 'w') as f:
f.write(pdf)
response = HttpResponse(mimetype='application/pdf')
...

Related

Django call function to save file cannot work

I am create Django project and create function for download file, But my project cannot work, File not response to save
view.py
from django.http.response import HttpResponse
from django.conf import settings
from django.http import HttpResponse, Http404
def index(request):
BASE_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
filename = 'my_file.json'
filepath = BASE_DIR + '/filedownload/' + filename
download(request,filepath)
return HttpResponse('Download File')
def download(request, path):
file_path = path
if os.path.exists(file_path):
with open(file_path, 'rb') as fh:
response = HttpResponse(fh.read(), content_type="application/x-download")
response['Content-Disposition'] = 'inline; filename=' + os.path.basename(file_path)
return response
raise Http404
How can I solve this?
Your download() returns response to your index() and your index() returns its own response(not a response of download()). If you returns response of download() like below, it will works.
import os
from django.http.response import HttpResponse
from django.conf import settings
from django.http import HttpResponse, Http404
def index(request):
BASE_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
filename = 'my_file.json'
filepath = BASE_DIR + '/filedownload/' + filename
return download(request,filepath)
def download(request, path):
file_path = path
if os.path.exists(file_path):
with open(file_path, 'rb') as fh:
response = HttpResponse(fh.read(), content_type="application/x-download")
response['Content-Disposition'] = 'inline; filename=' + os.path.basename(file_path)
return response
raise Http404

While converting HTML to pdf, the page is stuck in loading at create pdf

While trying to generate a pdf file with the below code, the browser is stuck loading
from io import BytesIO
from django.http import HttpResponse
from django.template.loader import get_template
from xhtml2pdf.pisa import pisa
def render_to_pdf(template_src, context_dict={}):
template = get_template(template_src)
html = template.render(context_dict)
result = BytesIO()
print('RESULT')
pdf = pisa.pisaDocument(BytesIO(html.encode("ISO-8859-1")), result)
print('PDF')
if not pdf.err:
return HttpResponse(result.getvalue(), content_type='application/pdf')
return None
and generate_pdf view:
def generate_pdf(request):
pdf = render_to_pdf('doc.html')
response = HttpResponse(pdf, content_type='application/pdf')
filename = "Document_to_mail.pdf"
content = "inline; filename=%s" %(filename)
download = request.GET.get("download")
if download:
content = "attachment; filename=%s" %(filename)
response['Content-Disposition'] = content
return response
browser is stuck in pdf = pisa.pisaDocument(BytesIO(html.encode("ISO-8859-1")), result)

Preview PDF document

If I run:
127.0.0.1:8000/document/1/preview
this pdf file is downloaded.
I need display it in HTML(preview with print function). How to do it?
views.py
from xhtml2pdf import pisa
from django.template.loader import render_to_string
from datetime import datetime
import StringIO
def pdf_report(request, did):
d_instance = get_object_or_404(MyObject, pk=did, user=request.user)
contents = render_to_string('pdf_preview.html', {'object':d_instance})
response = HttpResponse(mimetype='application/pdf')
response['Content-Disposition'] = 'attachment; filename=answer_%s.pdf' % (f_date,)
result = StringIO.StringIO()
pdf = pisa.pisaDocument(StringIO.StringIO(contents.encode('utf-8')), result, show_error_as_pdf=True, encoding='UTF-8')
if not pdf.err:
response.write(result.getvalue())
result.close()
return response
urls.py
(r'^document/(?P<did>\d+)/preview/$', 'app.views.pdf_report'),
To make the file open in the browser, use inline content-disposition.
response['Content-Disposition'] = 'inline; filename=answer_%s.pdf' % f_date

download images through django

I try to download an image from my django website. I do it like this:
def file_download(request, filename):
from django.core.servers.basehttp import FileWrapper
import mimetypes
import settings
import os
filepath = os.path.join(settings.MEDIA_ROOT, filename)
wrapper = FileWrapper(open(filepath))
content_type = mimetypes.guess_type(filepath)[0]
response = HttpResponse(wrapper, mimetype='content_type')
response['Content-Disposition'] = "attachment; filename=%s" % filename
return response
However, it doesn't work for images (I tries jpg files), but do work for txt files. Why?
Probably you need to open the file in binary mode:
wrapper = FileWrapper(open(filepath, 'rb'))

Django with mod_XSENDFILE unable to download complete file

Attached is the code which downloads a file from browser using django 1.3 and Apache 2.2 with mod_xsendfile
#login_required
def sendfile(request, productid):
path = settings.RESOURCES_DIR
filepath = os.path.join('C:/workspace/y/src/y/media/audio/','sleep_away.mp3')
print "filepath",filepath
filename = 'sleep_away.mp3' # Select your file here.
print "Within sendfile size", os.path.getsize(filepath)
wrapper = FileWrapper(open(filepath,'r'))
content_type = mimetypes.guess_type(filename)[0]
response = HttpResponse(wrapper, content_type = content_type)
print "Within wrapper"
from django.utils.encoding import smart_str
response['X-Sendfile'] = smart_str(filepath)
response['Content-Length'] = os.path.getsize(filepath)
from django.utils.encoding import smart_str
response['Content-Disposition'] = 'attachment; filename=%s/' % smart_str(filename)
return response
The console shows the following filesize which is the right size
Within sendfile size 4842585
But when I download/save the file it shows 107 KB...i.e 109,787 bytes.Where am I going wrong. Why isnt it downloading the complete file?
I consider your new to django or python. Try to put the import statements at the beginning of the method. Once imported it can be used through the method no need import every time you use. In windows you should use "rb" (read binary) to serve anything other than text files. Try not to use variable names that might conflict with method names or other keywords of the language. Your method should be like this
#login_required
def sendfile(request, productid):
from django.utils.encoding import smart_str
##set path and filename
resource_path = settings.RESOURCES_DIR # resource dir ie /workspace/y/src/y/media
filename = "sleep_away.mp3" #file to be served
##add it to os.path
filepath = os.path.join(resource_path,"audio",filename)
print "complete file path: ", filepath
##filewrapper to server in size of 8kb each until whole file is served
file_wrapper = FileWrapper(file(filepath,'rb')) ##windows needs rb (read binary) for non text files
##get file mimetype
file_mimetype = mimetypes.guess_type(filepath)
##create response with file_mimetype and file_wrapper
response = HttpResponse(content_type=file_mimetype, file_wrapper)
##set X-sendfile header with filepath
response['X-Sendfile'] = filepath ##no need for smart_str here.
##get filesize
print "sendfile size", os.stat(filepath).st_size
response['Content-Length'] = os.stat(filepath).st_size ##set content length
response['Content-Disposition'] = 'attachment; filename=%s/' % smart_str(filename) ##set disposition
return response ## all done, hurray!! return response :)
Hope that helps
You could have a look at the django-private-files project. Haven't tested it myself, but it looks promissing.
link to the docs --> http://readthedocs.org/docs/django-private-files/en/latest/usage.html
cheers