How to change extension of uploaded file to "png" in django?
in views:
def pictures_2png(file):
return Image.open(file).save('img.png')
Pictures.objects.create_pictures(car, pictures_2png(request.FILES["picture"]))
Without pictures_2png file saves on hard disk with it old extension (jpg, gif, etc). Something wrong in that function, but if I use it (function) in ipython with my local images - it works. Whats wrong? How to fix it?
Thanks.
via link
def pictures_2png(file):
buffer = StringIO()
Image.open(file).save(buffer, "PNG")
return InMemoryUploadedFile(buffer, None, 'test.png', 'image/png', buffer.len, None)
Related
I'm trying to convert a pdf file uploaded in Django to a jpg file. I would like to use the file directly in the InMemoryUploadedFile state.
I tried to use wand but without any success.
Here is the code I wrote:
from django.shortcuts import render
from wand.image import Image as wi
# Create your views here.
def readPDF(request):
context = {}
if request.method == 'POST':
uploaded_file = request.FILES['document']
if uploaded_file.content_type == 'application/pdf':
pdf = wi(filename=uploaded_file.name, resolution=300)
pdfImage = pdf.convert("jpeg")
return render(request, 'readPDF.html', {"pdf": pdfImage})
I tried different things like using uploaded_file.file or uploaded_file.name as the first argument for the wand image but without any success.`
I thank you in advance for your help!
Should be able to pass InMemoryUploadedFile directly to Wand's constructor.
uploaded_file = request.FILES['document']
if uploaded_file.content_type == 'application/pdf':
with wi(file=uploaded_file, resolution=300) as pdf:
# ...
However, I wouldn't recommend attempting to convert PDF pages to JPEGs in a HTTP request. Best to write the document to storage, and have a background worker manage the slow / unsafe tasks.
I have a simple django platform where I can upload text files. Ultimately I want to return a downloadable mp3 audio file made from the text in the uploaded file. My problem currently is that I cannot seem to correctly specify the type of file that the website outputs for download.
I then tried to make the downloadable output of the website an mp3 file:
views.py (code adapted from https://github.com/sibtc/simple-file-upload)
def simple_upload(request):
if request.method == 'POST' and request.FILES['myfile']:
myfile = request.FILES['myfile']
print(str(request.FILES['myfile']))
x=str(myfile.read())
tts = gTTS(text=x, lang='en')
response=HttpResponse(tts.save("result.mp3"),content_type='mp3')
response['Content-Disposition'] = 'attachment;filename=result.mp3'
return response
return render(request, 'core/simple_upload.html')
Upon pressing the upload button, the text-to-speech conversion is successful but the content_type of the response is not definable as 'mp3'. The file that results from the download is result.mp3.txt and it contains 'None'.
Can you try to prepare your response using the sample code below?
I've managed to return CSV files correctly this way so it might help you too.
Here it is:
HttpResponse(content_type='text/plain') # Plain text file type
response['Content-Disposition'] = 'attachment; filename="attachment.txt"' # Plain text file extension
response.write("Hello, this is the file contents.")
return response
There are two problems I can see here. The first is that tts.save() returns None, and that is getting passed directly to the HttpResponse. Secondly, the content_type is set to mp3 and ought to be set to audio/mp3.
After calling tts.save(), open the mp3 and pass the file handle to the HttpResponse, and then also set the content_type correctly - for example:
def simple_upload(request):
if request.method == 'POST' and request.FILES['myfile']:
...
tts.save("result.mp3")
response=HttpResponse(open("result.mp3", "rb"), content_type='audio/mp3')
I've got an app deployed on Heroku using Django, and so far it seems to be working but I'm having a problem uploading new thumbnails. I have installed Pillow to allow me to resize images when they're uploaded and save the resized thumbnail, not the original image. However, every time I upload, I get the following error: "This backend doesn't support absolute paths." When I reload the page, the new image is there, but it is not resized. I am using Amazon AWS to store the images.
I'm suspecting it has something to do with my models.py. Here is my resize code:
class Projects(models.Model):
project_thumbnail = models.FileField(upload_to=get_upload_file_name, null=True, blank=True)
def __unicode__(self):
return self.project_name
def save(self):
if not self.id and not self.project_description:
return
super(Projects, self).save()
if self.project_thumbnail:
image = Image.open(self.project_thumbnail)
(width, height) = image.size
image.thumbnail((200,200), Image.ANTIALIAS)
image.save(self.project_thumbnail.path)
Is there something that I'm missing? Do I need to tell it something else?
Working with Heroku and AWS, you just need to change the method of FileField/ImageField 'path' to 'name'. So in your case it would be:
image.save(self.project_thumbnail.name)
instead of
image.save(self.project_thumbnail.path)
I found the answer with the help of others googling as well, since my searches didn't pull the answers I wanted. It was a problem with Pillow and how it uses absolute paths to save, so I switched to using the storages module as a temp save space and it's working now. Here's the code:
from django.core.files.storage import default_storage as storage
...
def save(self):
if not self.id and not self.project_description:
return
super(Projects, self).save()
if self.project_thumbnail:
size = 200, 200
image = Image.open(self.project_thumbnail)
image.thumbnail(size, Image.ANTIALIAS)
fh = storage.open(self.project_thumbnail.name, "w")
format = 'png' # You need to set the correct image format here
image.save(fh, format)
fh.close()
NotImplementedError: This backend doesn't support absolute paths - can be fixed by replacing file.path with file.name
How it looks in the the console
c = ContactImport.objects.last()
>>> c.json_file
<FieldFile: protected/json_files/data_SbLN1MpVGetUiN_uodPnd9yE2prgeTVTYKZ.json>
>>> c.json_file.name
'protected/json_files/data_SbLN1MpVGetUiN_uodPnd9yE2prgeTVTYKZ.json'
In order to resize images upon upload (using PIL), I'm overriding the save method for my Article model like so:
def save(self):
super(Article, self).save()
if self.image:
size = (160, 160)
image = Image.open(self.image)
image.thumbnail(size, Image.ANTIALIAS)
image.save(self.image.path)
This works locally but in production I get an error:
NotImplementedError: This backend doesn't support absolute paths.
I tried replacing the image.save line with
image.save(self.image.url)
but then I get an IOError:
[Errno 2] No such file or directory: 'https://my_bucket_name.s3.amazonaws.com/article/article_images/2.jpg'
That is the correct location of the image though. If I put that address in the browser, the image is there. I tried a number of other things but so far, no luck.
You should try and avoid saving to absolute paths; there is a File Storage API which abstracts these types of operations for you.
Looking at the PIL Documentation, it appears that the save() function supports passing a file-like object instead of a path.
I'm not in an environment where I can test this code, but I believe you would need to do something like this instead of your last line:
from django.core.files.storage import default_storage as storage
fh = storage.open(self.image.name, "w")
format = 'png' # You need to set the correct image format here
image.save(fh, format)
fh.close()
For me default.storage.write() did not work, image.save() did not work, this one worked. See this code if anyone is still interested. I apologize for the indentation. My project was using Cloudinary and Django small project.
from io import BytesIO
from django.core.files.base import ContentFile
from django.core.files.storage import default_storage as storage
def save(self, *args, **kargs):
super(User, self).save(*args, **kargs)
# After save, read the file
image_read = storage.open(self.profile_image.name, "r")
image = Image.open(image_read)
if image.height > 200 or image.width > 200:
size = 200, 200
# Create a buffer to hold the bytes
imageBuffer = BytesIO()
# Resize
image.thumbnail(size, Image.ANTIALIAS)
# Save the image as jpeg to the buffer
image.save(imageBuffer, image.format)
# Check whether it is resized
image.show()
# Save the modified image
user = User.objects.get(pk=self.pk)
user.profile_image.save(self.profile_image.name, ContentFile(imageBuffer.getvalue()))
image_read = storage.open(user.profile_image.name, "r")
image = Image.open(image_read)
image.show()
image_read.close()
If you are working with cloud storages for files in Django
NotImplementedError: This backend doesn't support absolute paths
To fix it you need to replace file.path with file.name
For code in the the question: image.save(self.image.path) with image.save(self.image.name)
Here how it looks like in the console
>>> c = ContactImport.objects.last()
>>> c.json_file.name
'protected/json_files/data_SbLN1MpVGetUiN_uodPnd9yE2prgeTVTYKZ.json'
>>> c.json_file
<FieldFile: protected/json_files/data_SbLN1MpVGetUiN_uodPnd9yE2prgeTVTYKZ.json>
>>> c.json_file.url
'https://storage.googleapis.com/super-secret/media/api/protected/json_files/data_SbLN1MpVGetUiN_uodPnd9yE2prgeTVTYKZ.json?Expires=1631378947&GoogleAccessId=secret&Signature=ga7...'
I want to create thumbnails of uploaded image files and save them with "_th" at the end of the filename. Currently, I am using the following code:
def _create_thumbnail(img_path):
image = Image.open(img_path)
if image.mode not in ("L", "RGB"):
image = image.convert("RGB")
image.thumbnail(MEDIA_THUMBNAIL_SIZES, Image.ANTIALIAS)
return image.save(img_path, 'JPEG', quality=MEDIA_THUMBNAIL_QUALITY)
It overwrites the original file. Is there a way to easily change the name of the file to include _th before the file extension and save it in the same place?
Also, I am saving the thumbnail after the post save signal using the following method:
#receiver(post_save, sender=Media, dispatch_uid="media_create_thumb")
def create_media_thumbnail(sender, **kwargs):
thumb = generate_thumbnail(kwargs['instance'].file)
I was wondering if this is an ok (pythonic?) way of using signals? Since I am not using the django admin panel, using the admins post save isn't an option.
This method to create thumbnails will be open to users, so if there is anything about the above code which might cause problems, I'd appreciate the heads up!
I would try the following:
import os
(head, tail) = os.path.split(img_path)
(name,ext)=tail.split('.')
tail=name+'_th.'+ext
img_path=os.path.join(head,tail)
edit:
as i found out recently, you can even shortcut that:
(name,ext)=os.path.splitext(img_path)
img_path = name + '_th.' + ext