Esempio n. 1
0
    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)
Esempio n. 2
0
 def get_file_hash(self):
     return file_hash(self.file)
Esempio n. 3
0
    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']