javascriptfilecordovavideophonegap-plugins

Cordova file upload


I want to upload a video to YouTube from my phone device storage. However when I upload the file it comes through as blank. When I use the same upload code but with a web file, it works. Wondering where I am going wrong!

Method one everything uploads correctly and the video plays on YouTube.

loadWebFile('assets/intro.mpg');

function loadWebFile(url) {
    var xhr = new XMLHttpRequest();
    xhr.open('GET', url);
    xhr.responseType = 'blob';
    xhr.onload = function (e) {
        uploadFile(xhr.response); // type: Blob
    };
    xhr.onerror = function (e) {
        console.log('loadWebFile.onerror', e);
    };
    xhr.send();
};

Method two The video title and description appears on YouTube, but the video is blank. I'm definitely passing through a valid file.

window.requestFileSystem = window.requestFileSystem || window.webkitRequestFileSystem;
if (window.webkitStorageInfo) {
    window.webkitStorageInfo.requestQuota(access, 1024 * 1024, function (bytes) {
        if (window.requestFileSystem) {
            window.requestFileSystem(access, bytes, function (filesystem) {
                loadFile('/Movies/intro.mpg');
            }, me.onError);
        } else {
            window.alert('requestFileSystem not supported');
        }
    }, me.onError);
} else {
    window.alert('webkitStorageInfo not supported');
}

// this sends an empty video to YouTube
function loadFile(path) {
    filesystem.root.getFile(path, null, function (fileEntry) {
        fileEntry.file(function (file) {
            uploadFile(file); // type: File
        });
    }, function (e) {
        console.log('loadFile.error', e);
    });
}

Both methods share the same upload function:

// uploads using the YouTube script
// https://github.com/youtube/api-samples/blob/master/javascript/cors_upload.js
function uploadFile(file) {
    var metadata = {
        snippet: {
            title: 'Video title',
            description: 'Video description',
            tags: 'Video tags',
            categoryId: 22
        },
        status: {
            privacyStatus: 'unlisted'
        }
    };
    var uploader = new MediaUploader({
        baseUrl: 'https://www.googleapis.com/upload/youtube/v3/videos',
        file: file,
        token: accessToken,
        metadata: metadata,
        params: {
            part: Object.keys(metadata).join(',')
        },
        onError: function (e) {
            console.log('onError', JSON.parse(e));
        },
        onProgress: function (e) {
            console.log('onProgress', e);
        },
        onComplete: function (e) {
            console.log('onComplete', JSON.parse(e));
        }
    });
    uploader.upload();
};

I've have an example project with some of the code (minus the upload script) here:

https://github.com/kmturley/cordova-files


Solution

  • So to upload files I realised for:

    The code i'm now using for local files which uploads the file and sets correct metadata:

    function uploadVideo(fileURL) {
        var options = new FileUploadOptions();
        options.fileKey = 'file';
        options.fileName = fileURL.substr(fileURL.lastIndexOf('/') + 1);
        options.mimeType = 'video/mpg';
        options.chunkedMode = false;
        options.headers = {
            Authorization: 'Bearer ' + accessToken
        };
        options.params = {
            "": {
                snippet: {
                    title: 'Video title',
                    description: 'Video description',
                    tags: 'Video tags',
                    categoryId: 22
                },
                status: {
                    privacyStatus: 'unlisted'
                }
            }
        };
        var ft = new FileTransfer();
        ft.upload(fileURL, 'https://www.googleapis.com/upload/youtube/v3/videos?part=snippet,status', function (data) {
            console.log('upload success', data);
        }, function (e) {
            console.log('upload error', e);
        }, options, true);
        ft.onprogress = function (progressEvent) {
            console.log('onprogress: ' + ((progressEvent.loaded / progressEvent.total) * 100) + '%');
        };
    }
    

    And I also had to modify the plugin to allow the metadata to be passed through to YouTube using a single request:

    FileTransfer.java lines 374 - 376

    beforeData.append("Content-Disposition: form-data; name=\"").append(key.toString()).append("\";");
    beforeData.append(" filename=\"").append("file.json").append('"').append(LINE_END);
    beforeData.append("Content-Type: ").append("application/json").append(LINE_END).append(LINE_END);
    

    If you do modify the plugin, remember cordova caches this code. I use this command to force it to update the plugin:

    cordova platform remove android; cordova platform add android;