File uploads via Cordova

Has anyone got any experience uploading files from the cordova camera / video?

Uploading via a input form works fine, but when trying to use the Filereader API I can only get it to work by converting it into a Base64 string. Which causes memory issues on larger files.

window.resolveLocalFileSystemURL( video[0].localURL ,
           function( fileEntry){
                fileEntry.file(
                    function(data){
                        var blob = b64toBlobAlt(data, 'video/mp4')
                        $this.uploadFile( blob );
                    }
                )
            },
            function(error){
                console.error(error)
            }
 );


function b64toBlobAlt(dataURI, contentType) {
     var byteString = atob(dataURI.split(',')[1]);
     var ab = new ArrayBuffer(byteString.length);
     var ia = new Uint8Array(ab);

     for (var i = 0; i < byteString.length; i++) {
           ia[i] = byteString.charCodeAt(i);
     }
     return new Blob([ab], { type: contentType });
}

I would really like any advice as I am stuck when trying to upload large files.
Much appreciated

2 Likes

Have you looked into the CollectionFS package?

It has different “Storage Adapters” that you can try. With GridFS, for example, file data is stored in chunks in your MongoDB database. There is an adapter for amazon S3 as well. Not sure if this helps you specifically, but I hope it does!

Yeah, I don’t want to store the data in grid fs and converting HD videos on
aws is expensive. So really looking to utilize YouTube

Finally got it working. I used the cordova file transfer plugin:

    function postVideo(accessToken, fileURI) {
    var metadata = {
        snippet: {
            title: "test",
            description: "test",
            tags: ["youtube-cors-upload"],
            categoryId: 21
        },
        status: {
            privacyStatus: "unlisted"
        }
    }

    var options = new FileUploadOptions();
    options.fileKey = "file";
    options.fileName = 'test';
    options.mimeType = "video/mp4";
    options.chunkedMode = false;

    options.headers = {
        Authorization: "Bearer "+ accessToken,
        "Access-Control-Allow-Origin": "http://meteor.local"
    };

    var params = new Object();
    params.part = Object.keys(metadata).join(',')

    options.params = params;
    console.log(options)
    var ft = new FileTransfer();
    ft.upload(fileURI, "https://www.googleapis.com/upload/youtube/v3/videos?part=snippet", win, fail, options, true);

    ft.onprogress = function(progressEvent) {
        if (progressEvent.lengthComputable) {
            // console.log(progressEvent)
          // loadingStatus.setPercentage(progressEvent.loaded / progressEvent.total);
        } else {
            console.log('something not loading')
          // loadingStatus.increment();
        }
        console.log(progressEvent.loaded / progressEvent.total);
    };
}

function win(r) {
    console.log(r)
    console.log("Code = " + r.responseCode);
    console.log("Response = " + r.response);
    console.log("Sent = " + r.bytesSent);
}

function fail(error) {
    console.log(error)
    // alert("An error has occurred: Code = " + error.code);
    console.log("upload error source " + error.source);
    console.log("upload error target " + error.target);
}
3 Likes

Hello, have you already tried to upload audio files to FScollection from cordova? I can’t make it work, I’m using on the same way than in web platform. Any advice?

Thanks!

Hi @michaelbell, good job. I am looking for the same thing :wink:
How do made the access to Camera folder and the files their ?
I get also just a exceptions using the apache.file plugin.

Would be great if could that know how.

Hi @michaelbell ,

Thanks for this. It helped a lot.

I am also trying to set the privacyStatus as unlisted. However, it seems there is something small missing in this example because of which the meta data of the video is not actually set.

I am trying to find out how to set the multi part post meta data for the video meta data. Would appreciate any help if anyone knows how to do that.

After much investigation, YouTube insert API call does not seem to support metadata update in same call as insert (see supported mime type on API page, it does not include multipart request). You need to follow the insert http call with a update request.

The Google API client libraries seem to internally do two calls , one to insert and one to update meta data). It gives impression that it was single request at API level but internally it looks like two HTTP calls.

I am quite disappointed with documentation of Google YouTube APIs. They seem to be beginner unfriendly.

Just as a side note, since I needed selective sharing of the videos, I shifted to uploading the videos to google drive which has support for doing that at API level. Google drive supports embedding videos using frame just like YouTube and fit my use case better.