You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
1.Go to the edit page
2. Save the edits without uploading a new image.
4. If you check the image that was there earlier, it will be damaged.
Expected behavior
it is expected to receive modified data in other fields, without damaging the image
Actual behavior
No response
Debugging material
I did a little research. I found that when submitting the form, if you do not embed a new image, there is file data in the form, but they are empty. web_1 | INFO 2024-08-12 07:05:52.875 request id: None - core.admin:on_model_change - Field name: image_url, Field type: <class 'starlette.datastructures.UploadFile'>, Field value: UploadFile(filename='', size=0, headers=Headers({'content-disposition': 'form-data; name="image_url"; filename=""', 'content-type': 'application/octet-stream'}))
By adding a simple check and removing this field from the data, I avoid the problem of file corruption:
` async def on_model_change(self, data, model, is_created, request):
form = await request.form()
for key, value in form.items():
app_logger.info(
f"Field name: {key}, Field type: {type(value)}, Field value: {value}"
)
if "image_url" in form:
image = form["image_url"]
if image.filename == "":
data.pop("image_url", None)
app_logger.info("Image field drop")`
I encountered the exact same problem and solved it in the following way.
I created a custom type FileType and overrode the process_bind_param function. I added transliteration of the file name from Cyrillic (otherwise, the name gets erased, leaving only the extension, for example: название_файла.png -> png).
Additionally, as mentioned above, I found a bug with file corruption and added a check.
from fastapi_storages.integrations.sqlalchemy import FileType as _FileType
class FileType(_FileType):
def process_bind_param(self, value: Any, dialect: Dialect) -> Optional[str]:
if value is None:
return value
if len(value.file.read(1)) != 1:
return None
#Transliteration
file_name_language = detect_language(value.filename)
file_name = translit(value.filename, reversed=True) if file_name_language else value.filename
file = StorageFile(name=file_name, storage=self.storage)
#Fix file corruption
if value.size is None:
return file.name
file.write(file=value.file)
value.file.close()
return file.name
Hey, thanks both for the investigations.
I think it was already discussed somewhere else, but in this case your file field was nullable so you could do this.
We also have to consider the case where the file field is required and we are editing this.
Looking at Django admin seems like they work around this that if the file field is required but are editing an object that already has a file, then the field is optional so you either override it or the existing one remains. I think we can follow the same approach we need changes both in SQLAdmin and fastapi-storages. I will look into this.
Checklist
master
.Describe the bug
If you try to edit any fields of the form or submit the form unchanged, the image file that was uploaded earlier will be corrupted.
Here is my code:
Steps to reproduce the bug
1.Go to the edit page
2. Save the edits without uploading a new image.
4. If you check the image that was there earlier, it will be damaged.
Expected behavior
it is expected to receive modified data in other fields, without damaging the image
Actual behavior
No response
Debugging material
I did a little research. I found that when submitting the form, if you do not embed a new image, there is file data in the form, but they are empty.
web_1 | INFO 2024-08-12 07:05:52.875 request id: None - core.admin:on_model_change - Field name: image_url, Field type: <class 'starlette.datastructures.UploadFile'>, Field value: UploadFile(filename='', size=0, headers=Headers({'content-disposition': 'form-data; name="image_url"; filename=""', 'content-type': 'application/octet-stream'}))
By adding a simple check and removing this field from the data, I avoid the problem of file corruption:
` async def on_model_change(self, data, model, is_created, request):
Environment
ubuntu 23.04, python 3.10, sqladmin[full] latest, fastapi 0.111, sqlalchemy[asyncio]~=2.0.30
Additional context
No response
The text was updated successfully, but these errors were encountered: