11月19, 2017

使用NodeJs上传文件到七牛云

七牛云是国内比较出色的云存储提供商,同时提供10G免费空间、10G免费流量。国内不少网站都选择七牛来存储网站图片等静态资源,不少博客框架也默认提供七牛的存储配置,包括本博客使用的火麒麟,还有诸如Ghost博客也是默认提供七牛存储配置的。

七牛的文档提供的比较完善,但还是有一些坑,总会一些没有提及到的点,本人使用的时候就遇到几个坑,大家在使用过程中可以注意一下!

先说一下基本用法吧。这里是前端页面直接上传,所以主要用到了七牛的JS SDK 和 NodeJs sdk。

1、前端引入

<script src="./vendor/plupload.full.min.js"></script>
<script src="./vendor/qiniu.min.js"></script>
<script src="https://cdn.bootcss.com/moment.js/2.19.2/moment.min.js"></script>

其中moment.js为非必要的,我这里是为了后面重命名文件名使用的。

2、前端表现

<div id="wrap">
    <button id="upload">上传</button>
</div>

3、初始化上传

let uploader = window.Qiniu.uploader({
        disable_statistics_report: true,
        runtimes: 'html5, html4',                     // 上传模式,依次退化
        browse_button: 'upload',             // 上传选择的点选按钮,必需
        uptoken_url: '/upload/token',         // Ajax请求uptoken的Url,强烈建议设置(服务端提供)
        get_new_uptoken: false,             // 设置上传文件的时候是否每次都重新获取新的uptoken
        unique_names: false,
        save_key: false,                  // 默认false。若在服务端生成uptoken的上传策略中指定了sava_key,则开启,SDK在前端将不对key进行任何处理
        domain: 'https://image.luodao.me/',  // bucket域名,下载资源时用到,必需
        container: 'wrap',                     // 上传区域DOM ID,默认是browser_button的父元素
        max_file_size: '20mb',             // 最大文件体积限制
        max_retries: 3,                     // 上传失败最大重试次数
        dragdrop: true,                     // 开启可拖曳上传
        drop_element: 'wrap',                  // 拖曳上传区域元素的ID,拖曳文件或文件夹后可触发上传
        chunk_size: '4mb',                  // 分块上传时,每块的体积
        auto_start: true,                   // 选择文件后自动上传,若关闭需要自己绑定事件触发上传
        init: {
            'FilesAdded': function(up, files) {

            },
            'BeforeUpload': function(up, file) {
                // 每个文件上传前,处理相关的事情
            },
            'UploadProgress': function(up, file) {
                // 每个文件上传时,处理相关的事情
            },
            'FileUploaded': function(up, file, info) {
                var domain = up.getOption('domain');
                var res = JSON.parse(info.response);
                var sourceLink = domain + res.key;
                console.log(sourceLink);
            },
            'Error': function(up, err, errTip) {
                //上传出错时,处理相关的事情
            },
            'UploadComplete': function() {
                //队列文件处理完毕后,处理相关的事情
            },
            'Key': function(up, file){
                let ext = file.name.split('.')[1];
                let date = moment(new Date()).format('YYYY-MM-DD');
                return self.fileType + '/' + date + "/"+ file.id + '.' + ext;
            }
        }
    });

参数都比较好理解,文档中都有提到。

这里使用ajax请求uptoken,使用这种方法可以每次都从固定的一个位置请求uptoken的值,但是使用这个方法会在控制台输出一个同步ajax的警告,因为同步ajax已经不提倡使用了,控制台洁癖者可以选择使用其他两种方法来获取uptoken,文档有说明,不再赘述。

4、NodeJs端uptoken生成

这里需要七牛nodejs sdk。

npm install qiniu --save

生成token,这里使用thinkjs的请求方式,如使用如express等框架,略做修改即可。

import Base from'./base.js';
import qiniu from 'qiniu';

//自行换成自己的accessKey和secretKey
const accessKey = 'xxxxxx';
const secretKey = 'xxxxxx';
const mac = new qiniu.auth.digest.Mac(accessKey, secretKey);

export default class extends Base {

    indexAction() {

    }

    tokenAction(){
        const putPolicy = new qiniu.rs.PutPolicy({
            scope: 'image'//自行选择自己对应的bucket
        });
        const uploadToken = putPolicy.uploadToken(mac);

        this.json({
            uptoken: uploadToken
        });
    }
}

5、遇到的坑

使用过程中还是遇到几个坑的,这里说明一下。

5.1、js sdk版本问题

七牛sdk基于plupload开发,但它的的版本更新速度完全更不上pluplaod的更新速度,所以会出现版本不匹配导致的错误,如可能遇到的b.setOption is not a function这样的错误。

官方文档里面推荐开发者使用它们的cdn,但没有告诉开发者该选择哪个版本的sdk,所以我理所当然的选择选择了两个js文件的最新版本,结果就悲剧了。然后调试源码,谷歌。后面发现根本是两个文件版本不对的原因。

解决办法:使用bower安装方式,这样可以同时下载七牛js sdkplupload,并且他们版本是匹配的,毕竟官方校对过了。

5、2 save_key问题

细心的朋友可以发现,上面我是在前端生成save_key的。官方文档上说,可以再后端控制save_key的生成,只需要后端配合生成save_key

this.json({
     uptoken: uploadToken,
     save_key :save_key
});

然后前端同时配置:

unique_names: false,
save_key: true,

然而发现并没有用...,至于原因,也懒得去追究了,最后还是使用了前端生成key的方式。

最后注意Key这个函数名是大写的,我看成小写的,结果大半天不起效,找了半天原因,完全是浪费时间啊。

'Key': function(up, file){
        let ext = file.name.split('.')[1];
        let date = moment(new Date()).format('YYYY-MM-DD');
        return self.fileType + '/' + date + "/"+ file.id + '.' + ext;
}

本文链接:https://luodao.me/post/upload-file-to-qiniu.html

-- EOF --

Comments

评论加载中...

注:如果长时间无法加载,请针对 disq.us | disquscdn.com | disqus.com 启用代理。