How to get file and SHA-1 digest of downloaded file?

I have this model in a Django application:

class Image(models.Model): image_file = models.ImageField( upload_to='images/', width_field='width', height_field='height' ) width = models.PositiveIntegerField( blank = True, null = True, editable = False ) height = models.PositiveIntegerField( blank = True, null = True, editable = False ) sha1 = models.CharField(max_length=32, blank=True, editable=False) filesize = models.PositiveIntegerField(blank=True, null=True, editable=False) 

Now I can upload images through the Django admin site. And the width and height properties are stored in the database automatically when it is loaded due to special ImageField parameters.

But I would also like to automatically digest the downloaded file size and SHA-1 and save these properties too. How can I do it?

+4
source share
3 answers

It has been a while, but something like this should work:

 import hashlib class Image(models.Model): #... def save(self, *args, **kwargs): super(Image, self).save(*args, **kwargs) f = self.image_file.open('rb') hash = hashlib.sha1() if f.multiple_chunks(): for chunk in f.chunks(): hash.update(chunk) else: hash.update(f.read()) f.close() self.sha1 = hash.hexdigest() self.filesize = self.image_file.size 

EDIT: Added Dan reading suggestion in piece. The default block size is 64 KB.

+3
source

I'm not sure you can do this automatically. But ImageField also a FileField , so you can always open the file and calculate the checksum using hashlib.sha1 . You will need to read the file to calculate the checksum so that you can sniff the size at the same time.

Some time has passed since I used Django ORM, but I believe that there is a way to write a method that is called whenever the model instance is saved or read from the main repository. That would be a good place to calculate.

+1
source

Although Burkhan Khalid gave the answer, but I think this is still part of the puzzle. This still does not solve the problem of saving to the database. Here is a complete solution that also uses the newer with clause to take advantage of the Python and Django context_manager (so file.close () is not necessary, this happens automatically):

 import hashlib class Image(models.Model): #... def save(self, *args, **kwargs): with self.image_file.open('rb') as f: hash = hashlib.sha1() if f.multiple_chunks(): for chunk in f.chunks(): hash.update(chunk) else: hash.update(f.read()) self.sha1 = hash.hexdigest() self.filesize = self.image_file.size super(Image, self).save(*args, **kwargs) 

Note that super () is called in the with clause. This is important, otherwise you will receive an error message: ValueError: I/O operation on closed file. Django tries to read a closed file, thinking that it is open when you already closed it. This is also the last command to save everything that we updated to the database (this was left in the previous best answer, where you most likely have to call save () again to really save this data)

0
source

Source: https://habr.com/ru/post/1392276/


All Articles