I am currently working on a Django app that allows me to download an image while only storing the image as a temporary file. My Django app is running on a server while I am accessing the website through a local windows machine. While I am able to download the image, the file will not open. For example, Windows Photos says that "It appears we don't support this file format". Is there something wrong with the code that would cause this problem?
Views.py
def download_png(request, study):
Names(study) #Function to retrieve (name) variable
Retrieve(study) #Function to retrieve (data) variable
BASE_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
pngfilename = str(name) + "_" + str(current_time) + ".png"
filepath = BASE_DIR + '/polls/graphics/' + pngfilename
temp, filepath = tempfile.mkstemp(suffix='.png')
with open(temp, 'w') as f:
f = df2img.plot_dataframe(data)
df2img.save_dataframe(fig=f, filename=filepath)
response = HttpResponse(temp, content_type=mimetypes.guess_type(filepath))
response['Content-Disposition'] = "attachment; filename=%s" % pngfilename
return response
Update 06/30/22:
Thank you for all the help. It turns out it is better to use FileResponse rather than HttpResponse when downloading a file Here's what the updated code looks like:
def download_png(request, study):
Names(study)
Retrieve(study)
pngfilename = str(name) + "_" + str(current_time) + ".png"
mime_type, _ = mimetypes.guess_type(pngfilename)
fig = df2img.plot_dataframe(data)
df2img.save_dataframe(fig=fig, filename=pngfilename)
response = FileResponse(open(pngfilename, 'rb'), content_type=mime_type)
response['Content-Disposition'] = "attachment; filename=%s" % pngfilename
os.remove(pngfilename)
return response
Related
I am currently trying to create a function within a Django app to download a pandas dataframe as an image. I wanted to create the image as a temporary file, download it, then delete it. Does anyone know how to integrate tempfile into this code?
Views.py
def download_png(request, study):
Names(study) #Funciton to get (name) variable
Retrieve(study) #Function to get (data) variable
BASE_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
pngfilename = str(name) + "_" + str(current_time) + ".png"
temp = tempfile.NamedTemporaryFile(suffix=".png")
fig = temp.write(df2img.plot_dataframe(data))
filepath = temp.name
response = HttpResponse(df2img.save_dataframe(fig=fig, filename=filepath), content_type=mimetypes.guess_type(filepath))
response['Content-Disposition'] = "attachment; filename=%s" % pngfilename
return response
Update 06/30/22:
I had a lot of difficulty integrating the tempfile module because it requires data to be converted to bytes-like objects. Instead I simply resolved on deleting the file after creating it.
def download_png(request, study):
Names(study)
Retrieve(study)
pngfilename = str(name) + "_" + str(current_time) + ".png"
mime_type, _ = mimetypes.guess_type(pngfilename)
fig = df2img.plot_dataframe(data)
df2img.save_dataframe(fig=fig, filename=pngfilename)
response = FileResponse(open(pngfilename, 'rb'), content_type=mime_type)
response['Content-Disposition'] = "attachment; filename=%s" % pngfilename
os.remove(pngfilename)
return response
This is how you can use the tempfile library:
tempfile = tempfile.mktemp(suffix='.png')
with open(temp, 'w') as f:
f.write(df2img.plot_dataframe(data))
do_something_with_your_file(temp)
os.unlink(temp)
Edit: was just reading the tempfile documentation and apparently tempfile.mktemp is prone to race conditions, so you should either use tempfile.mkstemp like:
fd, tempf = tempfile.mkstemp()
Or there is a context manager:
with tempfile.NamedTemporaryFile() as tmp:
with open(tmp.name, 'w') as f:
f.write('some data')
# do something with your tempfile file
And then it will automatically delete the tempfile afterwards.
I'm going to create a zip file from some of the image files stored on my server.
I've used the following function to do this:
def create_zip_file(user, examination):
from lms.models import StudentAnswer
f = BytesIO()
zip = zipfile.ZipFile(f, 'w')
this_student_answer = StudentAnswer.objects.filter(student_id=user.id, exam=examination)
for answer in this_student_answer:
if answer.answer_file:
answer_file_full_path = answer.answer_file.path
fdir, fname = os.path.split(answer_file_full_path)
zip.writestr(fname, answer_file_full_path)
zip.close() # Close
zip_file_name = "student-answers_"+ str(examination.id)+"_" + str(user.id) + "_" + date=datetime.datetime.now().strftime("%Y-%m-%d-%H-%M") + '.zip'
response = HttpResponse(f.getvalue(), content_type="application/x-zip-compressed")
response['Content-Disposition'] = 'attachment; filename=%s' % zip_file_name
return response
Everything is fine and all photos are made in zip file but there is only one problem.
The problem is that the photos won't open and this error will appear in Windows:
Its look like we don't support this file format.
What is wrong with my codes?
To append data from file you have to use
write(filename)
Using writestr(filename) you add only string from variable filename but not from file.
I'm trying to rotate and save the image to GCS with the below code.
img = images.Image(blob_key=image.blob)
img.rotate(270)
t = img.execute_transforms(output_encoding=images.PNG)
filename = '/' + UploadHandler.get_gs_bucket_for_images() + 'blobstore_demo.png'
with gcs.open(filename, 'w') as f:
f.write(t)
blobstore_filename = '/gs' + filename
key = blobstore.create_gs_key(blobstore_filename)
But when I try to view the file using GAE's blostore Viewer, I get an encoded image. That is, the content-type for that blob is not set to image/png. So how I managed to set the content-type?
You can define your image mimetype, just edit yor code this way:
img = images.Image(blob_key=image.blob)
img.rotate(270)
t = img.execute_transforms(output_encoding=images.PNG)
filename = '/' + UploadHandler.get_gs_bucket_for_images() + 'blobstore_demo.png'
mimetype = 'image/png'
with gcs.open(filename,'w', content_type=mimetype) as f:
f.write(t)
blobstore_filename = '/gs' + filename
key = blobstore.create_gs_key(blobstore_filename)
We want to import contacts photos from google API.
Following code was working for me.
for email, name, entry in feed:
photo = client.GetPhoto(entry)
if photo:
fname = str(uuid.uuid4()) + '.jpg'
image_file = open(dname + '/' + fname, 'wb')
image_file.write(photo)
image_file.close()
result[email] = '/media/import/%s/%s' % (dir, fname)
Now, for some reasons, we get in files atom feed copy. So method GetPhoto no working.
Any ideas, why it happened and what is current way to retrieve contacts photo?
Here is work around google API changes. Now we're using direct requests to API.
for email, name, entry in feed:
photo_link = e.GetPhotoLink()
if photo_link:
request = http.request(
'GET',
photo_link.href,
headers={
'Authorization':'OAuth %s' % client.current_token.access_token
}
)
if request.status == 200:
photo = str(request.read())
fname = str(uuid.uuid4()) + '.jpg'
image_file = open(dname + '/' + fname, 'wb')
image_file.write(photo)
image_file.close()
result[email] = '/media/import/%s/%s' % (tid, fname) #str(photo.href) #
I would like to create a zip file on the fly to serve to users through Cherry Py: I tried the following code that produced an invalid zip file:
#cherrypy.expose
def ZipDir(self, *args):
path = "\\".join(args)
output = StringIO.StringIO()
file = zipfile.ZipFile(output, "w")
zip_filename = path + ".zip"
cherrypy.response.headers['Content-Type'] = 'application/zip'
cherrypy.response.headers['Content-Disposition'] = 'attachment; filename="%s"' % (zip_filename,)
dir = filter(lambda x: x.lower().endswith(".mp3") or not ("." in x), os.listdir("G:\\Music\\" + path))
for f in dir:
file.write("G:\\Music\\" + path + "\\" + f,f,zipfile.ZIP_DEFLATED)
return output.getvalue()
The file size looks about right, but it doesnt register as a zip file with any acrhicing applications.
I forgot to call file.close() before the return. That fixed it!