django open a zip file for user to download - python

Django 1.7, Python 3.4, windows apache 2.4.12 + wsgi
In my program, I generate some csv files and put them in a zip file. I would like to let the user download the zip file, either force download (after file is generated and render response) or a click of button (after display result, user has to click a button to download.)
Currently I am forcing them to download once the zip file is generated on the server.
I have referenced the following links and come up with my code below. But it is always give me this error "'charmap' codec can't decode byte 0x8d in position 80: character maps to " I tried to set it with utf-8 and ascii, and similar errors will be given.
referenced links:
django download file from server to user's machine,or read online
how to serve downloadable zip file in django
https://djangosnippets.org/snippets/365/
Generating file to download with Django
Anyone know why am I getting this error and how to get this to work?
Thank you very much!
zip_filename = time.strftime("%Y%m%d") + ".zip"
with zipfile.ZipFile(zip_filename, mode='a', compression=zipfile.ZIP_DEFLATED) as zf:
for s in sql_request:
// generate csv files
zf.write(csv_file)
// close zf
zip_file = open(zip_filename, 'r')
response = HttpResponse(zip_file, content_type='application/force-download')
response['Content-Disposition'] = 'attachment; filename="%s"' % 'foo.zip'
return response

If you're on Windows, you might need to change your open line to include the b flag.
zip_file = open(zip_filename, 'rb')

Related

Using Shareplum to download, alter and then upload a file to sharepoint

Exactly as the title says, I have this code
from shareplum import Site
from shareplum import Office365
from shareplum.site import Version
authcookie = Office365('https://mysite.sharepoint.com/', username='username', password='password').GetCookies()
site = Site('https://mysite.sharepoint.com/sites/mysite/', version=Version.v2016, authcookie=authcookie)
folder = site.Folder('Shared Documents/Beta Testing')
file = folder.get_file('practice.xlsx')
with open("practice.xlsx", "wb") as fh:
fh.write(file)
print('---')
folder.upload_file('xlsx', 'practice.xlsx')
Currently it downloads the file just fine which is fantastic, however I do not know how to reverse what I did with opening and downloading the file. Basically I need to be able to upload the file with the exact same name as the one I downloaded in the exact same format (in this case xlsx) as to overwrite the one in the sharepoint with the updated document.
Your post indicates that you want to modify the file so you will need some file handling for the downloaded file once it is saved after modification. Once the file modification has been done you need to open the file in 'rb' and then read that to a variable which will be the content when calling folder_obj.upload_file(content, name).
#this is your step to modify the file.
with open("practice.xlsx", "wb") as fh:
#file modification stuff... pyxlsx?
fh.write(file)
#open the file and read it into a variable as binary
with open("practice.xlsx", "rb") as file_obj:
file_as_string = file_obj.read()
#upload the file including the file name and the variable (file_as_string)
folder.upload_file(file_as_string, 'practice.xlsx')
This has been working for me. If you want to change the name of the file to include a version, delete the old file by calling folder.delete_file("practice.xlsx").
Can you try the below and see if it works?
with open("practice.xlsx", "wb") as fh:
file_content = fh.write(file)
folder.upload_file(file_content,'practice.xlsx')

SharePlum download file - File is a string?

I'm using SharePlum and get_file method. It seems to have downloaded the file in string format. So when I print the file this is what I get.
authcookie = Office365(config["sp_base_path"], username=config["sp_user"], password=config["sp_password"]).GetCookies()
site = Site(config["sp_base_path"] + "/sites/portal/", version=Version.v365, authcookie=authcookie)
folder = site.Folder('Shared Documents/tickets/' + ticketid)
data = folder.get_file(request.GET["filename"])
print(data)
IDATx��k�UW§�����ax�TF∟J�Td↕ML}Ԩ����Ą��☼�T�↕‼>�¶����GК#5Biڂ&&~�/���UiK�6FZ�#��t��;e`f��{�▼ι�{�9��������y�}��k����{�-4#US�↔▲◄�k
��^������#Q .g�5$R6�♦����♂<�.��Τ�w♂���\I�►♠f*xD &C�∟�▼��`�\Z b☺Xh t��♦o¶�‼X↔|n�H#�r↑Z♂��O�p}��7�☻�*Ot$�!"■0�e׼2��e`e��o2=L�#s►�!<����5�x�►Ӿ↓N�f�2☼��←<���S�������m�w∟gC�\>�n��ж☻N�f)�=►B!��El�♫J~�BDx7�(�¶�~B5�؎�8� �m��v�∟�:▼0<����☻←§■$�B♣(�F�'���H♥q~"Rǻ�v
The Explanation for this question is
Everything can be treated as bytes, so obviously everything is kind of string with encoding
What you are seeing is an application/octet-stream encoded string which can be a content of any file more specifically a binary file
try open a small exe from your computer in notepad++, don't change it, you can see similar content in it
If you want to save that content to a local file then you can use this python code
with open('myfile.docx', 'wb') as f:
f.write(data.encode())
f.close()
If you want to use SharePlum API then use
folder.download_file('filename.txt')
Assuming filename.txt is a file uploaded in sharepoint
I've figured it out. I removed the response.text and return response.content that gave me the in memory file. Thanks for helping me!

Django post-office: unable to open email attachement

I've written a django view that loads a number of PDF files and combines them into a .zipfile.
I dont want to save the object on the server, so I am using StringIO()
This is done with the following code:
zip_buffer = StringIO.StringIO()
summary_filename = 'summary' + str(user) + '.pdf'
with zipfile.ZipFile(zip_buffer, mode='w', compression=zipfile.ZIP_DEFLATED) as zf:
for file in attachements:
zf.write(str(settings.MEDIA_ROOT) + '/' + str(file[0].file),
file[1] + '.' + str(file[0].file).split('.')[-1])
zf.writestr(summary_filename, pdf)
When I was debugging the code I had it return the object as a download in the browser through the following code
response = HttpResponse(zip_buffer.getvalue(), 'application/x-zip-compressed')
return response
This all works as intended, when I click the button a .zip file is downloaded by the browser that contains all of the information.
The problems started when I wanted to email the file as well. I am using Django post-office
And intitally tried sending the email with the following command:
attachment_file = zip_buffer.getvalue()
send_email([requester.email], email_template
context, attachments={'summary.pdf': attachment_file})
The attachement file is exactly the same as the one I supplied to the browser, yet this causes the following exception:
file() argument 1 must be encoded string without NULL bytes, not str
I then tried something different:
send_email([requester.email], 'userprofile_summary', requester.profile.tenant,
context, attachments={
'summary.zip': ContentFile(attachment_file)})
Now this works in the sense that the email gets sent with an attachement, but the file that I receive is unopenable. Its like its corrupted, both OSX, Windows and Linux computers where unable to open the file.
I am currently at a loss at what to do / what is the problem. The file worked perfectly in the browser, yet it crashes when I try to email it. When I encapsulate it into a 'ContentFile()' class it returns a file that cannot be opened.
Does anyone know what I am doing wrong?
I solved it, it was a mistake in my code. For future readers with similar problems:
I forgot to add a zf.close() after the zf.writestr(summary_filename, pdf) , though the browser was able to handle this mistake, Django is more carefull - leading to my problems. Adding the close() command solved it.

User downloadable PDFs in Google App Engine returning corrupted PDFs

I've created a python script that generates a PDF from supplied user data using reportlab. The PDFs download fine and everything works when I run the script from the command line. However when I try to pass the file to Google App Engine like this:
...
outputstream = StringIO.StringIO()
PDF = output.write(outputstream)
class PDFHandler(webapp2.RequestHandler):
def get(self):
self.response.headers['Content-Type'] = 'application/pdf'
self.response.headers['Content-Disposition'] = 'attachment; filename=Myfile.pdf'
self.response.headers['Content-Transfer-Encoding'] = 'binary'
self.response.out.write(PDF)
and run the development server, the PDF downloads, but when I try to open it, chrome says it can't open the file, Ubuntu's document viewer says "can't open plain/text document", even though when I check the document's properties it states 'application/pdf' and it has the appropriate .pdf suffix, and when I try to open it in GIMP image viewer, it states "document is damaged." Is there something wrong with the way I'm passing the file to the webapp2 handler? Any help would be greatly appreciated!
I solved the problem by going over some old tutorials. It was in the last line of code where I had neglected to include .getvalue() to the output:
outputstream = StringIO.StringIO()
PDF = output.write(outputstream)
class PDFHandler(webapp2.RequestHandler):
def get(self):
self.response.headers['Content-Type'] = 'application/pdf'
self.response.headers['Content-Disposition'] = 'attachment; filename=Myfile.pdf'
self.response.headers['Content-Transfer-Encoding'] = 'binary'
self.response.out.write(PDF.getvalue())

Python Bottle File Upload

The following code is successfully uploading an image file using the Bottle framework.
upload = bottle.request.files.get("filPhoto01")
if upload is not None:
name, ext = os.path.splitext(upload.filename)
if ext not in ('.png','.jpg','.jpeg'):
return "File extension not allowed."
save_path = "/tmp/abc".format(category=category)
if not os.path.exists(save_path):
os.makedirs(save_path)
file_path = "{path}/{file}".format(path=save_path, file=upload.filename)
with open(file_path, 'w') as open_file:
open_file.write(upload.file.read())
However, when I try to open this file manually after upload, I can't open the file. I can see the icon of the uploaded file with the correct size (implying the whole image was uploaded), but I cannot view it in any application like MS paint, etc.
I also tried referencing the file in my web application, but it does not render there either. What could possibly be wrong?
Just a guess, but since it sounds like you're on Windows, you'll want to write the file in binary mode:
with open(file_path, 'wb') as open_file:
(Also, you didn't mention your Python version, but FYI in Python 3 you'd need to use binary mode even on Linux.)

Categories