代码之家  ›  专栏  ›  技术社区  ›  Kim T

Cordova文件上传

  •  0
  • Kim T  · 技术社区  · 11 年前

    我想从我的手机设备存储中将视频上传到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

    3 回复  |  直到 11 年前
        1
  •  2
  •   João Pimentel Ferreira    5 年前

    这里是另一个可行的解决方案。我现在就测试了,它确实有效。你需要标准 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')
        }
      })
    
        2
  •  1
  •   João Pimentel Ferreira    6 年前

    官方文件传输插件是 deprecated 当我写这个的时候 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)
        }
      })
    
        3
  •  0
  •   Kim T    11 年前

    因此,为了上传文件,我意识到:

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

    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:

    文件传输.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;