CollectionFS: How to get URL for file that has been uploaded as a base64-String?


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 that 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

var newFile = new FS.File(theBase64String);'upload.jpg');
Images.insert(newFile, function(...) { ...

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.

EDIT: 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}). This parameter can be used to get a URL for a file before it has been stored on the server side. Strange thing is: 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.


I had to do a similar kind of thing in this thread over here

Basically you can use the following function b64toBlob to turn the Base64 data into a javascript Blob which you can then use with FileReader API to use as a File - see docs here

var b64ToBlob = function(b64Data, contentType, sliceSize) {
    var byteArray, byteArrays, byteCharacters, byteNumbers, i, offset, slice
    sliceSize = sliceSize || 512
    byteCharacters = atob(b64Data)
    byteArrays = []
    offset = 0
    while (offset < byteCharacters.length) {
        slice = byteCharacters.slice(offset, offset + sliceSize)
        byteNumbers = (function() {
            var j, ref, results
            results = []
            for (i = j = 0, ref = slice.length; 0 <= ref ? j < ref : j > ref; i = 0 <= ref ? ++j : --j) {
            return results
        byteArray = new Uint8Array(byteNumbers)
        offset += sliceSize
    return new Blob(byteArrays, { type: contentType })


@firegoby: Thanks for this info.

I also saw a solution on stackoverflow using Blobs, which is a bit shorter, since it is using the built-in window.atob() function. However, I wanted to avoid this “blobbing”, since this would limit me to IE 10+, according to the MDN developer APIs. I would have expected that CollectionFS handles this kind of conversion for me somehow :-/


I had a look at the FileReader API, but I could not find a way to convert a Blob into a File. Did I miss something? This approach would only help me if the result would be accepted by CollectionFS as a “real” file (i.e. as something that is also returned from an HTML file upload element).


I now tried this approach, but did not succeed. As expected, the FileReader is not accepted as a valid input for CollectionFS. I need a “real” File :-/


I just presumed that Blob and File would be somehow inter-operable as sources of binary data since the docs said “The File interface is based on Blob, inheriting blob functionality and expanding it to support files on the user’s system.” I didn’t actually go looking for the specific API to make it happen - sorry about that if it’s not the case :frowning:


No problem, thanks anyway for trying to help, highly appreciated. Well, I’m still stuck, as I can find no workaround. I filed an issue in the Github repository, hoping the DEV’s can help me with that. Unfortunately, the documentation of CollectionFS is quite sparse, so I am not really able to help myself. I even had a look at the source code, but did not really get what’s going on since everything is distributed among different modules and quite complex.