-
-
Notifications
You must be signed in to change notification settings - Fork 864
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
S3Boto3Storage raises ValueError: I/O operation on closed file. #382
Comments
@tsifrer thanks for the report. Just to clarify -- this happens on both 1.6.4 and 1.6.5? |
@jschneier Correct, happens on both, 1.6.4 and 1.6.5. |
I'm also having this issue, any update on it ? |
It looks like the save of S3Boto3Storage now closes the file. I think it's a side effect of c73680e but haven't tried with the commit reverted. |
I am also facing this issue but not with collectstatic. But rather with uploading a file. I just moved from boto 2.40.0 to boto3 1.4.7 and django-storages from 1.1.8 to 1.6.5. After reading the comments above, I changed django-storages to 1.6.3 but the issue still occurs. Any help? |
I just tried going back versions even further and at 1.5.0, this issue doesn't occur. It occurs on every version later than 1.5.0. Here is a snippet for uploading a cropped image file:-
|
I experience this issue with version 1.6.5, but not with 1.6.3. |
Same as @abhinavnair for me. Uploading a file results in a crash, but The bug seems to be filetype independent, The same issue occurs on image and text files. The 1.5 version works well, but the bug shows up on every version greater than it. |
Has anyone manged to work around this? |
@WhyNotHugo yes, you don't need to assume that the saved file handler is open #382 (comment) |
@abhinavnair |
@xrmx It's not an assumption I'm making; it's an assumption Note that, if you're using |
I had to lock the Pipfile to this:
|
I had this issue too with django-storages == "1.6.5" but after downgrading to "1.5.0" with suggestion by @abhinavnair problem doesn't occured. |
I get this issue with django-storages version 1.6.6 too. |
Using a custom StorageClass fix the issue : from storages.backends.s3boto3 import S3Boto3Storage, SpooledTemporaryFile
import os
class CustomS3Boto3Storage(S3Boto3Storage):
def _save_content(self, obj, content, parameters):
"""
We create a clone of the content file as when this is passed to boto3 it wrongly closes
the file upon upload where as the storage backend expects it to still be open
"""
# Seek our content back to the start
content.seek(0, os.SEEK_SET)
# Create a temporary file that will write to disk after a specified size
content_autoclose = SpooledTemporaryFile()
# Write our original content into our copy that will be closed by boto3
content_autoclose.write(content.read())
# Upload the object which will auto close the content_autoclose instance
super(CustomS3Boto3Storage, self)._save_content(obj, content_autoclose, parameters)
# Cleanup if this is fixed upstream our duplicate should always close
if not content_autoclose.closed:
content_autoclose.close() |
I tried suggestion by @coderberry and it didn't work. I tried @WhyNotHugo pull request (did One thing I noticed was that when I tried to upload an image the first time it crashed (but uploaded), but second attempt worked. Every image worked in second attempt but not in first. I managed to get it working with example by @charlesthk |
the PR from @WhyNotHugo worked with Boto3==1.5.36 and it seems @charlesthk's fix works with the latest version of everything |
@charlesthk can you make a pull request with this to the master? |
I tried the solution by @charlesthk but it gives me an error: cant' start new thread. Edit: The error occurs once in a while but not every time. I have been searching for the solution but found nothing. |
I confirm that |
And I also confirm that @charlesthk solution works with django-storages 1.6.6 (currently the lastest) Thanks @charlesthk! 🎉 |
#481 fixes similar issue in Google Cloud Storage. All the storages need to act like the Django file storage, which calls |
I still experience this issue in django-storages 1.7.1 . |
Also having this issue. The custom class in @charlesthk's comment solves it. |
What needs to happen to get this fix enabled by default? |
Using this class with the new django-storages gives the error: ValueError: seek of closed file This change should fix that - jschneier/django-storages#382 (comment)
Using this class with the new django-storages gives the error: ValueError: seek of closed file This change should fix that - jschneier/django-storages#382 (comment)
This is @mannpy's solution from: jschneier#382 (comment)
Pull request opened for this fix here: #905 |
For me, a patch like this (which does not involve copying) fixes the issues. --- site-packages/storages/backends/s3boto3.py.orig 2020-07-31 11:46:19.309504453 +0300
+++ site-packages/storages/backends/s3boto3.py 2020-07-31 11:58:25.400758620 +0300
@@ -38,10 +38,16 @@
boto3_version_info = tuple([int(i) for i in boto3_version.split('.')])
+# https://github.com/boto/s3transfer/issues/80#issuecomment-562356142
+class NonCloseableBufferedReader(io.BufferedReader):
+ def close(self):
+ self.flush()
+
+
@deconstructible
class S3Boto3StorageFile(File):
"""
The default file object used by the S3Boto3Storage backend.
@@ -542,11 +548,12 @@
obj = self.bucket.Object(encoded_name)
if self.preload_metadata:
self._entries[encoded_name] = obj
content.seek(0, os.SEEK_SET)
- obj.upload_fileobj(content, ExtraArgs=params)
+ with NonCloseableBufferedReader(content) as reader:
+ obj.upload_fileobj(reader, ExtraArgs=params)
return cleaned_name
def delete(self, name):
name = self._normalize_name(self._clean_name(name))
self.bucket.Object(self._encode_name(name)).delete() |
This looks like a better solution, can we possibly have a patch for this and new version? I know it's because of |
Can I see a full version of your code? where does ABC and SpooledTemporaryFile comes from? |
@robertpro |
@pasevin Thanks! These are the imports: import os
from abc import ABC
from tempfile import SpooledTemporaryFile
from storages.backends.s3boto3 import S3Boto3Storage |
in django-storages==1.6.5, te S3Boto3Storage backend closes the file after saving. This effectively prevents from re-opening the same file later. Bug: jschneier/django-storages#382 Resolution: jschneier/django-storages#754
November 2020 , I downgraded django stotages from 1.9.0 to 1.5.0, it solved the issue for me |
I much prefer this non-copying solution given that the reason that |
Can someone verify that this branch resolves their issue? |
Yes, it solves my issue. |
@jschneier I need to wait to see this change on pypi? |
I'm going to push in a breaking change at some point so I wouldn't recommend. I'll just deploy as-is actually. |
@israellias just released. |
Unfortunately the fix seems to have broken things more generally (see #967) so I've put together an alternative one. My solution is to separate out the collectstatic handling since that seems to be quite different & not as common. Please take a look at #968. This way it'll just be a quick update to a setting and any additional fixes are logically separated. |
@jschneier Can you please specify what tag/release this is fixed in? |
Hey everyone! |
I'm getting this error occasionally. (ValueError: seek of closed file) boto3 1.18.28 DEFAULT_FILE_STORAGE = 'storages.backends.s3boto3.S3Boto3Storage' Should we use the patch from @robertpro ? |
in django-storages==1.6.5, te S3Boto3Storage backend closes the file after saving. This effectively prevents from re-opening the same file later. Bug: jschneier/django-storages#382 Resolution: jschneier/django-storages#754
When running
python manage.py collectstatic
we get the following exception:This only happens when using django-storages 1.6.4 or above.
Versions 1.6.3 and lower work fine.
We're using Django 1.11.4, python 3.5.2, boto3 1.4.6.
The text was updated successfully, but these errors were encountered: