默认情况下,如果以指定key或者saveKey的方式上传一个和已经存在于空间中的文件名字相同而且内容相同的文件的时候,七牛服务器会根据新上传的文件内容的hash推断出该文件已经存在,不会覆写已有的文件。
如果上传的文件被指定的名字和空间中已有文件的名字相同,但是内容不同时,会返回如下错误信息 {“error”:“file exists”}。
问:如果真的有这种文件内容不同,但是需要指定相同名字的覆盖上传需求怎么办呢?
答:很简单,设置PutPolicy里面的scope和insertOnly参数,并且在POST请求里面指定需要覆盖的文件的key。在覆盖上传里面,scope的值需要设置为bucket:key这样的方式,这个key和POST请求里面的key值相同,另外必须保证insertOnly为0,这样,文件就可以覆盖上传了。
覆盖上传文件的步骤:
1. 按照bucket:key的方式设置PutPolicy里面的scope参数,另外设置insertOnly参数为0。
2. 构建包含指定要覆盖的文件的key,文件内容和上传token的表单
3. 向七牛云存储服务器提交HTTP POST请求
4. 解析七牛云存储服务器返回的回复。
文件上传之后,七牛云存储对文件的命名遵循以下的规则:
1. 文件上传的POST请求中,如果指定了参数key,那么以key来命名文件。
2. 文件上传的POST请求中,没有指定参数key,但是上传策略PutPolicy里面指定了saveKey参数,那么以saveKey命名文件。
3. 文件上传的POST请求中,如果没有指定参数key,而且在上传策略PutPolicy里面也没有指定saveKey参数,那么七牛云存储服务器会使用根据文件内容计算得来的hash值作为文件的名字。
备注:
上面的命名方式是按顺序检测的,一旦确认了文件的名字,就不会再检测后面的规则。比如同时指定了表单参数key和上传策略参saveKey,那么也是以key来命名上传的文件。
七牛云存储服务器会对每个上传的文件都会计算它的hash值,所以上传的文件一定是有名字的。
使用 Formdata 方式上传,表单的参数 key 指定文件要保存的名字(文件key)。
在使用覆盖上传的时候,必须指定参数 key。
文件上传后的命名将遵循以下规则:
- 源Bucket和目标Bucket必须在同一区域,即处理结果不能跨区域另存。
- 客户端已指定
Key
,以Key
命名。 - 客户端未指定
Key
,上传策略中设置了saveKey
,以saveKey
的格式命名。 - 客户端未指定
Key
,上传策略中未设置saveKey
,以文件hash(etag)
命名。
vue中使用七牛上传,我做了一个例子(vue init webpack构建,实现了断点续传、暂停上传、继续上传),github地址:https://github.com/cag2050/qiniu_demo
七牛使用 Formdata 方式上传,缺点:
1. IE 8/9 不支持。
2. 无法使用分片上传功能(分片上传功能实现了断点续传、暂停和继续)。
不考虑兼容性的情况下,如手机端,可以使用 Formdata 结合七牛表单上传的方式上传文件。
断点续传的含义:配置项 chunk_size 值为0时表示不使用分片上传功能(分片上传功能实现了断点续传)
分片上传 =====
分片上传是将一个文件分为多个尺寸相同的小数据块,每个小数据块以一个独立的 HTTP 请求分别上传。所有小数据块都上传完成后,再发送一个请求给服务端将这些小数据块组织成一个逻辑资源,以完成上传过程。
缺点:相比表单上传,分片上传需要多次 HTTP 请求才能完成上传过程,会有额外的成本开销。另外也增加了代码的复杂度,因此选择是否使用分片上传时应谨慎评估使用的必要性。(个人见解:此处可以判断文件大小,如果很大,才用分片上传)
断点续传 =====
虽然片的存在周期并非永久,但已足以实现断点续传机制。
每成功上传一个片,客户端都会收到服务端返回一个代表当前已上传多少片的进度信息,我们称之为Context
。上传下一个片时应提供前一个片上传成功后返回的Context
。因此,这个Context
可以认为是片传输进度的一个标记。
如果上传过程中,服务端发现一个块已经被片数据装满,那么最后一个片上传成功后返回的Context
将是一个特殊的值EOB
,告诉客户端不要再往这个块附加更多的片。
如果客户端在每次收到Context
信息时都将其持久化到本地,即使客户端程序意外崩溃或正常重启,都可以在启动时读取上一次上传成功的片对应的Context
,从而接着继续传输剩余片。这个效果我们称之为断点续传。
断点续上传功能对上传一个需要较长时间(例如一天时间才能上传完毕)的大文件很有价值,毕竟我们很难保证这段很长的时间内客户端都不会被关闭,且网络一直处于连接状态。当前主流的移动平台(iOS、Android、Windows Phone 8)都有监测非活动应用并自动将其关闭的功能,这意味着在移动平台上我们要上传一个大文件时更容易遇到中途程序突然被关闭的情况,断点续传也就更有价值。
支持断点续传功能之后,在客户端很自然可以支持一个新功能:暂停或恢复某个文传的上传过程。
uploader为一个plupload对象,继承了所有plupload的方法,如下所示初始化:
var uploader = Qiniu.uploader({
var uploader = Qiniu.uploader({ runtimes: 'html5,flash,html4', // 上传模式,依次退化 browse_button: 'pickfiles', // 上传选择的点选按钮,必需 // 在初始化时,uptoken,uptoken_url,uptoken_func三个参数中必须有一个被设置 // 切如果提供了多个,其优先级为uptoken > uptoken_url > uptoken_func // 其中uptoken是直接提供上传凭证,uptoken_url是提供了获取上传凭证的地址,如果需要定制获取uptoken的过程则可以设置uptoken_func // uptoken : '<Your upload token>', // uptoken是上传凭证,由其他程序生成 uptoken_url: 'http://localhost:9090/videos/token', // Ajax请求uptoken的Url,强烈建议设置(服务端提供) // uptoken_func: function(file){ // 在需要获取uptoken时,该方法会被调用 // // do something // return uptoken; // }, get_new_uptoken: false, // 设置上传文件的时候是否每次都重新获取新的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: 'qujsh1', // bucket域名,下载资源时用到,必需 container: 'video_container', // 上传区域DOM ID,默认是browser_button的父元素 max_file_size: '500mb', // 最大文件体积限制 flash_swf_url: '/plupload/Moxie.swf', //引入flash,相对路径 max_retries: 3, // 上传失败最大重试次数 dragdrop: true, // 开启可拖曳上传 drop_element: 'video_container', // 拖曳上传区域元素的ID,拖曳文件或文件夹后可触发上传 chunk_size: '4mb', // 分块上传时,每块的体积 auto_start: true, // 选择文件后自动上传,若关闭需要自己绑定事件触发上传 //x_vars : { // 查看自定义变量 // 'time' : function(up,file) { // var time = (new Date()).getTime(); // do something with 'time' // return time; // }, // 'size' : function(up,file) { // var size = file.size; // do something with 'size' // return size; // } //}, init: { 'FilesAdded': function(up, files) { plupload.each(files, function(file) { // 文件添加进队列后,处理相关的事情 }); }, 'BeforeUpload': function(up, file) { // 每个文件上传前,处理相关的事情 }, 'UploadProgress': function(up, file) { // 每个文件上传时,处理相关的事情 }, 'FileUploaded': function(up, file, info) { //console.log(info); // 每个文件上传成功后,处理相关的事情 // 其中info是文件上传成功后,服务端返回的json,形式如: // { // "hash": "Fh8xVqod2MQ1mocfI4S4KpRL6D98", // "key": "gogopher.jpg" // } // 查看简单反馈 // var domain = up.getOption('domain'); // var res = parseJSON(info); // var sourceLink = domain +"/"+ res.key; 获取上传成功后的文件的Url }, 'Error': function(up, err, errTip) { //上传出错时,处理相关的事情 }, 'UploadComplete': function() { //队列文件处理完毕后,处理相关的事情 }, 'Key': function(up, file) { // 若想在前端对每个文件的key进行个性化处理,可以配置该函数 // 该配置必须要在unique_names: false,save_key: false时才生效 var key = ""; // do something with key here return key } } });
其中的属性说明:
domain:为七牛空间对应的域名,选择某个空间后,可通过 空间设置->基本设置->域名设置 查看获取
plupload.js版本低的话,会报错误:ReferenceError: mOxie is not defined。
因为plupload js在2.2.0开始,就去掉了mOxie 这个变量;所以建议使用 plupload js 的版本是在 2.1.1 到 2.1.9。(我用的是2.1.9版本)
npm已无法安装低版本。