caiyue1993/IceCream

CreamAsset created from URL

Fonceur opened this issue · 5 comments

From the parameters description of the create method, it says: "url: The URL of the file to store. Any path extension on the file (e.g. "mov") will be maintained".

Expected behavior

So I would expect that if I send a PDF file, it will be stored as a PDF file with the extension PDF...

Actual behavior

The init() converts the file to Data(contentsOf: url), saving a Data file with no extension. So retrieving the file through asset.filePath gets us the URL of a Data file, not a PDF...

So is there an iCloud requirement to convert the file to Data? If not, could we get a new create method (or have a preserveFormat parameter) to do something like:

self.uniqueFileName = "\(objectID)_\(propName).\(url.pathExtension)"
let destinationURL = CreamAsset.creamAssetDefaultURL().appendingPathComponent(uniqueFileName)
try FileManager.default.copyItem(at: url, to: destinationURL)

P.S. copyItem can throw, but the do/catch was omitted

After more digging, converting to Data doesn't seem to be an iCloud requirement...

There is one possible issue, the backward compatibility. How is the Parse (from iCloud) supposed to know if it should use copyItem or create a Data file from the URL... Maybe a parameter of the SyncEngine, SyncObject or add "isPreservedFormat" to the CKRecordConvertible protocol?

BTW, since people are supposed to use storedData() to access the data, you might want to get rid of the "data" field to avoid any confusion. Or at least make it private, and have storedData() return it, if not nil, while loading from the url as a fall back...

Thinking about it some more, backward compatibility of the Parse method isn't a problem. If the file was saved to iCloud as Data, then the copyItem will preserve it anyway.

The current method of saving to iCloud as Data, then parsing as Data(contentsOf: url) to do a data.write(to: url) is not very efficient... ;)

Hi @Fonceur , thanks for submitting this issue!
Actually as the Apple doc says,

CloudKit saves only the asset data; it does not save the filename or any other metadata associated with the initial file you provide.

So even if you save the data as with extension(e.g. mov), the retrieved file through asset.filePath will not contain the extension.

I apologize for approving the misleading comment "Any path extension on the file (e.g. "mov") will be maintained". It's not working as expected in the existing codebase.

Yeah, that's what I realized, so now I'm storing the extension in the CKRecord, to put it back on parsing... ;)

As I suggested in the #209, I don't recommend storing file extension in the CKRecord. It will add more complexity to the codebase and I don't see the necessity. You can store the file extension as a property in the upper object as you like.

Turn to #209 for more details