Django post-office: unable to open email attachement - python

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.

Related

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!

Copying .csv file located on Heroku server to local drive

I have a Python/Django web application deployed to Heroku that writes information to a .csv file.
Once the file has been written I want to pull it down from the Heroku server to the users local drive.
I don't need to persist the file anywhere and so I am avoiding using S3 or storing in the database.
I have used the Heroku "ps:copy" command which works but surely this would mean the user would need the Heroku CLI installed on their machine for this to work?
Is there any other way?
I've pasted the code below that currently generates the .csv using the djqscsv library that works with Django QuerySets:
# Generate report filename
filename = djqscsv.generate_filename(qs, append_datestamp=True)
# Generate report
try:
with open(filename, 'ab') as csv_file:
print(filename)
write_csv(qs, csv_file)
messages.success(request, 'Consultation added to report successfully!')
messages.warning(request, 'Note: Certain needs may not appear in report, \
this is a result of filtering process.')
So once "csv_file" has been written I would then redirect to the "csv_view" you have described above, obviously without writing any further rows?
This should do the trick. When sent to the csv_view, Django generates a CSV and has it automatically download to the client's browser.
Your provided code:
# Generate report filename
filename = djqscsv.generate_filename(qs, append_datestamp=True)
# Generate report
try:
with open(filename, 'ab') as csv_file:
print(filename)
write_csv(qs, csv_file)
messages.success(request, 'Consultation added to report successfully!')
messages.warning(request, 'Note: Certain needs may not appear in report, \
this is a result of filtering process.')
You need to merge this code with my code into the same view.
def csv_view(request):
filename = djqscsv.generate_filename(qs, append_datestamp=True)
response = HttpResponse(content_type='text/csv')
response['Content-Disposition'] = 'attachment; filename="{}.csv"',format(filename)
writer = csv.writer(response)
writer.writerow(qs) #use a for loop if you have multiple rows
messages.success(request, 'Consultation added to report successfully!')
messages.warning(request, 'Note: Certain needs may not appear in report, \
this is a result of filtering process.')
return response
Just to be clear, csv_view is where the CSV is generated, not merely a link to the CSV generated in another view.
This method does not save the CSV to the Dyno either. I thought that it did and just deleted it after, but I don't think it saves it to the server ever.
Discovered that the djqscsv library has the render_to_csv_response included which solves the problem:
# Generate file name from QuerySet
filename = djqscsv.generate_filename(qs, append_datestamp=True)
# Autodownload csv file in browser
return render_to_csv_response(qs, filename=filename)

How to download a file with .torrent extension from link with Python

I tried using wget:
url = https://yts.lt/torrent/download/A4A68F25347C709B55ED2DF946507C413D636DCA
wget.download(url, 'c:/path/')
The result was that I got a file with the name A4A68F25347C709B55ED2DF946507C413D636DCA and without any extension.
Whereas when I put the link in the navigator bar and click enter, a torrent file gets downloaded.
EDIT:
Answer must be generic not case dependent.
It must be a way to download .torrent files with their original name.
You can get the filename inside the content-disposition header, i.e.:
import re, requests, traceback
try:
url = "https://yts.lt/torrent/download/A4A68F25347C709B55ED2DF946507C413D636DCA"
r = requests.get(url)
d = r.headers['content-disposition']
fname = re.findall('filename="(.+)"', d)
if fname:
with open(fname[0], 'wb') as f:
f.write(r.content)
except:
print(traceback.format_exc())
Py3 Demo
The code above is for python3. I don't have python2 installed and I normally don't post code without testing it.
Have a look at https://stackoverflow.com/a/11783325/797495, the method is the same.
I found an a way that gets the torrent files downloaded with their original name like as they were actually downloaded by putting the link in the browser's nav bar.
The solution consists of opening the user's browser from Python :
import webbrowser
url = "https://yts.lt/torrent/download/A4A68F25347C709B55ED2DF946507C413D636DCA"
webbrowser.open(url, new=0, autoraise=True)
Read more:
Call to operating system to open url?
However the downside is :
I don't get the option to choose the folder where I want to save the
file (unless I changed it in the browser but still, in case I want to save
torrents that matches some criteria in an other
path, it won't be possible).
And of course, your browser goes insane opening all those links XD

django open a zip file for user to download

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')

Django : Write a session data to a file and let the user download the data

Need Help on how to write session contents to a file in static directory in django, so that it can be served to the user.
I have some huge session data. I want to store it in a file. Then serve it back to user.
I have no idea how to do it. Can you please help me on this ?
Thanks,
Bala.
# mastazi, i did all research and without any luck came to SOF.
Here is a peiece of code i tried .
xml = request.session.get('content')
fileName = request.session['search'] + '.xml'
path = (/pathto/file/)
response = HttpResponse(FileWrapper(xml.read()), content_type='text/xml')
response['Content-Disposition'] = 'attachment; filename=%s'%fileName
I even tried to write the file to static folder ..
Then tried to access it directly. Its not working. There is some issue. I tried redirecting the output to the file path. But nothing works.
THanks

Categories