科尔多瓦文件上传

Cordova file upload

我想从我的 phone 设备存储中将视频上传到 YouTube。但是,当我上传文件时,它显示为空白。当我使用相同的上传代码但使用 web 文件时,它可以工作。想知道我哪里出错了!

方法一 一切都正确上传并且视频在 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();
};

方法二 视频标题和说明出现在 YouTube 上,但视频是空白的。我肯定传递的是有效文件。

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);
    });
}

两种方法共享相同的上传功能:

// 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();
};

我有一个示例项目,其中包含一些代码(减去上传脚本):

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

所以要上传我意识到的文件:

我现在用于上传文件并设置正确元数据的本地文件的代码:

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) + '%');
    };
}

而且我还必须修改插件以允许使用单个请求将元数据传递到 YouTube:

FileTransfer.java 第 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);

如果您确实修改了插件,请记住 cordova 缓存了这段代码。我使用这个命令强制它更新插件:

cordova platform remove android; cordova platform add android;

官方文件传输插件是 deprecated and when I'm writing this, its test script fails

这让我使用了一种纯粹的 javascript 方法并且它确实有效

function uploadFile (localPath, fileName, remoteUrl, callback) {
  // loads local file with http GET request
  var xhrLocal = new XMLHttpRequest()
  xhrLocal.open('get', localPath)
  xhrLocal.responseType = 'blob'
  xhrLocal.onerror = () => {
    callback(Error('An error ocurred getting localpath on' + localPath))
  }
  xhrLocal.onload = () => {
    // when data is loaded creates a file reader to read data
    var fr = new FileReader()
    fr.onload = function (e) {
      // fetch the data and accept the blob
      console.log(e)
      fetch(e.target.result)
        .then(res => res.blob())
        .then((res) => {
          // now creates another http post request to upload the file
          var formData = new FormData()
          formData.append('imagefile', res, fileName)
          // post form data
          const xhrRemote = new XMLHttpRequest()
          xhrRemote.responseType = 'json'
          // log response
          xhrRemote.onerror = () => {
            callback(Error('An error ocurred uploading the file to ' + remoteUrl))
          }
          xhrRemote.onload = () => {
            if (typeof callback === 'function') {
              callback(null, 'File uploaded successful, ' + xhrRemote.response)
            }
          }

          // create and send the reqeust
          xhrRemote.open('POST', remoteUrl)
          xhrRemote.send(formData)
        })
    }
    fr.readAsDataURL(xhrLocal.response) // async call
  }
  xhrLocal.send()
}

现在就这样称呼它

uploadFile('file:///storage/emulated/0/Android/data/myfile.jpg',
  'myfile.jpg',
  'https://example.com/upload_url',
  (err, res) => {
    if (err) {
      console.error(err)
    } else {
      console.log(res)
    }
  })

这是另一个可行的解决方案。我现在进行了测试,它确实有效。你需要标准 cordova-plugin-file

function uploadFileToServer (fileUri, fileName, remoteUrl, callback) {
  window.resolveLocalFileSystemURL(fileUri, function (fileEntry) {
    fileEntry.file(function (file) {
      var reader = new FileReader()
      reader.onloadend = function () {
        var blob = new Blob([new Uint8Array(this.result)], { type: 'application/octet-stream' })
        var fd = new FormData()

        fd.append('file', blob, fileName)

        var xhr = new XMLHttpRequest()
        xhr.open('POST', remoteUrl, true)
        xhr.onload = function () {
          if (xhr.status === 200) {
            if (typeof callback === 'function') { callback() }
          } else {
            if (typeof callback === 'function') { callback(xhr.status) }
          }
        }
        xhr.onerror = function (err) {
          if (typeof callback === 'function') { callback(err) }
        }
        xhr.send(fd)
      }
      reader.readAsArrayBuffer(file)
    }, function (err) {
      if (typeof callback === 'function') { callback(err) }
    })
  })
}

你称之为:

uploadFileToServer('file:///storage/emulated/0/Android/data/myfile.jpg',
  'myfile.jpg',
  'https://example.com/upload_url',
  (err) => {
    if (err) {
      console.error('Error uploading file', err)
    } else {
      console.log('Upload done it with success')
    }
  })