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

经过两周时间的折腾,终于实现了在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);
                }
            });
        });
    };
实现的总体思路是如果大文件的上传就分段上传,如果文件比较小就直接上传。由于我上传的是图片,所以只需要实现单文件上传即可。

初步采用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);
      });
}

发现一直报这样的错误:

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

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

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

发现问题依然存在,所以开始怀疑是不是传输文件流的格式存在问题,所以就详细的查看了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);
      });
}

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

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值