赞
踩
经过两周时间的折腾,终于实现了在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的使用,大家可以参考官网!
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。