amol- / depot

Toolkit for storing files and attachments in web applications
MIT License
161 stars 41 forks source link

Need to set the file pointer to the beginning before upload #53

Closed mutr closed 6 years ago

mutr commented 6 years ago

I think you need to add file.seek(0, 0) somewhere in a create methods. It takes me a day to realise why this simple piece of code does not work as expected (produces empty files in datastores) :)

    for depot in DepotManager._depots:
      file = request.files['file']
      UPLOADED_FILES.append({depot: DepotManager.get(depot).create(file)})

Also it will be great to have DepotManager.list() function.

amol- commented 6 years ago

The list is missing on purpose. It's specific to the underlying used storage, some storages might miss support for listing their content at all and depot won't expose features that are available only on some storages.

Also for the seek, it's not really expected you read back from a file you just saved. That behaves pretty much like it would if you saved the file on disk yourself, so if you need to read the file again you are supposed to call seek youself, as you are the only one who knows that the source is seekable and that you are trying to reuse it.

mutr commented 6 years ago

By Depot Manager.list() I mean list configured depots.

Ok, but simple note about seek in documentation would be great. Thank you.

mutr commented 6 years ago

It's not convenient if I need to store two copy of file in the database :disappointed:

content_public   = UploadedFileProperty(upload_storage='amazon')
content_offline  = UploadedFileProperty(upload_storage='mongodb')

I have to open file twice or copy file object in memory:

fl = open('file.jpg', 'rb')
fl1 = open('file.jpg', 'rb')
attach = Attachment(content_public=fl, content_offline=fl1)

I think simple option like seek_back=True would be better solution.

amol- commented 6 years ago

You don't have to open twice or copy the file, you just have to assign one field at the time:

a = Attachment()
a.content_public = fl
fl.seek(0)
a.content_offline = fl

Or you can write a wrapper that does the seekback for you, just make a class that seeks to 0 at the end of read and you are done:

attach = Attachment(content_public=SeekBackFile(fl), 
                    content_offline=SeekBackFile(fl))

I don't recall there is any Python API that seeks back after reading a file, and there is a good reason for that. You have to guarantee at all that your source is seekable. Only you who created the original entity can know if it's seekable.