前端如何上传图片至七牛云

上传文件是我们在前端开发中经常遇到的一个问题。最近在做某项目管理后台的时候,需要将轮播图上传至七牛云。以前在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

最终效果如下图所示:


上传图片至七牛
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 206,214评论 6 481
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 88,307评论 2 382
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 152,543评论 0 341
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 55,221评论 1 279
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 64,224评论 5 371
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 49,007评论 1 284
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,313评论 3 399
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,956评论 0 259
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 43,441评论 1 300
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,925评论 2 323
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 38,018评论 1 333
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,685评论 4 322
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,234评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,240评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,464评论 1 261
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 45,467评论 2 352
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,762评论 2 345

推荐阅读更多精彩内容