fix(reports): read file as binary so content and content size matches#12410
fix(reports): read file as binary so content and content size matches#12410XDjackieXD wants to merge 1 commit into
Conversation
When reading files as text, the file size reported byht python seems to mismatch the actual content size (for example 1458 instead of 1460 in inventree_transfer_order_report.html) which leads to Content-Length header being set to the wrong value when using S3 as the storage backend.
✅ Deploy Preview for inventree-web-pui-preview canceled.
|
|
That's an odd one. Can you please add some regression tests with some golden files |
|
To be honest: I have no idea of django or the used testing framework. The "golden sample" seems to be To find this I patched the The output for I'd be glad if you could write the tests for this. |
|
I found the issue: there is a unicode symbol in line 13 of To be fair I'm not even sure now if this is a proper fix then but any other potential fix would probably need to be done within django-storage while doing it this way should not break anything and lead to a quick solution. |
|
That can be OS and deployment specific; git (project created on Unix like systems) and windows for example often has issues |
| 'Template file %s does not exist in %s', file_name, file | ||
| ) | ||
| return ContentFile(file.open('r').read(), os.path.basename(file_name)) | ||
| return ContentFile(file.open('rb').read(), os.path.basename(file_name)) |
There was a problem hiding this comment.
Binary read means we have to handle text encoding issues downstream ourselves; have you confirmed this does not cause any other issues with non-English languages
There was a problem hiding this comment.
No I have not confirmed that.
|
How does this result in the wrong content length? Shouldn't any files be served directly by a proxy? Django should not be getting in the way of this. Unless I'm misunderstanding the chain of events here |
|
Depends on the specific action; when the content is accessed via the Django storage framework there are some headers set that might be influenced by the perceived and saved size. There is not much actual reproduction info included so I can not make more concrete statements about the actual path for this to occur |
Not the Content-Length when served to the client but the Content-Length when Inventree tries to upload the files to S3 when the storage backend is set to S3 (I have not checked if the content length to the client would be wrong when served through inventree but the file with issues is never directly served to clients so even if that would be an issue 99.9% of users would have never hit such an issue on the client facing side). It's weird to me that a seek to the end would not return the length in bytes but the length in characters when the file is opened in text mode but apparently that is how python behaves. I'm by no means a python expert but I also could not find any other way to get the size of a File object in python which is probably why django-storages (or boto3?) uses this method to get the size of the file. |
|
Looking a bit more into django, django-storage and boto3 it is still not clear to me where this "mishap" regarding the filesize happens. Sadly it seems to be very much not standardized if the size property should represent the length in characters or the size in bytes. |
When reading files as text, the file size reported by python seems to mismatch the actual content size (for example 1458 instead of 1460 in inventree_transfer_order_report.html) which leads to Content-Length header being set to the wrong value when using S3 as the storage backend.
As this only seems to be happening with this file it might also be some weirdness with this specific template but reading in binary mode seems to be less error-prone in general.