Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Using file.write() fails on S3 when files are missing #607

Closed
vdboor opened this issue Sep 25, 2018 · 6 comments · Fixed by #1282
Closed

Using file.write() fails on S3 when files are missing #607

vdboor opened this issue Sep 25, 2018 · 6 comments · Fixed by #1282
Labels

Comments

@vdboor
Copy link

vdboor commented Sep 25, 2018

This works:

storage = S3Boto3Storage()
storage.file_overwrite = True
storage.save('test.txt', BytesIO(b'data'))

This fails:

file = storage.open('test.txt', 'w')
file.write(b'data')
file.close()

The S3Boto3StorageFile.write() method tries to detect the file size (self.file.tell()) which raises an exception when the file doesn't exist yet.

>>> f = storage.open('test.txt', 'w')
>>> f.write(b'test')
Traceback (most recent call last):
  File "/usr/local/lib/python3.6/site-packages/storages/backends/s3boto3.py", line 128, in write
    if self.buffer_size <= self._buffer_file_size:
  File "/usr/local/lib/python3.6/site-packages/storages/backends/s3boto3.py", line 134, in _buffer_file_size
    pos = self.file.tell()
  File "/usr/local/lib/python3.6/site-packages/storages/backends/s3boto3.py", line 99, in _get_file
    if self._storage.gzip and self.obj.content_encoding == 'gzip':
  File "/usr/local/lib/python3.6/site-packages/boto3/resources/factory.py", line 339, in property_loader
    self.load()
  File "/usr/local/lib/python3.6/site-packages/boto3/resources/factory.py", line 505, in do_action
    response = action(self, *args, **kwargs)
  File "/usr/local/lib/python3.6/site-packages/boto3/resources/action.py", line 83, in __call__
    response = getattr(parent.meta.client, operation_name)(**params)
  File "/usr/local/lib/python3.6/site-packages/botocore/client.py", line 320, in _api_call
    return self._make_api_call(operation_name, kwargs)
  File "/usr/local/lib/python3.6/site-packages/botocore/client.py", line 623, in _make_api_call
    raise error_class(parsed_response, operation_name)
botocore.exceptions.ClientError: An error occurred (404) when calling the HeadObject operation: Not Found
@holmberd
Copy link

Related, #350

@sww314 sww314 added the s3boto label May 13, 2019
@divick
Copy link

divick commented Apr 6, 2020

No activity on this since more than a year. This started to happen for me suddenly and i am wondering what really changed for this to fail. I am still wondering if it is really a django-storages issue?

@michaelfward
Copy link

I'm experiencing the issue as well. Any workarounds?

@michaelfward
Copy link

Seems that open(), close(), and then open() + write() is a workaround for now

@nl-emmanuellodovice
Copy link

I had this problem also, my work around was to add a save_overwrite method

    def save_overwrite(self, name, content, max_length=None):
        """ Save method that makes sure the file is saved in the provided name by deleting the existing file if there is
         one. This method is useful when you are storing a file using a computed path and the path is not stored in
         the database.
        """
        if self.exists(name):
            self.delete(name)
        return self.save(name, content, max_length)

@jschneier
Copy link
Owner

Okay will fix, the issue here is that the gzip downloading path should only be called on files opened in read mode, not write.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

Successfully merging a pull request may close this issue.

7 participants