当前位置:   article > 正文

Ionic中采用cordova-transfer上传图片到腾讯云对象存储(COS)_error_cgi_param_no_such_op

error_cgi_param_no_such_op

经过两周时间的折腾,终于实现了在Ionic中将图片上传到腾讯云COS中。这里记录一下自己踩过的坑。
在腾讯云COS提供的SDK包中,只有JavaScript-SDK包,该包的实现是采用Jquery实现的。而在我们Ionic开发中是采用Angular实现的,所以不太想引入Jquery的相关内容。所以想参考他的JavaScript-SDK的源码自己实现图片上传功能。
在JavaScript-SDK中文件的上传代码如下:

 CosCloud.prototype.uploadFile = function (success, error, onprogress, bucketName, remotePath, file, insertOnly, taskReady) {

        var that = this;
        if (file.size > MAX_UNSLICE_FILE_SIZE) {
            that.sliceUploadFile(success, error, onprogress, bucketName, remotePath, file, insertOnly, undefined, undefined, taskReady);
            return;
        }

        if (remotePath.substr(remotePath.length - 1) === '/') {
            error({code: -1, message: 'path not allow end with "/"'});
            return;
        }
        remotePath = fixPath(remotePath);

        // 辅助 cancelTask
        var taskId = guid();
        var $xhr;
        var globalTask = {
            id: taskId,
            state: 'uploading',
            cancel: function () {
                $xhr && $xhr.abort();
            }
        };
        this.tasks[taskId] = globalTask;
        taskReady && typeof taskReady === 'function' && taskReady(taskId);

        that.getAppSign(function (sign) {
            var url = that.getCgiUrl(remotePath, sign);
            var formData = new FormData();
            insertOnly = insertOnly === 0 ? 0 : 1;
            formData.append('op', 'upload');
            formData.append('fileContent', file);
            formData.append('insertOnly', insertOnly);
            $xhr = $.ajax({
                type: 'POST',
                url: url,
                data: formData,
                processData: false,
                contentType: false,
                xhr: function () {

                    var xhr = $.ajaxSettings.xhr();
                    xhr.upload.onprogress = function (evt) {
                        var percent = evt.loaded / evt.total;
                        if (typeof onprogress === 'function') {
                            onprogress(percent, 0);
                        }
                    };

                    return xhr;

                },
                success: function () {
                    if (globalTask.state === 'cancel') return;
                    success.apply(this, arguments);
                },
                error: function () {
                    if (globalTask.state === 'cancel') return;
                    success.apply(this, arguments);
                }
            });
        });
    };
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58
  • 59
  • 60
  • 61
  • 62
  • 63
  • 64
实现的总体思路是如果大文件的上传就分段上传,如果文件比较小就直接上传。由于我上传的是图片,所以只需要实现单文件上传即可。
  • 1

初步采用cordova-transfer实现的代码如下:

  public uploadImg(path: string):string {
    if(!path) {
      return;
    }
    //根据时间获取当前文件名称
    let fileName=this.globalData.userId+"_"+Date.now();
    let options = {
      fileKey: 'fileContent',
      fileName:fileName,
      params: {'op':'upload','insertOnly':0}
    };
    let uploadUrl=this.getUrl(fileName);
    this.fileTransfer.upload(path, uploadUrl, options)
      .then((data) => {
        return fileName;
      }, (err) => {
        this.nativeService.showToast("上传文件失败!");
        this.nativeService.showToast(err);
        this.logger.log(err);
      });
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21

发现一直报这样的错误:

{"code":-5964,"message":"ERROR_CGI_PARAM_NO_SUCH_OP","request_id":""}
  • 1

一开始怀疑是上传的url不正确,通过与官网demo上传文件后的报文对比后发现没有对Base64的签名结果进行转义。所以对getUrl方法进行修改。结果为:

public getUrl(fileName:string):string{
    return  this.uploadUrl+fileName+'?sign='+encodeURIComponent(this.sign);
}
  • 1
  • 2
  • 3

发现问题依然存在,所以开始怀疑是不是传输文件流的格式存在问题,所以就详细的查看了cordova-transfer的官网说明,发现transfer默认情况下chunkedMode的值为true,即以chunked streaming 的模式上传数据,而这个模式COS是不支持的。所以添加chunkedMode参数,并将chunkedMode设置为false。问题得到了解决。最终的代码如下:

  public uploadImg(path: string):string {
    if(!path) {
      return;
    }
    //根据时间获取当前文件名称
    let fileName=this.globalData.userId+"_"+Date.now();
    //let options: any;
    let options = {
      fileKey: 'fileContent',
      fileName:fileName,
      params: {'op':'upload','insertOnly':0},
      chunkedMode:false
    };
    let uploadUrl=this.getUrl(fileName);
    this.fileTransfer.upload(path, uploadUrl, options,true)
      .then((data) => {
        return fileName;
      }, (err) => {
        this.nativeService.showToast("上传文件失败!");
        this.nativeService.showToast(err);
        this.logger.log(err);
      });
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23

关于腾讯云COS的使用,大家可以参考官网!

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/小蓝xlanll/article/detail/311950
推荐阅读
相关标签
  

闽ICP备14008679号