2014-04-19 77 views
3

我意識到這是一個簡單的任務,這個問題得到回答多次,但我無法得到它。在將圖像保存到磁盤之前,有沒有辦法調整大小和裁剪圖像?我發現的所有解決方案傾向於存儲圖像,調整大小,然後再存儲它。我可以這樣做嗎?如何在保存之前用PIL調整上傳文件的大小?

# extending form's save() method 
def save(self): 
    import Image as pil 

    # if avatar is uploaded, we need to scale it 
    if self.files['avatar']: 
     img = pil.open(self.files['avatar']) 
     img.thumbnail((150, 150), pil.ANTIALIAS) 

     # ??? 
     # self.files['avatar'] is InMemoryUpladedFile 
     # how do I replace self.files['avatar'] with my new scaled image here? 
     # ??? 

    super(UserForm, self).save() 

回答

6

我能想出解決辦法。您只需將修改的文件保存爲StringIO,然後從中創建一個新的InMemoryUploadedFile。下面是完整的解決方案:

def save(self): 

    import Image as pil 
    import StringIO, time, os.path 
    from django.core.files.uploadedfile import InMemoryUploadedFile 

    # if avatar is uploaded, we need to scale it 
    if self.files['avatar']: 
     # opening file as PIL instance 
     img = pil.open(self.files['avatar']) 

     # modifying it 
     img.thumbnail((150, 150), pil.ANTIALIAS) 

     # saving it to memory 
     thumb_io = StringIO.StringIO() 
     img.save(thumb_io, self.files['avatar'].content_type.split('/')[-1].upper()) 

     # generating name for the new file 
     new_file_name = str(self.instance.id) +'_avatar_' +\ 
         str(int(time.time())) + \ 
         os.path.splitext(self.instance.avatar.name)[1] 

     # creating new InMemoryUploadedFile() based on the modified file 
     file = InMemoryUploadedFile(thumb_io, 
            u"avatar", # important to specify field name here 
            new_file_name, 
            self.files['avatar'].content_type, 
            thumb_io.len, 
            None) 

     # and finally, replacing original InMemoryUploadedFile() with modified one 
     self.instance.avatar = file 

    # now, when form will be saved, it will use the modified file, instead of the original 
    super(UserForm, self).save() 
0

我不熟悉PIL,但我可以從文檔看,你可以把文件對象爲「文件」參數「開放」的功能。

Django request.FILES存儲UploadedFile對象 - 上傳文件(保存在內存或臨時文件中)的簡單包裝,它支持讀取,查找和指示操作,因此可以直接傳遞給PIL「打開」功能。

相關問題