Open derwaldgeist opened 9 years ago
I now opened the URL that is returned by .url({ brokenIsFine: true }) in the browser. Here one can see an error message:
Error in method "/cfs/files/:value/:value/", Error: TypeError: Cannot read property 'images' of undefined
at Object.httpGetHandler (packages/cfs:access-point/access-point-handlers.js:61:1)
at Object.accessPoint.get (packages/cfs:access-point/access-point-server.js:175:1)
at packages/cfs:http-methods/http.methods.server.api.js:575:1
After inspecting the database collections, I found out that the file content was never saved to the GridFS collection, if it was uploaded as base64. There is only a file record in cfs.images.filerecord, but no record in cfs_gridfs.images.files. It is quite obvious that this way of uploading a file is broken.
EDIT: I've now also tested uploading a Blob. Same thing. There is a small difference in the database, though. For a blob, "original" contains an entry "updatedAt". For base64 data URLs, this updatedAt is missing, there is only "type" and "size".
Since there was no feedback so far, I switched over to Slingshot, although that package is not optimal for my use-case. But at least the upload worked there. Still hoping that CollectionFS/GridFS will support this scenario at some time.
You want to insert as base 64 string? I managed to do this as so:
Meteor.methods({
'uploadImage': function (base64EncodedImage) {
let future = new Future();
let onComplete = future.resolver();
let fsFile = new FS.File();
fsFile.attachData(base64EncodedImage, function(error) {
if (error) resolve(error, null);
QAImages.insert(fsFile, function (err, fileObj) {
onComplete(null, fileObj.url());
});
});
return future.wait();
});
My use case: I'm using the mdg:camera package to get an image from my mobile device. This image is returned as a standard base64-String, as it could be used directly in an image's src attribute.
For performance reasons, I would like to retrieve the image from GridFS using an HTTP URL instead. The upload is working fine, but if I'm retrieving the image and call .url() on the returned File object, the URL is null. I assumed the URL would be set automatically in the case of base64 strings. Obviously, this is not the case.
Is there a way to convert the base64 string into a valid File object and upload it as such instead?
I have tried
to get a "real" FS.File before uploading (instead of uploading the base64 string directly), and also set a name for it, but still on later retrieval the .url() is null.
In the database, I can see that for "real" file uploads (using an HTML upload form element), the file record contains a "copies" entry, but for the File that had been created based on the base64String it does not.
Another mystery: After reading some of the Github issues for CollectionFS, I found out that one can call .url with an additional parameter like this: .url({brokenIsFine: true}) to get a URL for the file before it has been stored on the server side. Strange thing is: Yes, this call returns a URL for my base64 strings; but this URL never becomes valid, even if I wait some time and reload the browser. So, this is a kind of broken forever URL. It is also unclear to me, why this .url() call should even differ, since I am only calling the .url() function after the callback from insert has been executed. This is because the callback will add the image to my model object and only this will trigger the re-rendering of my templates. So, the .url() should be available at this time. At least, if the insert callback is called after the upload was successful, as I expect.
Anyway, I'm still wondering how on earth I can get a URL for a file that has been uploaded to GridFS as a base64 encoded string, as this is the only thing I get from the mdg:camera API?!