fix: strip exif data from image files before uploading

This commit is contained in:
Abhishek Balam 2020-11-30 11:59:16 +05:30
parent dd8e2114ab
commit bd2e3530cd
3 changed files with 35 additions and 5 deletions

View file

@ -30,7 +30,7 @@ import frappe
from frappe import _, conf
from frappe.model.document import Document
from frappe.utils import call_hook_method, cint, cstr, encode, get_files_path, get_hook_method, random_string, strip
from frappe.utils.image import strip_exif_data
class MaxFileSizeReachedError(frappe.ValidationError):
pass
@ -456,6 +456,7 @@ class File(Document):
def save_file(self, content=None, decode=False, ignore_existing_file_check=False):
file_exists = False
self.content = content
if decode:
if isinstance(content, text_type):
self.content = content.encode("utf-8")
@ -466,10 +467,15 @@ class File(Document):
if not self.is_private:
self.is_private = 0
self.content_type = mimetypes.guess_type(self.file_name)[0]
if self.content_type and "image" in self.content_type:
self.content = strip_exif_data(self.content, self.content_type)
self.file_size = self.check_max_file_size()
self.content_hash = get_content_hash(self.content)
self.content_type = mimetypes.guess_type(self.file_name)[0]
duplicate_file = None
# check if a file exists with the same content hash and is also in the same folder (public or private)

View file

@ -5,7 +5,7 @@ from __future__ import unicode_literals, print_function
import os
def resize_images(path, maxdim=700):
import Image
from PIL import Image
size = (maxdim, maxdim)
for basepath, folders, files in os.walk(path):
for fname in files:
@ -17,3 +17,26 @@ def resize_images(path, maxdim=700):
im.save(os.path.join(basepath, fname))
print("resized {0}".format(os.path.join(basepath, fname)))
def strip_exif_data(content, content_type):
""" Strips exif from image files which support it.
Works by creating a new Image object which ignores exif by
default and then extracts the binary data back into content.
Returns: stripped image content
"""
from PIL import Image
import io
original_image = Image.open(io.BytesIO(content))
output = io.BytesIO()
new_image = Image.new(original_image.mode, original_image.size)
new_image.putdata(list(original_image.getdata()))
new_image.save(output, format=content_type.split('/')[-1].upper())
content = output.getvalue()
return content

View file

@ -73,4 +73,5 @@ pycryptodome==3.9.8
paytmchecksum==1.7.0
wrapt==1.10.11
razorpay==1.2.0
rsa>=4.1 # not directly required, pinned by Snyk to avoid a vulnerability
rsa>=4.1 # not directly required, pinned by Snyk to avoid a vulnerability
pillow==8.0.1