﻿id	summary	reporter	owner	description	type	status	component	version	severity	resolution	keywords	cc	stage	has_patch	needs_docs	needs_tests	needs_better_patch	easy	ui_ux
34674	Updating the file contents of a Django FileField during upload results in I/O error	Jeroen Jacobs	nobody	"I'm trying to encrypt the contents of a file that is being uploaded. This is the relevant code snippet:

{{{
class AppFile(models.Model):
    app_file = models.FileField(upload_to=upload_to, validators=[validate_file_size])
    encrypted_data_key = models.CharField(max_length=500, blank=True)

    def encrypt_file_with_data_key(self, data_key):
        cipher = Fernet(data_key)
        with self.app_file.open(mode='rb') as file:
            file_data = file.read()
            encrypted_data = cipher.encrypt(file_data)
        with self.app_file.open(mode='wb') as encrypted_file:
            encrypted_file.write(encrypted_data)

    def save(self, *args, **kwargs):
        if self._state.adding is True:

            # New image being uploaded
            encrypted_data_key, data_key = self.generate_data_key_from_vault()
            self.encrypted_data_key = encrypted_data_key

            # Encrypt the uploaded image file
            self.encrypt_file_with_data_key(data_key)

        super().save(args, kwargs)

}}}

I prefer this approach as this is agnostic of the StorageProvider being used. I also want to avoid detaching the file to a temporary folder, and re-attach it after encryption.


However, this results in the following error:

{{{
Traceback (most recent call last):
  File ""/Users/jeroenjacobs/.pyenv/versions/myapp/lib/python3.11/site-packages/django/core/handlers/exception.py"", line 55, in inner
    response = get_response(request)
               ^^^^^^^^^^^^^^^^^^^^^
  File ""/Users/jeroenjacobs/.pyenv/versions/myapp/lib/python3.11/site-packages/django/core/handlers/base.py"", line 197, in _get_response
    response = wrapped_callback(request, *callback_args, **callback_kwargs)
               ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File ""/Users/jeroenjacobs/.pyenv/versions/myapp/lib/python3.11/site-packages/django/views/generic/base.py"", line 84, in view
    return self.dispatch(request, *args, **kwargs)
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File ""/Users/jeroenjacobs/.pyenv/versions/myapp/lib/python3.11/site-packages/django/views/generic/base.py"", line 119, in dispatch
    return handler(request, *args, **kwargs)
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File ""/Users/jeroenjacobs/.pyenv/versions/myapp/lib/python3.11/site-packages/django/views/generic/edit.py"", line 184, in post
    return super().post(request, *args, **kwargs)
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File ""/Users/jeroenjacobs/.pyenv/versions/myapp/lib/python3.11/site-packages/django/views/generic/edit.py"", line 153, in post
    return self.form_valid(form)
           ^^^^^^^^^^^^^^^^^^^^^
  File ""/Users/jeroenjacobs/.pyenv/versions/myapp/lib/python3.11/site-packages/django/contrib/messages/views.py"", line 12, in form_valid
    response = super().form_valid(form)
               ^^^^^^^^^^^^^^^^^^^^^^^^
  File ""/Users/jeroenjacobs/.pyenv/versions/myapp/lib/python3.11/site-packages/django/views/generic/edit.py"", line 135, in form_valid
    self.object = form.save()
                  ^^^^^^^^^^^
  File ""/Users/jeroenjacobs/.pyenv/versions/myapp/lib/python3.11/site-packages/django/forms/models.py"", line 548, in save
    self.instance.save()
  File ""/Users/jeroenjacobs/PycharmProjects/myapp/mainapp/models.py"", line 90, in save
    self.encrypt_file_with_data_key(data_key)
  File ""/Users/jeroenjacobs/PycharmProjects/myapp/mainapp/models.py"", line 77, in encrypt_file_with_data_key
    with self.app_file.open(mode='wb') as encrypted_file:
         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File ""/Users/jeroenjacobs/.pyenv/versions/myapp/lib/python3.11/site-packages/django/db/models/fields/files.py"", line 80, in open
    self.file.open(mode)
  File ""/Users/jeroenjacobs/.pyenv/versions/myapp/lib/python3.11/site-packages/django/core/files/uploadedfile.py"", line 115, in open
    self.file.seek(0)
ValueError: I/O operation on closed file.
}}}

Reading the contents doesn't seem to be a problem, but writing seems to generate an error, despite `open` being called.


"	Bug	closed	File uploads/storage	4.2	Normal	duplicate			Unreviewed	0	0	0	0	0	0
