上传文件是我们在前端开发中经常遇到的一个问题。最近在做某项目管理后台的时候,需要将轮播图上传至七牛云。以前在Vue里面做过类似的功能,但是在Angular中使用同样的方法发现行不通。
此篇文章主要介绍在Angular组件中如何上传图片至七牛云。在其他前端框架(比如React、Vue等)中步骤3同样适用,只是步骤1和步骤2有所区别。下面具体介绍在Angular组件中上传图片至七牛云的步骤。
步骤1:引入依赖的js文件
引入方式1:在index.html中引入
在index.html中引入七牛js-sdk文件中的压缩文件,这里我们引入qiniu.min.js。
【注意】在引入qiniu.min.js之前,我们需要引入plupload上传组件。
Plupload是一款由著名的web编辑器TinyMCE团队开发的上传组件,简单易用且功能强大。
Plupload有以下功能和特点:
- 拥有多种上传方式:HTML5、flash、silverlight以及传统的<input type=”file” />。Plupload会自动侦测当前的环境,选择最合适的上传方式,并且会优先使用HTML5的方式。所以你完全不用去操心当前的浏览器支持哪些上传方式,Plupload会自动为你选择最合适的方式。
- 支持以拖拽的方式来选取要上传的文件
- 支持在前端压缩图片,即在图片文件还未上传之前就对它进行压缩
- 可以直接读取原生的文件数据,这样的好处就是例如可以在图片文件还未上传之前就能把它显示在页面上预览
- 支持把大文件切割成小片进行上传,因为有些浏览器对很大的文件比如几G的一些文件无法上传。
这里我们引入plupload.full.min.js和plupload的zh_CN.js文件。
在index中引入qiniu和plupload的js代码如下图所示:
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8">
<title>test</title>
<meta name="viewport" content="width=device-width, initial-scale=1">
<link rel="icon" type="image/x-icon" href="favicon.ico">
</head>
<body>
<app-root></app-root>
<!--上传图片 七牛JS-SDK-->
<script src="//cdn.staticfile.org/plupload/2.1.9/plupload.full.min.js"></script>
<script src="//cdn.bootcss.com/plupload/2.1.9/i18n/zh_CN.js"></script>
<script src="//cdn.staticfile.org/qiniu-js-sdk/1.0.14-beta/qiniu.min.js"></script>
</body>
</html>
以上引入js文件的方式我们这里均采用CDN的方式引入,也可以将这些文件下载到本地,然后用引入文件的方式引入。
引入方式2:通过配置angular.json的方式引入
我们也可以先在工程的src目录下建立一个文件夹lib,然后将plupload.full.min.js和qiniu.min.js下载至本地放到该目录下。如下图所示:
然后通过在angualr.json中进行相应的配置,即可引入需要依赖的js文件。代码如下图所示:
"scripts": [
"./src/lib/plupload.full.min.js",
"./src/lib/qiniu.min.js"
]
步骤2:在组件中声明需要依赖的js文件
做这个功能的时候一直卡在了这一步,找了半天原因是因为没有在angular组件中进行声明。因此要想使用依赖的js文件,首先得在组件中进行声明,代码如下图所示:
declare var Qiniu: any;
declare var plupload: any;
步骤3:初始化 uploader
通过阅读 七牛JavaScript SDK文档,需要做如下初始化:
// 上传添加时的轮播图
uploadBanner(): void {
const _this = this;
_this.uploadProgress = 0;
_this.bannerUrl = '';
const optionImg = {
runtimes: 'html5,flash,html4', // 上传模式,依次退化
browse_button: 'uploadbanner', // 上传选择的点选按钮,必需
// 在初始化时,uptoken,uptoken_url,uptoken_func三个参数中必须有一个被设置
// 切如果提供了多个,其优先级为uptoken > uptoken_url > uptoken_func
// 其中uptoken是直接提供上传凭证,uptoken_url是提供了获取上传凭证的地址,如果需要定制获取uptoken的过程则可以设置uptoken_func
// uptoken : '', // uptoken是上传凭证,由其他程序生成
// uptoken_url: '//cloud-api.changhong.io', // Ajax请求uptoken的Url,强烈建议设置(服务端提供)
uptoken_func: function(file) { // 在需要获取uptoken时,该方法会被调用
// _this.uploadProgress = 0;
return _this.uptoken;
},
get_new_uptoken: true, // 设置上传文件的时候是否每次都重新获取新的uptoken
// downtoken_url: '/downtoken',
// Ajax请求downToken的Url,私有空间时使用,JS-SDK将向该地址POST文件的key和domain,服务端返回的JSON必须包含url字段,url值为该文件的下载地址
// unique_names: true, // 默认false,key为文件名。若开启该选项,JS-SDK会为每个文件自动生成key(文件名)
// save_key: true, // 默认false。若在服务端生成uptoken的上传策略中指定了sava_key,则开启,SDK在前端将不对key进行任何处理
domain: 'http://pqe96fvpl.bkt.clouddn.com', // bucket域名,下载资源时用到,必需
//container: 'container', // 上传区域DOM ID,默认是browser_button的父元素
max_file_size: '100mb', // 最大文件体积限制
flash_swf_url: 'https://cdn.bootcss.com/plupload/2.1.9/Moxie.swf', // 引入flash,相对路径
max_retries: 3, // 上传失败最大重试次数
//dragdrop: true, // 开启可拖曳上传
//drop_element: 'container', // 拖曳上传区域元素的ID,拖曳文件或文件夹后可触发上传
chunk_size: '4mb', // 分块上传时,每块的体积
auto_start: true, // 选择文件后自动上传,若关闭需要自己绑定事件触发上传
init: {
'FilesAdded': function(up, files) {
plupload.each(files, function(file) {
if (file.type === 'image/jpg' || file.type === 'image/jpeg' || file.type === 'image/png') {
_this.uploadProgress = 0;
} else {
_this.nzMessageService.success('仅支持类型为.jpg,.png的文件');
up.removeFile(file);
return false;
}});
},
'BeforeUpload': function(up, file) {
// 每个文件上传前,处理相关的事情
},
'UploadProgress': function(up, file) {
// 每个文件上传时,处理相关的事情
_this.uploadProgress = file.percent;
},
'FileUploaded': function (up, file, info) {
// 每个文件上传成功后,处理相关的事情
// 其中info是文件上传成功后,服务端返回的json,形式如:
// {
// "hash": "Fh8xVqod2MQ1mocfI4S4KpRL6D98",
// "key": "gogopher.jpg"
// }
// 查看简单反馈
const domain = up.getOption('domain');
const res = JSON.parse(info.response);
const sourceLink = domain + '/' + res.key; // 获取上传成功后的文件的Url
_this.bannerUrl = sourceLink;
},
'Error': function (up, err, errTip) {
// 上传出错时,处理相关的事情
// swal('', errTip, 'error');
},
'Key': function (up, file) {
// 若想在前端对每个文件的key进行个性化处理,可以配置该函数
// 该配置必须要在unique_names: false,save_key: false时才生效
const key = 'portal/banners/' + file.name;
// do something with key here
return key;
}
// 'UploadComplete': function() {
// 队列文件处理完毕后,处理相关的事情
// },
// 'Key': function(up, file) {
// 若想在前端对每个文件的key进行个性化处理,可以配置该函数
//该配置必须要在unique_names: false,save_key: false时才生效
//
//var key = "";
//do something with key here
//return key
// }
}
};
this.uploaderAdd = Qiniu.uploader(optionImg);
}
browse_button属性的值需要在模板文件中,添加对应的id选择器的节点,比如当设置browse_button的值为'uploadbanner'的时候,则模板文件中需添加如下的按钮:
<button nz-button id="uploadeditbanner"><i nz-icon nzType="upload"></i><span>上传</span></button>
如何获取upToken?
根据七牛官方文档:JS-SDK 依赖服务端颁发 token,为了安全,token 建议通过网络从服务端获取。后端服务应提供一个 URL 地址,供 SDK 初始化使用,前端通过 Ajax 请求该地址后获得 upToken。
前端有以下3种方式获取upToken:
uptoken : '', // uptoken是上传凭证,由其他程序生成
uptoken_url: '', // Ajax请求uptoken的Url,强烈建议设置(服务端提供)
uptoken_func: function(file) { }, //在需要获取uptoken时,该方法会被调用
这3种方式具体用哪种需根据后端服务提供哪种获取upToken的方式决定。
如何获取domain地址?
domain地址需要从后端编写接口的人告知。
如何限制上传的文件类型?
如果我们需要限制文件的类型,比如我们只允许上传.jpg、.jpeg、.png格式的文件,则需要在FilesAdded函数中添加如下代码:
plupload.each(files, function(file) {
if (file.type === 'image/jpg' || file.type === 'image/jpeg' || file.type === 'image/png') {
_this.uploadProgress = 0;
} else {
_this.nzMessageService.success('仅支持类型为.jpg、.jpeg、.png的文件');
up.removeFile(file);
return false;
}
});
如何显示上传进度条?
如果需要显示上传的进度条,则在UploadProgress函数中添加相应代码。
_this.uploadProgress = file.percent;
通过file参数的percent属性获取到上传进度的百分比,然后赋值给需要在前端页面上进行显示的变量。
如何获取上传完成后返回的文件的url地址?
上传完成后,要获取上传的图片的url地址,则需要在FileUploaded函数中,添加如下代码:
const domain = up.getOption('domain');
const res = JSON.parse(info.response);
const sourceLink = domain + '/' + res.key; // 获取上传成功后的文件的Url
最终效果如下图所示: