def import_file(self, folder_path, file_name): full_path = folder_path + file_name extension = file_name.split('.')[-1] f = open(full_path, "rb") if extension == 'jpg': extension = 'jpeg' form = WallpaperForm(files={'file': SimpleUploadedFile( name='tmp.{extension}'.format(extension=extension), content=f.read(), content_type=extension )}) if form.is_valid(): logger.info('Saving image \'{}\''.format(file_name)) # Wallpaper wallpaper = form.save(commit=False) wallpaper.size = form.cleaned_data['file'].size wallpaper.hash = file_hash(form.cleaned_data['file']) form.cleaned_data['file'].file.seek(0) wallpaper.width, wallpaper.height = Image.open(form.cleaned_data['file'].file).size wallpaper.extension = extension wallpaper.file.save( 'w_{hash}.{extension}'.format(hash=wallpaper.hash, extension=wallpaper.extension), form.cleaned_data['file'] ) wallpaper.save() # Thumbnail form.cleaned_data['file'].file.seek(0) thumb_file = create_thumbnail(form.cleaned_data['file'].file, extension) thumb_width, thumb_height = Image.open(BytesIO(thumb_file)).size thumbnail = Thumbnail( size=sys.getsizeof(thumb_file), wallpaper=wallpaper, hash=file_hash(BytesIO(thumb_file)), width=thumb_width, height=thumb_height, extension=extension ) thumbnail.file.save( 't_{hash}.{extension}'.format(hash=thumbnail.hash, extension=extension), ContentFile(thumb_file) ) thumbnail.save() else: logger.info('Image \'{}\' did not validate: \'{}\''.format(file_name, form.errors)) os.remove(full_path)
def get_file_hash(self): return file_hash(self.file)
def clean_file(self): """ Validate the file on the following: - file type: only allow .jpeg and .png - file size: check the maximum file size - hash: dont allow duplicate images - width: sensible min and max image width - height: sensible min and max image height - megapixels: the combined width and height should yield a minimal size """ file_name = self.cleaned_data['file'].name # Check file type. # We need to get a file object for PIL. We might have a path or we # might have to read the data into memory. if hasattr(self.cleaned_data['file'], 'temporary_file_path'): f = self.cleaned_data['file'].temporary_file_path() elif hasattr(self.cleaned_data['file'], 'read'): f = BytesIO(self.cleaned_data['file'].read()) else: f = BytesIO(self.cleaned_data['file']['content']) try: img = PILImage.open(f) except Exception: # Python Imaging Library doesn't recognize it as an image raise ValidationError( 'Unsupported image type. Please upload png or jpeg. ({})'.format( file_name ) ) if img.format not in ('PNG', 'JPEG'): raise ValidationError( 'Unsupported image type. Please upload png or jpeg ({})'.format( file_name ) ) # Check file size if self.cleaned_data['file'] \ and self.cleaned_data['file']._size > self.MAX_FILE_SIZE * 1024: raise ValidationError( 'Please limit the file size to under {}MB ({})'.format( self.MAX_FILE_SIZE / 1024, file_name ) ) # Check file hash. self.cleaned_data['file'].seek(0) image_hash = file_hash(self.cleaned_data['file']) try: wallpaper = Wallpaper.objects.get(hash=image_hash) except Wallpaper.DoesNotExist: pass else: error_msg = 'This wallpaper already exists' if wallpaper.active is True: error_msg += ' (<a href="{}" target="_blank">{}</a>)'.format( reverse('walldb:wallpaper:details', args=(image_hash,)), image_hash ) elif wallpaper.active is None: error_msg += ', but has not yet been accepted' elif wallpaper.active is False: error_msg += ', but was rejected based on quality or content' error_msg += ' ({})'.format(file_name) raise ValidationError(mark_safe(error_msg)) # Check image width and height. self.cleaned_data['file'].file.seek(0) image_width, image_height = PILImage.open(self.cleaned_data['file'].file).size if WallpaperForm.MIN_IMAGE_PX_WIDTH < image_width > WallpaperForm.MAX_IMAGE_PX_WIDTH: raise ValidationError( "Wallpaper image width should be between '{}' and '{}' pixels" " ({})" .format( WallpaperForm.MIN_IMAGE_PX_WIDTH, WallpaperForm.MAX_IMAGE_PX_WIDTH, file_name ) ) if WallpaperForm.MIN_IMAGE_PX_HEIGHT < image_height > WallpaperForm.MAX_IMAGE_PX_HEIGHT: raise ValidationError( "Wallpaper image height should be between '{}' and '{}' pixels" " ({})" .format( WallpaperForm.MIN_IMAGE_PX_HEIGHT, WallpaperForm.MAX_IMAGE_PX_HEIGHT, file_name ) ) # Validate a wallpaper to have a minimum amount of mega pixels if (image_width * image_height) < WallpaperForm.MIN_PIXELS: raise ValidationError( 'Image size of \'{}x{}\' does not meet the minimum requirement' ' of at least 1.3 mega pixels (about \'1280x960\' for example)' ' ({})' .format( image_width, image_height, file_name ) ) return self.cleaned_data['file']