使用JS将APP(包括安卓和IOS)上传到七牛 (上传APP因此不考虑数据处理)javascript
uptoken使用JAVA后台获得html
七牛上传基于plupload下面不详述如何使用参见前端
七牛上传的简单案例也不详述,参见官网事例很清楚了。就是参数必定看仔细!java
清除缓存问题ios
IOS APP上传icon和ipa自动生成plistajax
补充:限制选择文件类型;打开多个选择文件窗口算法
1.使用前端获取:
本人是个前端,在后台还没给出获取uptoken接口时,我先选择了使用JS(uptoken_func参数)获取进行测试,代码以下:详细参见json
// uptoken_func: function (file) { // 在须要获取uptoken时,该方法会被调用 /** * 上传凭证算法实现参考 * 请注意External Resources项中引用的第三方CryptoJS库 */ var genUpToken = function(accessKey, secretKey, putPolicy) { //SETP 2 var put_policy = JSON.stringify(putPolicy); //SETP 3 var encoded = base64encode(utf16to8(put_policy)); //SETP 4 var hash = CryptoJS.HmacSHA1(encoded, secretKey); var encoded_signed = hash.toString(CryptoJS.enc.Base64); //SETP 5 var upload_token = accessKey + ":" + safe64(encoded_signed) + ":" + encoded; console && console.log("upload_token=", upload_token) return upload_token; // }
费了半天劲,又是引入CryptoJS,又是加入utf16to8等等方法,最后仍是失败了,生成了一个uptoken我用来上传文件上传失败,就问七牛工单,他说uptoken过期或者错误,这就无法搞了也不知道为何错,就在没有头绪的时候后台接口好了,得,用后台接口,结束!(有童鞋用JS获取了uptoken的能够来交流)
不过在错误中学习到了uptoken的第三个值(用“:”分割的aaaa:aaaa:aaaa)能够经过base64解码获得上传策略。segmentfault
2.使用后台获取(我选择的是java)
导入gson-1.6.jar和qiniu-java-sdk-7.0.0.jar,如下是qiniu的方法!是用uptoken,传入须要的参数既能够得到,本人不作后台开发就不详述,就是必定注意参数不要传错了,咱们搞了很久AK,SK复制错了,若是提示uptoken错误多检查几遍参数。到此完成了一个最简单的上传。图片描述api
奇葩同样的大坑啊,原本就是刚刚上手qiniu还没搞懂的时候还在郁闷昨天还好好的怎么过了一晚就上传失败了,查询资料,全不费功夫社区有人踩过了。看第二个评论,简单说就是设置uptoken参数不能上传大文件,必须设置uptoken_url才行,做者说的第一个方法我进不去,就没有纠结。这个是qiniu的bug!
你直接看源码就知道它在判断须要分块的时候,js-sdk内部设置up.setOption的调用getUptoken(),that.tokenInfo在只填写token的时候,仍是undefined,因此就出问题了。
由于tokenInfo是在走getNewUpToken()设置的,而getNewUpToken是走填了url才会执行的函数。
刚刚拿到需求,思索一番,
方案一:生成一个可用覆盖文件的uptoken;
方案二:qiniuJSjdk经过配置参数能够覆盖文件。
查阅API,社区资料,发现方案一能够行的通,只需后台uptoken方法时传入key参数便可覆盖服务器上面的key文件。
我原觉得key也是后台给设定的存储文件名,(这个key并非服务器存储的最终文件名)后来才发现不是,详细看scope参数。
指定上传的目标资源空间 Bucket 和资源键 Key(key的长度最大为750字节)。有两种格式:
●<bucket>,表示容许用户上传文件到指定的 bucket。在这种格式下文件只能新增,若已存在同名资源上传则会失败。
●<bucket>:<key>,表示只容许用户上传指定 key的文件。在这种格式下文件默认容许修改,若已存在同名资源则会被覆盖。若是只但愿上传指定 key 的文件,而且不容许修改,那么能够将下面的insertOnly 属性值设为 1。
因为后台须要key,因此前台在uptoken_url时传参,例如:'/appstore/app/qiniuUploadToken?params=a.png'。
前台有三个参数和文件名有关:
// unique_names: true, // 默认false,key为文件名。若开启该选项,JS-SDK会为每一个文件自动生成key(文件名) // save_key: true, // 默认false。若在服务端生成uptoken的上传策略中指定了sava_key,则开启,SDK在前端将不对key进行任何处理 'Key': function (up, file) { // 若想在前端对每一个文件的key进行个性化处理,能够配置该函数 // 该配置必需要在unique_names: false,save_key: false时才生效 var key = file.name;//**错误** // do something with key here return key }
重点看第三个参数,当时没有在乎就这样写的,因此认为给后台传的key就是服务器存储的文件名,其实否则,是我在JS key中设置了var key = file.name。应该须要前端定一个名字,而不是文件原名。
看官方文档给出以下解决方法,生成管理token,清除缓存。
可是客服给出了更好的解决方案
1、URL 问号传参刷新:
2、在七牛云存储上刷新: 一、登陆portal.qiniu.com 二、工具刷新 三、API 接口文档刷新:
3、只使用fusion cdn加速,且没有使用七牛存储
我选择了最简单的第一种,URL 问号传参。(抛出问题:ios app是ipa url问号传参,仍是plisturl问号传参,仍是都须要,待测试验证,以后更新!)
例如,若是 http://7xt44n.com2.z0.glb.qin...
这个图片资源没有更新, 能够在该 URL 后面加上参数的形式来让 CDN
强制刷新:http://7xt44n.com2.z0.glb.qin...,CDN
拿到这个 URL 后会强制回七牛的存储中取回最新的资源。原理: (用户建立空间为普通平台,在这个平台下 url 是完整缓存的。也就是说。若是你带了? 1234 这样的查询参数在文件 url
后面,就变成了不一样的 url,因此不会命中 cdn 的缓存。会去原站七牛拉资源,这时候拉取到的资源就变成了覆盖更新后的资源了。)
原先的ios部署很是不方便,须要上传icon和ipa获得地址后修改plist,再上传plist。因此就想能不能作到自动。
仍是喜欢先查阅资料看看网上有没有方案,一无所得。
方案以下:(如下代码感谢导师的支持)
使用Arttemplate获得一个模板
使用blob获得一个blob数据用于生成file对象
使用七牛的表单上传,结合XMLHttpRequest,formData获得一个表单数据
详细代码:
function plist(icon57Url, icon512Url, ipaUrl, key,plistUrl) { var data = { icon57Url: icon57Url, icon512Url: icon512Url, ipaUrl: ipaUrl, }; var html = template('test', data); var blob = new Blob([html], {type: "text/plain"}); //document.getElementById('content').innerHTML = html; var Qiniu_UploadUrl = "http://up.qiniu.com"; var Qiniu_upload = function (f, token) { var xhr = new XMLHttpRequest(); xhr.open('POST', Qiniu_UploadUrl, true); var formData, startDate; formData = new FormData(); //if (key !== null && key !== undefined) formData.append('key', key); formData.append('token', token); formData.append('name', key + '.plist'); formData.append('chunk', 0); formData.append('chunks', 1); formData.append('key', key + '.plist'); formData.append('file', f, key + '.plist'); var taking; xhr.upload.addEventListener("loadstart", function (up, file) { /*up.settings.multipart_params = { filename : "xucheng.docx" };*/ }, false); xhr.upload.addEventListener("progress", function (evt) { if (evt.lengthComputable) { /*var nowDate = new Date().getTime(); taking = nowDate - startDate; var x = (evt.loaded) / 1024; var y = taking / 1000; var uploadSpeed = (x / y); var formatSpeed; if (uploadSpeed > 1024) { formatSpeed = (uploadSpeed / 1024).toFixed(2) + "Mb\/s"; } else { formatSpeed = uploadSpeed.toFixed(2) + "Kb\/s"; }*/ //var percentComplete = Math.round(evt.loaded * 100 / evt.total); //progressbar.progressbar("value", percentComplete); // console && console.log(percentComplete, ",", formatSpeed); } }, false); xhr.onreadystatechange = function (response) { if (xhr.readyState == 4 && xhr.status == 200 && xhr.responseText != "") { var blkRet = JSON.parse(xhr.responseText); Compost('/appstore/app/updateOneProperty',{'id':datascope.appid,'ios_url':plistUrl},function () { $('#ios_url').textbox('setText', plistUrl); }) console.log("plist上传成功") } else if (xhr.status != 200 && xhr.responseText) { } }; startDate = new Date().getTime(); $("#progressbar").show(); xhr.send(formData); }; /*var reader = new window.FileReader(); reader.readAsDataURL(blob); reader.onloadend = function() { var base64data = reader.result; console.log(base64data); }*/ $.ajax({ type: "get", url: "/appstore/app/qiniuUploadToken?params=" + key + ".plist", async: true, dataType: "json", success: function (data) { var token = data.uptoken; console.log(token); Qiniu_upload(blob, token); } }); }
到此最重要的一步自动上传plist完成!,以此共同窗习。
plupload插件支持,ipa和apk都是zip类型,因此title是Zip files
filters: { mime_types: [ {title: "Image files", extensions: "png"}, //限定png后缀上传 {title: "Zip files", extensions: "ipa"}, //限定ipa后缀上传 {title: "Zip files", extensions: "apk"}, //限定apk后缀上传 ] },
每次实例化option方法时会( browse_button: *// 上传选择的点选按钮,必需)给按钮绑定一个点击事件,因此以后会点击打开屡次选择文件窗口。
尝试解决方案(失败):销毁option对象,销毁对象绑定的事件不会删除
销毁绑定事件,因为没有事件名称因此没法删除
尝试解决方案(成功):
if (uploader) {uploader.disableBrowse(true);}