ks3jssdk.js 40 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154
  1. (function KS3JsSDK (win) {
  2. var ks3FileUploader = function(ks3PostOptions, pluploadOptions){
  3. this.defaultKS3Options = {
  4. KSSAccessKeyId: "",
  5. policy: "", //请求中用于描述获准行为的安全策略。没有安全策略的请求被认为是匿名请求,只能访问公共可写空间。
  6. signature: "", //根据Access Key Secret和policy计算的签名信息,KS3验证该签名信息从而验证该Post请求的合法性。
  7. bucket_name: "", //上传的空间名
  8. key: "", //被上传键值的名称。如果用户想要使用文件名作为键值,可以使用${filename} 变量。例如:如果用户想要上传文件local.jpg,需要指明specify /user/betty/${filename},那么键值就会为/user/betty/local.jpg。
  9. acl: "private", //上传文件访问权限,有效值: private | public-read
  10. uploadDomain: "", //上传域名,http://destination-bucket.kss.ksyun.com 或者 http://kssws.ks-cdn.com/destination-bucket
  11. autoStart: false, //是否在文件添加完毕后自动上传
  12. onInitCallBack: function(){}, //上传初始化时调用的回调函数
  13. onErrorCallBack: function(){}, //发生错误时调用的回调函数
  14. onFilesAddedCallBack: function(){}, //文件添加到浏览器时调用的回调函数
  15. onBeforeUploadCallBack: function(){}, //文件上传之前时调用的回调函数
  16. onStartUploadFileCallBack: function(){}, //文件开始上传时调用的回调函数
  17. onUploadProgressCallBack: function(){}, //上传进度时调用的回调函数
  18. onFileUploadedCallBack: function(){}, //文件上传完成时调用的回调函数
  19. onUploadCompleteCallBack: function(){} //所有上传完成时调用的回调函数
  20. };
  21. if (ks3PostOptions){
  22. //用ks3PostOptions覆盖 defaultKS3Options
  23. plupload.extend(this.defaultKS3Options, ks3PostOptions);
  24. }
  25. var multipartParams = {};
  26. if (this.defaultKS3Options.signature&&this.defaultKS3Options.policy){
  27. multipartParams = {
  28. "key": this.defaultKS3Options.key,
  29. "acl": this.defaultKS3Options.acl,
  30. "signature" : this.defaultKS3Options.signature,
  31. "KSSAccessKeyId": this.defaultKS3Options.KSSAccessKeyId,
  32. "policy": this.defaultKS3Options.policy
  33. ,'Cache-Control':this.defaultKS3Options['Cache-Control']
  34. ,'Expires': this.defaultKS3Options['Expires']
  35. ,'Content-Disposition': this.defaultKS3Options['Content-Disposition']
  36. ,'Content-Encoding': this.defaultKS3Options['Content-Encoding']
  37. ,'Content-Type': this.defaultKS3Options['Content-Type']
  38. ,'Content-Encoding': this.defaultKS3Options['Content-Encoding']
  39. }
  40. } else {
  41. multipartParams = {
  42. "key": this.defaultKS3Options.key,
  43. "acl": this.defaultKS3Options.acl,
  44. "KSSAccessKeyId": this.defaultKS3Options.KSSAccessKeyId
  45. }
  46. }
  47. for(var prop in this.defaultKS3Options) {
  48. if(typeof this.defaultKS3Options[prop] == 'string' && prop.indexOf('x-kss-meta-') !== -1 || prop == "x-kss-newfilename-in-body") {
  49. multipartParams[prop] = this.defaultKS3Options[prop];
  50. }
  51. }
  52. this.defaultPluploadOptions = {
  53. runtimes : 'html5,flash,silverlight,html4', //上传模式,依次退化;
  54. url: this.defaultKS3Options.uploadDomain,
  55. browse_button: 'browse', //触发对话框的DOM元素自身或者其ID
  56. flash_swf_url : '/public/pc/ks3-js-sdk/src/Moxie.swf', //Flash组件的相对路径
  57. silverlight_xap_url : '/public/pc/ks3-js-sdk/src//Moxie.xap', //Silverlight组件的相对路径;
  58. drop_element: undefined, //触发拖动上传的元素或者其ID
  59. multipart: true,
  60. multipart_params: multipartParams
  61. };
  62. if (pluploadOptions){
  63. plupload.extend(this.defaultPluploadOptions, pluploadOptions);
  64. }
  65. this.uploader = new plupload.Uploader(this.defaultPluploadOptions);
  66. this.uploader.bind("Init", this.onInit, this);
  67. this.uploader.bind("Error", this.onUploadError, this);
  68. this.uploader.init();
  69. this.uploader.bind("FilesAdded", this.onFilesAdded, this)
  70. this.uploader.bind("BeforeUpload", this.onBeforeUpload, this)
  71. this.uploader.bind("UploadFile", this.onStartUploadFile, this)
  72. this.uploader.bind("UploadProgress", this.onUploadProgress, this)
  73. this.uploader.bind("FileUploaded", this.onFileUploaded, this)
  74. };
  75. ks3FileUploader.prototype.onInit = function(uploader, obj){
  76. this.defaultKS3Options.onInitCallBack&&
  77. this.defaultKS3Options.onInitCallBack.apply(this, [uploader, obj]);
  78. };
  79. ks3FileUploader.prototype.onUploadError = function(uploader, obj) {
  80. this.defaultKS3Options.onErrorCallBack&&
  81. this.defaultKS3Options.onErrorCallBack.apply(this, [uploader, obj]);
  82. };
  83. ks3FileUploader.prototype.onFilesAdded = function(uploader, obj) {
  84. if (this.defaultKS3Options.autoStart)
  85. this.uploader.start();
  86. this.defaultKS3Options.onFilesAddedCallBack&&
  87. this.defaultKS3Options.onFilesAddedCallBack.apply(this, [uploader, obj]);
  88. };
  89. ks3FileUploader.prototype.onBeforeUpload = function(uploader, obj) {
  90. this.defaultKS3Options.onBeforeUploadCallBack&&
  91. this.defaultKS3Options.onBeforeUploadCallBack.apply(this, [uploader, obj]);
  92. };
  93. ks3FileUploader.prototype.onStartUploadFile = function(uploader, obj) {
  94. this.defaultKS3Options.onStartUploadFileCallBack&&
  95. this.defaultKS3Options.onStartUploadFileCallBack.apply(this, [uploader, obj]);
  96. };
  97. ks3FileUploader.prototype.onUploadProgress = function(uploader, obj) {
  98. this.defaultKS3Options.onUploadProgressCallBack&&
  99. this.defaultKS3Options.onUploadProgressCallBack.apply(this, [uploader, obj]);
  100. };
  101. ks3FileUploader.prototype.onFileUploaded = function(uploader, obj, resObj) {
  102. this.defaultKS3Options.onFileUploadedCallBack&&
  103. this.defaultKS3Options.onFileUploadedCallBack.apply(this, [uploader, obj, resObj]);
  104. };
  105. ks3FileUploader.prototype.onUploadComplete = function(uploader, obj) {
  106. this.defaultKS3Options.onUploadCompleteCallBack&&
  107. this.defaultKS3Options.onUploadCompleteCallBack.apply(this, [uploader, obj]);
  108. };
  109. return win.ks3FileUploader = ks3FileUploader;
  110. })(window);
  111. //create namespace
  112. var Ks3 = {};
  113. /**
  114. * 给url添加请求参数
  115. * @param url
  116. * @param obj
  117. * @returns {string} 带请求参数的url
  118. */
  119. Ks3.addURLParam = function(url, obj) {
  120. url += url.indexOf("?") == -1 ? "?" : "";
  121. var ret = [];
  122. for(var key in obj){
  123. key = encodeURIComponent(key);
  124. var value = obj[key];
  125. if(value && Object.prototype.toString.call(value) == '[object String]'){
  126. ret.push(key + '=' + encodeURIComponent(value));
  127. }
  128. }
  129. return url + ret.join('&');
  130. }
  131. /**
  132. * Changes XML DOM to JSON (xml 不带属性)
  133. * @param xml
  134. * @returns {{}} js对象
  135. */
  136. Ks3.xmlToJson = function (xml) {
  137. // Create the return object
  138. var obj = {};
  139. if (xml.nodeType == Node.TEXT_NODE) { // text
  140. obj = xml.nodeValue;
  141. }
  142. // do children
  143. if (xml.hasChildNodes()) {
  144. for(var i = 0; i < xml.childNodes.length; i++) {
  145. var item = xml.childNodes.item(i);
  146. var nodeName = item.nodeName;
  147. if (typeof(obj[nodeName]) == "undefined") {
  148. if( nodeName === '#text'){
  149. obj = item.nodeValue;
  150. }else{
  151. obj[nodeName] = Ks3.xmlToJson(item);
  152. }
  153. } else {//同级同标签转化为数组
  154. if (typeof(obj[nodeName].length) == "undefined") {
  155. var old = obj[nodeName];
  156. obj[nodeName] = [];
  157. obj[nodeName].push(old);
  158. }
  159. obj[nodeName].push(Ks3.xmlToJson(item));
  160. }
  161. }
  162. }
  163. return obj;
  164. };
  165. /*基于Javascript的Base64加解密算法*/
  166. Ks3.Base64 = {
  167. encTable :[ /*Base64编码表*/
  168. 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H',
  169. 'I', 'J', 'K', 'L', 'M', 'N', 'O' ,'P',
  170. 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X',
  171. 'Y', 'Z', 'a', 'b', 'c', 'd', 'e', 'f',
  172. 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n',
  173. 'o', 'p', 'q', 'r', 's', 't', 'u', 'v',
  174. 'w', 'x', 'y', 'z', '0', '1', '2', '3',
  175. '4', '5', '6', '7', '8', '9', '+', '/'
  176. ],
  177. decTable:[ /*Base64解码表*/
  178. -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
  179. -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
  180. -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
  181. -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
  182. -1, -1, -1, 62, -1, -1, -1, 63, 52, 53,
  183. 54, 55, 56, 57, 58, 59, 60, 61, -1, -1,
  184. -1, -1, -1, -1, -1, 00, 01, 02, 03, 04,
  185. 05, 06, 07, 08, 09, 10, 11, 12, 13, 14,
  186. 15, 16, 17, 18, 19, 20, 21, 22, 23, 24,
  187. 25, -1, -1, -1, -1, -1, -1, 26, 27, 28,
  188. 29, 30, 31, 32, 33, 34, 35, 36, 37, 38,
  189. 39, 40, 41, 42, 43, 44, 45, 46, 47, 48,
  190. 49, 50, 51, -1, -1, -1, -1, -1
  191. ],
  192. encUTF8: function(str) { /*将任意字符串按UTF8编码*/
  193. var code, res =[], len =str.length;
  194. var byte1, byte2, byte3, byte4, byte5, byte6;
  195. for (var i = 0; i < len; i++) {
  196. //Unicode码:按范围确定字节数
  197. code = str.charCodeAt(i);
  198. //单字节ascii字符:U+00000000 – U+0000007F 0xxxxxxx
  199. if (code > 0x0000 && code <= 0x007F) res.push(code);
  200. //双字节字符:U+00000080 – U+000007FF 110xxxxx 10xxxxxx
  201. else if (code >= 0x0080 && code <= 0x07FF) {
  202. byte1 = 0xC0 | ((code >> 6) & 0x1F);
  203. byte2 = 0x80 | (code & 0x3F);
  204. res.push(byte1, byte2);
  205. }
  206. //三字节字符:U+00000800 – U+0000FFFF 1110xxxx 10xxxxxx 10xxxxxx
  207. else if (code >= 0x0800 && code <= 0xFFFF) {
  208. byte1 = 0xE0 | ((code >> 12) & 0x0F);
  209. byte2 = 0x80 | ((code >> 6) & 0x3F);
  210. byte3 = 0x80 | (code & 0x3F);
  211. res.push(byte1, byte2, byte3);
  212. }
  213. //四字节字符:U+00010000 – U+001FFFFF 11110xxx 10xxxxxx 10xxxxxx 10xxxxxx
  214. else if (code >= 0x00010000 && code <= 0x001FFFFF) {
  215. byte1 =0xF0 | ((code>>18) & 0x07);
  216. byte2 =0x80 | ((code>>12) & 0x3F);
  217. byte3 =0x80 | ((code>>6) & 0x3F);
  218. byte4 =0x80 | (code & 0x3F);
  219. res.push(byte1, byte2, byte3, byte4);
  220. }
  221. //五字节字符:U+00200000 – U+03FFFFFF 111110xx 10xxxxxx 10xxxxxx 10xxxxxx 10xxxxxx
  222. else if (code >= 0x00200000 && code <= 0x03FFFFFF) {
  223. byte1 =0xF0 | ((code>>24) & 0x03);
  224. byte2 =0xF0 | ((code>>18) & 0x3F);
  225. byte3 =0x80 | ((code>>12) & 0x3F);
  226. byte4 =0x80 | ((code>>6) & 0x3F);
  227. byte5 =0x80 | (code & 0x3F);
  228. res.push(byte1, byte2, byte3, byte4, byte5);
  229. }
  230. //六字节字符:U+04000000 – U+7FFFFFFF 1111110x 10xxxxxx 10xxxxxx 10xxxxxx 10xxxxxx 10xxxxxx
  231. else if (code >= 0x04000000 && code <= 0x7FFFFFFF) {
  232. byte1 =0xF0 | ((code>>30) & 0x01);
  233. byte2 =0xF0 | ((code>>24) & 0x3F);
  234. byte3 =0xF0 | ((code>>18) & 0x3F);
  235. byte4 =0x80 | ((code>>12) & 0x3F);
  236. byte5 =0x80 | ((code>>6) & 0x3F);
  237. byte6 =0x80 | (code & 0x3F);
  238. res.push(byte1, byte2, byte3, byte4, byte5, byte6);
  239. }
  240. }
  241. return res;
  242. },
  243. encode: function(str) {
  244. /**
  245. * 将任意字符串用Base64加密
  246. * str:要加密的字符串
  247. * utf8编码格式
  248. */
  249. if (!str) return '';
  250. var bytes = this.encUTF8(str);
  251. var i = 0, len = bytes.length, res = [];
  252. var c1, c2, c3;
  253. while (i < len) {
  254. c1 = bytes[i++] & 0xFF;
  255. res.push(this.encTable[c1 >> 2]);
  256. //结尾剩一个字节补2个=
  257. if (i == len) {
  258. res.push(this.encTable[(c1 & 0x03) << 4], '==');
  259. break;
  260. }
  261. c2 = bytes[i++];
  262. //结尾剩两个字节补1个=
  263. if (i == len) {
  264. res.push(this.encTable[((c1 & 0x03) << 4) | ((c2 >> 4) & 0x0F)]);
  265. res.push(this.encTable[(c2 & 0x0F) << 2], '=');
  266. break;
  267. }
  268. c3 = bytes[i++];
  269. res.push(this.encTable[((c1 & 0x3) << 4) | ((c2 >> 4) & 0x0F)]);
  270. res.push(this.encTable[((c2 & 0x0F) << 2) | ((c3 & 0xC0) >> 6)]);
  271. res.push(this.encTable[c3 & 0x3F]);
  272. }
  273. return res.join('');
  274. }
  275. };
  276. Ks3.chrsz = 8; /* bits per input character. 8 - ASCII; 16 - Unicode */
  277. Ks3.b64pad = "="; /* base-64 pad character. "=" for strict RFC compliance */
  278. /*
  279. * //使用hmac_sha1算法计算字符串的签名
  280. * return base-64 encoded strings
  281. */
  282. Ks3.b64_hmac_sha1 = function(key, data) {
  283. return Ks3.binb2b64(Ks3.core_hmac_sha1(key, data));
  284. }
  285. /*
  286. * Calculate the HMAC-SHA1 of a key and some data
  287. */
  288. Ks3.core_hmac_sha1 = function(key, data)
  289. {
  290. var bkey = Ks3.str2binb(key);
  291. if(bkey.length > 16) bkey = Ks3.core_sha1(bkey, key.length * Ks3.chrsz);
  292. var ipad = Array(16), opad = Array(16);
  293. for(var i = 0; i < 16; i++)
  294. {
  295. ipad[i] = bkey[i] ^ 0x36363636;
  296. opad[i] = bkey[i] ^ 0x5C5C5C5C;
  297. }
  298. var hash = Ks3.core_sha1(ipad.concat(Ks3.str2binb(data)), 512 + data.length * Ks3.chrsz);
  299. return Ks3.core_sha1(opad.concat(hash), 512 + 160);
  300. }
  301. /*
  302. * Convert an array of big-endian words to a base-64 string
  303. */
  304. Ks3.binb2b64 = function(binarray)
  305. {
  306. var tab = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
  307. var str = "";
  308. for(var i = 0; i < binarray.length * 4; i += 3)
  309. {
  310. var triplet = (((binarray[i >> 2] >> 8 * (3 - i %4)) & 0xFF) << 16)
  311. | (((binarray[i+1 >> 2] >> 8 * (3 - (i+1)%4)) & 0xFF) << 8 )
  312. | ((binarray[i+2 >> 2] >> 8 * (3 - (i+2)%4)) & 0xFF);
  313. for(var j = 0; j < 4; j++)
  314. {
  315. if(i * 8 + j * 6 > binarray.length * 32) str += Ks3.b64pad;
  316. else str += tab.charAt((triplet >> 6*(3-j)) & 0x3F);
  317. }
  318. }
  319. return str;
  320. }
  321. /*
  322. * Convert an 8-bit or 16-bit string to an array of big-endian words
  323. * In 8-bit function, characters >255 have their hi-byte silently ignored.
  324. */
  325. Ks3.str2binb = function(str)
  326. {
  327. var bin = Array();
  328. var mask = (1 << Ks3.chrsz) - 1;
  329. for(var i = 0; i < str.length * Ks3.chrsz; i += Ks3.chrsz)
  330. bin[i>>5] |= (str.charCodeAt(i / Ks3.chrsz) & mask) << (32 - Ks3.chrsz - i%32);
  331. return bin;
  332. }
  333. /*
  334. * Calculate the SHA-1 of an array of big-endian words, and a bit length
  335. */
  336. Ks3.core_sha1 = function(x, len)
  337. {
  338. /* append padding */
  339. x[len >> 5] |= 0x80 << (24 - len % 32);
  340. x[((len + 64 >> 9) << 4) + 15] = len;
  341. var w = Array(80);
  342. var a = 1732584193;
  343. var b = -271733879;
  344. var c = -1732584194;
  345. var d = 271733878;
  346. var e = -1009589776;
  347. for(var i = 0; i < x.length; i += 16)
  348. {
  349. var olda = a;
  350. var oldb = b;
  351. var oldc = c;
  352. var oldd = d;
  353. var olde = e;
  354. for(var j = 0; j < 80; j++)
  355. {
  356. if(j < 16) w[j] = x[i + j];
  357. else w[j] = Ks3.rol(w[j-3] ^ w[j-8] ^ w[j-14] ^ w[j-16], 1);
  358. var t = Ks3.safe_add(Ks3.safe_add(Ks3.rol(a, 5), Ks3.sha1_ft(j, b, c, d)),
  359. Ks3.safe_add(Ks3.safe_add(e, w[j]), Ks3.sha1_kt(j)));
  360. e = d;
  361. d = c;
  362. c = Ks3.rol(b, 30);
  363. b = a;
  364. a = t;
  365. }
  366. a = Ks3.safe_add(a, olda);
  367. b = Ks3.safe_add(b, oldb);
  368. c = Ks3.safe_add(c, oldc);
  369. d = Ks3.safe_add(d, oldd);
  370. e = Ks3.safe_add(e, olde);
  371. }
  372. return Array(a, b, c, d, e);
  373. }
  374. /*
  375. * Add integers, wrapping at 2^32. This uses 16-bit operations internally
  376. * to work around bugs in some JS interpreters.
  377. */
  378. Ks3.safe_add =function(x, y)
  379. {
  380. var lsw = (x & 0xFFFF) + (y & 0xFFFF);
  381. var msw = (x >> 16) + (y >> 16) + (lsw >> 16);
  382. return (msw << 16) | (lsw & 0xFFFF);
  383. }
  384. /*
  385. * Bitwise rotate a 32-bit number to the left.
  386. */
  387. Ks3.rol = function(num, cnt)
  388. {
  389. return (num << cnt) | (num >>> (32 - cnt));
  390. }
  391. /*
  392. * Perform the appropriate triplet combination function for the current
  393. * iteration
  394. */
  395. Ks3.sha1_ft = function(t, b, c, d)
  396. {
  397. if(t < 20) return (b & c) | ((~b) & d);
  398. if(t < 40) return b ^ c ^ d;
  399. if(t < 60) return (b & c) | (b & d) | (c & d);
  400. return b ^ c ^ d;
  401. }
  402. /*
  403. * Determine the appropriate additive constant for the current iteration
  404. */
  405. Ks3.sha1_kt = function(t)
  406. {
  407. return (t < 20) ? 1518500249 : (t < 40) ? 1859775393 :
  408. (t < 60) ? -1894007588 : -899497514;
  409. }
  410. /**
  411. * 产生headers
  412. * CanonicalizedKssHeaders
  413. */
  414. Ks3.generateHeaders =function(header) {
  415. var str = '';
  416. var arr = [];
  417. if(header){
  418. var prefix = 'x-kss';
  419. for(var it in header){
  420. // step1 : 所有`x-kss`的属性都转换为小写
  421. if(it.indexOf(prefix) == 0){
  422. arr.push((it.toLowerCase() +':'+header[it]));
  423. }
  424. }
  425. // step2 : 根据属性名排序
  426. arr.sort();
  427. // step3 : 拼接起来
  428. str = arr.join('\n');
  429. }
  430. return str;
  431. }
  432. /**
  433. * 根据SK和请求生成Signature(用于Authorization头部)
  434. * @param sk secrete key
  435. * @param bucket bucket name
  436. * @param resource ObjectKey[?subResource]
  437. * @param http_verb PUT/GET/POST/DELETE
  438. * @param content_type Content-Type request header
  439. * @param headers headers of request
  440. * @returns {*}
  441. */
  442. Ks3.generateToken = function (sk, bucket, resource, http_verb, content_type, headers, time_stamp){
  443. // Content-MD5, Content-Type, CanonicalizedKssHeaders都为空
  444. var canonicalized_Kss_Headers = Ks3.generateHeaders(headers);
  445. var canonicalized_Resource = '/' + bucket + '/' + resource;
  446. if (canonicalized_Kss_Headers !== '') {
  447. var string2Sign = http_verb + '\n' + '' + '\n' + content_type + '\n' + time_stamp + '\n' + canonicalized_Kss_Headers + '\n' + canonicalized_Resource;
  448. } else {
  449. var string2Sign = http_verb + '\n' + '' + '\n' + content_type + '\n' + time_stamp + '\n' + canonicalized_Resource;
  450. }
  451. //console.log('string2Sign:' + string2Sign);
  452. var signature = Ks3.b64_hmac_sha1(sk, string2Sign);
  453. //console.log('signature:' + signature);
  454. return signature;
  455. }
  456. /**
  457. * 获取过期时间戳
  458. * @param seconds 多少秒后过期
  459. */
  460. function getExpires(seconds) {
  461. return Math.round(new Date().getTime()/1000) + seconds;
  462. };
  463. /*
  464. * url endpoints for different regions
  465. */
  466. Ks3.ENDPOINT = {
  467. HANGZHOU : 'kss.ksyun.com',
  468. AMERICA: 'ks3-us-west-1.ksyun.com',
  469. BEIJING : 'ks3-cn-beijing.ksyun.com',
  470. HONGKONG: 'ks3-cn-hk-1.ksyun.com',
  471. SHANGHAI: 'ks3-cn-shanghai.ksyun.com'
  472. };
  473. Ks3.config = {
  474. AK: '',
  475. SK: '',
  476. protocol:'http',
  477. baseUrl:'',
  478. region: '',
  479. bucket: '',
  480. prefix:'kss',
  481. // 分块上传的最小单位
  482. chunkSize:5*1024*1024,
  483. // 分块上传重试次数
  484. retries:20,
  485. currentUploadId: '',
  486. stopFlag: false // for multipart upload
  487. }
  488. /**
  489. * Get Bucket( List Object) 获取bucket下的objects
  490. * @param bucket : bucket name
  491. * @param url : 如:http://kss.ksyun.com/
  492. * @param cb : callback function
  493. *
  494. * @param {object} params
  495. * {
  496. * Bucket: '', // 非必传
  497. * delimiter: '', //分隔符,用于对一组参数进行分割的字符。
  498. * 'encoding-type': '', //指明请求KS3与KS3响应使用的编码方式。
  499. * maker: '', //指定列举指定空间中对象的起始位置。KS3按照字母排序方式返回结果,将从给定的 marker 开始返回列表。如果相应内容中IsTruncated为true,则可以使用返回的Contents中的最后一个key作为下次list的marker参数
  500. * 'max-keys': 0, //设置响应体中返回的最大记录数(最后实际返回可能小于该值)。默认为1000。如果你想要的结果在1000条以后,你可以设定 marker 的值来调整起始位置。
  501. * prefix: '', //限定响应结果列表使用的前缀
  502. * Signature: '' not required, 请求签名,从服务端获取
  503. * }
  504. */
  505. Ks3.listObject = function(params, cb) {
  506. var xhr = new XMLHttpRequest();
  507. var listObjectParams = {
  508. delimiter: params['delimiter'],
  509. 'encoding-type': params['encoding-type'],
  510. marker: params['marker'],
  511. 'max-keys': params['max-keys'],
  512. prefix: params['prefix']
  513. };
  514. var bucketName = params.Bucket || Ks3.config.bucket;
  515. var region = params.region || Ks3.config.region;
  516. if (region ) {
  517. Ks3.config.baseUrl = Ks3.ENDPOINT[region];
  518. }
  519. var url = Ks3.config.protocol + '://' + Ks3.config.baseUrl + '/' + bucketName; //元数据获取不要走cdn
  520. url = Ks3.addURLParam(url, listObjectParams);
  521. xhr.overrideMimeType('text/xml'); //兼容火狐
  522. xhr.onreadystatechange = function () {
  523. if (xhr.readyState == 4) {
  524. if (xhr.status >= 200 && xhr.status < 300 || xhr.status == 304) {
  525. //xml转为json格式方便js读取
  526. cb(Ks3.xmlToJson(xhr.responseXML));
  527. } else {
  528. alert('Request was unsuccessful: ' + xhr.status);
  529. console.log('status: ' + xhr.status);
  530. }
  531. }
  532. };
  533. //在金山云存储控制台(ks3.ksyun.com)中的”空间设置"页面需要设置对应空间(bucket)的CORS配置,允许请求来源(Allow Origin: * )和请求头(Allow Header: * )的GET请求,否则浏览器会报跨域错误
  534. xhr.open('GET', url, true);
  535. var signature = params.Signature || Ks3.generateToken(Ks3.config.SK, bucketName, '', 'GET', '' ,'', '');
  536. xhr.setRequestHeader('Authorization','KSS ' + Ks3.config.AK + ':' + signature );
  537. xhr.send(null);
  538. }
  539. /**
  540. * Delete Object
  541. * @param {object} params
  542. * {
  543. * Bucket: '' not required, bucket name
  544. * Key : '' Required , object key
  545. * region : '' not required bucket所在region
  546. * Signature: '' not required, 请求签名,从服务端获取
  547. * }
  548. * @param cb : callback function
  549. */
  550. Ks3.delObject = function(params, cb) {
  551. var bucketName = params.Bucket || Ks3.config.bucket;
  552. var key = Ks3.encodeKey(params.Key);
  553. var region = params.region || Ks3.config.region;
  554. if (region ) {
  555. Ks3.config.baseUrl = Ks3.ENDPOINT[region];
  556. }
  557. var url = Ks3.config.protocol + '://' + Ks3.config.baseUrl + '/' + bucketName + '/' + key;
  558. var signature = params.Signature || Ks3.generateToken(Ks3.config.SK, bucketName, key, 'DELETE', '' ,'', '');
  559. var xhr = new XMLHttpRequest();
  560. xhr.onreadystatechange = function() {
  561. if (xhr.readyState == 4) {
  562. if(xhr.status >= 200 && xhr.status < 300 || xhr.status == 304){
  563. cb(xhr.status);
  564. }else {
  565. alert('Request was unsuccessful: ' + xhr.status);
  566. console.log('status: ' + xhr.status);
  567. }
  568. }
  569. };
  570. xhr.open("DELETE", url, true);
  571. xhr.setRequestHeader('Authorization','KSS ' + Ks3.config.AK + ':' + signature );
  572. xhr.send(null);
  573. };
  574. /**
  575. * key 进行encodeURIComponent编码,'/'不能被编码
  576. */
  577. Ks3.encodeKey = function (key) {
  578. if(key == null) {
  579. return '';
  580. }
  581. var newKey = encodeURIComponent(key);
  582. newKey = newKey.replace(/\+/g,'%20').replace(/\*/g,'%2A').replace(/%7E/g,'~').replace(/%2F/g, '/');
  583. return newKey;
  584. }
  585. /**
  586. * 获取指定object的元数据
  587. * params {
  588. * Bucket: '' not required, bucket name
  589. * Key: '' Required object key
  590. * region : '' not required bucket所在region
  591. * Signature: '' not required, 请求签名,从服务端获取
  592. * }
  593. */
  594. Ks3.headObject = function(params, cb) {
  595. if (params.Key === null || params.Key === undefined) {
  596. alert('require the Key');
  597. }
  598. var key = Ks3.encodeKey(params.Key);
  599. var region = params.region || Ks3.config.region;
  600. if (region ) {
  601. Ks3.config.baseUrl = Ks3.ENDPOINT[region];
  602. }
  603. var bucketName = params.Bucket || Ks3.config.bucket || '';
  604. if(!bucketName) {
  605. alert('require the bucket name');
  606. }
  607. var url = Ks3.config.protocol + '://' + Ks3.config.baseUrl + '/' + bucketName + '/' + key;
  608. var type = 'HEAD';
  609. var signature = params.Signature ||Ks3.generateToken(Ks3.config.SK, bucketName, key, type, '' ,'', '');
  610. var xhr = new XMLHttpRequest();
  611. xhr.onreadystatechange = function() {
  612. if (xhr.readyState == 4) {
  613. if(xhr.status >= 200 && xhr.status < 300 || xhr.status == 304){
  614. //前端需要访问的头需要在CORS设置的Exposed Header中显式列出
  615. cb(null, xhr);
  616. }else {
  617. console.log('status: ' + xhr.status);
  618. cb({"msg":"request failed"}, xhr);
  619. }
  620. }
  621. };
  622. xhr.open(type, url, true);
  623. xhr.setRequestHeader('Authorization','KSS ' + Ks3.config.AK + ':' + signature );
  624. xhr.send(null);
  625. }
  626. /**
  627. * 获取指定object
  628. * params {
  629. * Bucket: '' not required, bucket name
  630. * Key: '' Required object key
  631. * region : '' not required bucket所在region
  632. * range : '' not required for range request
  633. * Signature: '' not required, 请求签名,从服务端获取
  634. * }
  635. */
  636. Ks3.getObject = function(params, cb) {
  637. if (params.Key === null || params.Key === undefined) {
  638. alert('require the Key');
  639. }
  640. var key = Ks3.encodeKey(params.Key);
  641. var region = params.region || Ks3.config.region;
  642. if (region ) {
  643. Ks3.config.baseUrl = Ks3.ENDPOINT[region];
  644. }
  645. var bucketName = params.Bucket || Ks3.config.bucket || '';
  646. if(!bucketName) {
  647. alert('require the bucket name');
  648. }
  649. var range = params.range || '';
  650. var url = Ks3.config.protocol + '://' + Ks3.config.baseUrl + '/' + bucketName + '/' + key;
  651. var type = 'GET';
  652. var signature = params.Signature || Ks3.generateToken(Ks3.config.SK, bucketName, key, type, '' ,'', '');
  653. var xhr = new XMLHttpRequest();
  654. xhr.onreadystatechange = function() {
  655. if (xhr.readyState == 4) {
  656. if(xhr.status >= 200 && xhr.status < 300 || xhr.status == 304){
  657. var bb = new Blob([this.response],{type: this.getResponseHeader('Content-Type')}); //from IE 10
  658. cb(null, bb, xhr);
  659. }else {
  660. console.log('status: ' + xhr.status);
  661. cb({"msg":"request failed"}, bb, xhr);
  662. }
  663. }
  664. };
  665. xhr.open(type, url, true);
  666. xhr.responseType = 'arraybuffer';
  667. var reRange = /^bytes=(\d+)-(\d+)$/i;
  668. if(range!==''&& reRange.test(range)){
  669. xhr.setRequestHeader('Range',range);
  670. }
  671. xhr.setRequestHeader('Authorization','KSS ' + Ks3.config.AK + ':' + signature );
  672. xhr.send(null);
  673. }
  674. /**
  675. * put object上传文件
  676. * params {
  677. * Bucket: '' not required, bucket name
  678. * Key: '' Required object key
  679. * region : '' not required bucket所在region
  680. * ACL: '' not required private | public-read
  681. * File: Object required 上传的文件
  682. * ProgressListener: Function, not required 上传进度监听函数
  683. * Signature: '' not required, 请求签名,从服务端获取
  684. * }
  685. */
  686. Ks3.putObject = function(params, cb) {
  687. if (params.Key === null || params.Key === undefined) {
  688. alert('require the Key');
  689. }
  690. var key = Ks3.encodeKey(params.Key);
  691. var region = params.region || Ks3.config.region;
  692. if (region ) {
  693. Ks3.config.baseUrl = Ks3.ENDPOINT[region];
  694. }
  695. var bucketName = params.Bucket || Ks3.config.bucket || '';
  696. if(!bucketName) {
  697. alert('require the bucket name');
  698. }
  699. var url = Ks3.config.protocol + '://' + Ks3.config.baseUrl + '/' + bucketName + '/' + key;
  700. var type = 'PUT';
  701. var xhr = new XMLHttpRequest();
  702. xhr.open(type, url, true);
  703. var headers = {};
  704. var acl = params.ACL;
  705. if (acl == 'private' || acl == 'public-read') {
  706. var attr_Acl = 'x-' + Ks3.config.prefix + '-acl';
  707. xhr.setRequestHeader(attr_Acl, acl);
  708. headers[attr_Acl] = acl;
  709. }
  710. var signature = params.Signature ||Ks3.generateToken(Ks3.config.SK, bucketName, key, type, params.File.type ,headers, '');
  711. xhr.onreadystatechange = function() {
  712. if (xhr.readyState == 4) {
  713. if(xhr.status >= 200 && xhr.status < 300 || xhr.status == 304){
  714. cb(null);
  715. }else if(xhr.status === 413 || xhr.status === 415) {
  716. var errMsg = Ks3.xmlToJson(xhr.responseXML)['Error']['Message'];
  717. cb({"msg":errMsg});
  718. }else {
  719. console.log('status: ' + xhr.status);
  720. cb({"msg":"request failed"});
  721. }
  722. }
  723. };
  724. xhr.upload.addEventListener("progress", params.ProgressListener, false);
  725. xhr.setRequestHeader('Authorization','KSS ' + Ks3.config.AK + ':' + signature );
  726. xhr.send(params.File);
  727. }
  728. /**
  729. * 下面这些部分都是关于分块上传的
  730. */
  731. /**
  732. * 初始化
  733. * params {
  734. * Bucket: '' not required, bucket name
  735. * Key: '' Required object key
  736. * region : '' not required bucket所在region
  737. * ContentType: '' not required content type of object key
  738. * ACL: '' not required private | public-read
  739. * TotalSize: '' not required, 分块上传文件总大小
  740. * Signature: '' not required, 请求签名,从服务端获取
  741. * }
  742. */
  743. Ks3.multitpart_upload_init = function(params, cb) {
  744. var bucketName = params.Bucket || Ks3.config.bucket || '';
  745. var Key = Ks3.encodeKey(params.Key) || null;
  746. if (!bucketName) {
  747. throw new Error('require the bucketName');
  748. }
  749. if (!Key) {
  750. throw new Error('require the object Key');
  751. }
  752. var region = params.region || Ks3.config.region;
  753. if (region ) {
  754. Ks3.config.baseUrl = Ks3.ENDPOINT[region];
  755. }
  756. var resource = Key + '?uploads';
  757. resource = resource.replace(/\/\//g, "/%2F");
  758. var contentType = params.ContentType || '';
  759. var type = 'POST';
  760. var url = Ks3.config.protocol + '://' + Ks3.config.baseUrl + '/' + bucketName + '/' + resource;
  761. var xhr = new XMLHttpRequest();
  762. xhr.open(type, url, true);
  763. var headers = {};
  764. var acl = params.ACL;
  765. if (acl == 'private' || acl == 'public-read') {
  766. var attr_Acl = 'x-' + Ks3.config.prefix + '-acl';
  767. xhr.setRequestHeader(attr_Acl, acl);
  768. headers[attr_Acl] = acl;
  769. }
  770. var totalSize = params.TotalSize;
  771. if(totalSize) {
  772. var attr_content_length = 'x-' + Ks3.config.prefix + '-meta-' + 'content-length';
  773. xhr.setRequestHeader(attr_content_length, totalSize);
  774. headers[attr_content_length] = totalSize;
  775. }
  776. var signature = params.Signature || Ks3.generateToken(Ks3.config.SK, bucketName, resource, type, contentType ,headers, '');
  777. xhr.overrideMimeType('text/xml'); //兼容火狐
  778. xhr.onreadystatechange = function() {
  779. if (xhr.readyState == 4) {
  780. if(xhr.status >= 200 && xhr.status < 300 || xhr.status == 304){
  781. var uploadId = Ks3.xmlToJson(xhr.responseXML)['InitiateMultipartUploadResult']['UploadId'];
  782. cb(null, uploadId);
  783. }else if(xhr.status === 413 || xhr.status === 415) {
  784. cb({"status":xhr.status, "msg": Ks3.xmlToJson(xhr.responseXML)['Error']['Message']},null);
  785. } else {
  786. console.log('status: ' + xhr.status);
  787. cb({"msg":"request failed"}, null);
  788. }
  789. }
  790. };
  791. xhr.setRequestHeader('Authorization','KSS ' + Ks3.config.AK + ':' + signature );
  792. if(contentType) {
  793. xhr.setRequestHeader('Content-Type', contentType);
  794. }
  795. xhr.send(null);
  796. }
  797. /**
  798. * 上传分块
  799. * params {
  800. * Bucket: '' not required, bucket name
  801. * Key: '' Required object key
  802. * ContentType: '' not required content type of object key
  803. * PartNumber: '' Required 分块的序号
  804. * UploadId: '' Required 初始化分块上传时获取的上传id
  805. * body: 表示上传内容的blob对象
  806. * Signature: '' not required, 请求签名,从服务端获取
  807. * }
  808. */
  809. Ks3.upload_part = function(params, cb){
  810. var bucketName = params.Bucket || Ks3.config.bucket || '';
  811. var Key = Ks3.encodeKey(params.Key) || null;
  812. var contentType = params.ContentType || '';
  813. var partNumber = (typeof params.PartNumber!=='undefined') ?params.PartNumber: '';
  814. var uploadId = params.UploadId || '';
  815. if (!bucketName || !Key) {
  816. throw new Error('require the bucketName and object key');
  817. }
  818. if (partNumber==='' || !uploadId) {
  819. throw new Error('require the partNumber and uploadId');
  820. }
  821. var body = params.body || '';
  822. var resource = Key + '?partNumber='+partNumber+'&uploadId='+uploadId;
  823. resource = resource.replace(/\/\//g, "/%2F");
  824. var url = Ks3.config.protocol + '://' + Ks3.config.baseUrl + '/' + bucketName + '/' + resource;
  825. var type = 'PUT';
  826. var signature = params.Signature || Ks3.generateToken(Ks3.config.SK, bucketName, resource, type, contentType ,'', '');
  827. var xhr = new XMLHttpRequest();
  828. xhr.onreadystatechange = function() {
  829. if (xhr.readyState == 4) {
  830. if(xhr.status >= 200 && xhr.status < 300 || xhr.status == 304){
  831. var etag = xhr.getResponseHeader('Etag');
  832. cb(null, partNumber,etag);
  833. }else if(xhr.status === 413 || xhr.status === 415) {
  834. cb({"status":xhr.status,"msg": Ks3.xmlToJson(xhr.responseXML)['Error']['Message']},null);
  835. } else {
  836. console.log('status: ' + xhr.status);
  837. cb({"msg":"request failed"}, null);
  838. }
  839. }
  840. };
  841. xhr.open(type, url, true);
  842. xhr.setRequestHeader('Authorization','KSS ' + Ks3.config.AK + ':' + signature );
  843. if(contentType) {
  844. xhr.setRequestHeader('Content-Type', contentType);
  845. }
  846. if(body) {
  847. //var contentLength = body.byteLength;
  848. //xhr.setRequestHeader('Content-Length', contentLength);
  849. xhr.send(body);
  850. }
  851. }
  852. /**
  853. * 完成上传(发送合并分块命令)
  854. * @param params
  855. * {
  856. * Bucket: '' not required, bucket name
  857. * Key: '' Required object key
  858. * UploadId: '' Required 初始化分块上传时获取的上传id
  859. * body: '' Required 描述的分块列表的xml文档
  860. * Signature: '' not required, 请求签名,从服务端获取
  861. * }
  862. * @param cb
  863. */
  864. Ks3.upload_complete = function(params,cb){
  865. var bucketName = params.Bucket || Ks3.config.bucket || '';
  866. var key = Ks3.encodeKey(params.Key) || null;
  867. var uploadId = params.UploadId || '';
  868. var callbackurl = params.callbackurl || '';
  869. var callbackbody = params.callbackbody || '';
  870. if (!bucketName || !key) {
  871. throw new Error('require the bucketName and object key');
  872. }
  873. if (!uploadId) {
  874. throw new Error('require the uploadId');
  875. }
  876. var body = params.body || '';
  877. var resource = key + '?uploadId='+uploadId;
  878. resource = resource.replace(/\/\//g, "/%2F");
  879. var contentType = 'text/plain;charset=UTF-8';
  880. var headers = {};
  881. if(callbackurl) {
  882. var attr_url = 'x-' + Ks3.config.prefix + '-callbackurl';
  883. headers[attr_url] = callbackurl;
  884. };
  885. if(callbackbody) {
  886. var attr_body = 'x-' + Ks3.config.prefix + '-callbackbody';
  887. headers[attr_body] = callbackbody;
  888. };
  889. var url = Ks3.config.protocol + '://' + Ks3.config.baseUrl + '/' + bucketName + '/' + resource;
  890. var type = 'POST';
  891. var signature = params.Signature || Ks3.generateToken(Ks3.config.SK, bucketName, resource, type, contentType,'', '');
  892. if(headers) {
  893. signature = params.Signature || Ks3.generateToken(Ks3.config.SK, bucketName, resource, type, contentType ,headers, '');
  894. };
  895. var xhr = new XMLHttpRequest();
  896. xhr.overrideMimeType('text/xml'); //兼容火狐
  897. xhr.onreadystatechange = function() {
  898. if (xhr.readyState == 4) {
  899. if(xhr.status >= 200 && xhr.status < 300 || xhr.status == 304){
  900. var res = Ks3.xmlToJson(xhr.responseXML);
  901. cb(null, res);
  902. }else {
  903. console.log('status: ' + xhr.status);
  904. cb({"msg":"request failed","status": xhr.status}, res);
  905. }
  906. }
  907. };
  908. xhr.open(type, url, true);
  909. xhr.setRequestHeader('Authorization','KSS ' + Ks3.config.AK + ':' + signature );
  910. if(callbackurl) {
  911. xhr.setRequestHeader('x-kss-callbackurl',callbackurl );
  912. }
  913. if(callbackbody) {
  914. xhr.setRequestHeader('x-kss-callbackbody',callbackbody );
  915. }
  916. if(body) {
  917. xhr.send(body);
  918. }
  919. }
  920. /**
  921. * 取消分块上传
  922. * @param params
  923. * {
  924. * Bucket: '' not required, bucket name
  925. * Key: '' Required object key
  926. * UploadId: '' Required 初始化分块上传时获取的上传id,
  927. * Signature: '' not required, 请求签名,从服务端获取
  928. * }
  929. * @param cb
  930. */
  931. Ks3.abort_multipart_upload = function(params, cb) {
  932. var bucketName = params.Bucket || Ks3.config.bucket || '';
  933. var key = Ks3.encodeKey(params.Key) || null;
  934. var uploadId = params.UploadId || '';
  935. if (!bucketName || !key) {
  936. throw new Error('require the bucketName and object key');
  937. }
  938. if (!uploadId) {
  939. throw new Error('require the uploadId');
  940. }
  941. var resource = key + '?uploadId='+uploadId;
  942. resource = resource.replace(/\/\//g, "/%2F");
  943. var url = Ks3.config.protocol + '://' + Ks3.config.baseUrl + '/' + bucketName + '/' + resource;
  944. var type = 'DELETE';
  945. var signature = params.Signature || Ks3.generateToken(Ks3.config.SK, bucketName, resource, type, '','', '');
  946. var xhr = new XMLHttpRequest();
  947. xhr.onreadystatechange = function() {
  948. if (xhr.readyState == 4) {
  949. if(xhr.status == 204 ){
  950. cb(null, {"status":xhr.status});
  951. }else {
  952. console.log('status: ' + xhr.status);
  953. cb({"msg":"request failed","status": xhr.status});
  954. }
  955. }
  956. };
  957. xhr.open(type, url, true);
  958. xhr.setRequestHeader('Authorization','KSS ' + Ks3.config.AK + ':' + signature );
  959. xhr.send(null);
  960. }
  961. /**
  962. *
  963. * @param params
  964. * {
  965. * Bucket: '' not required, bucket name
  966. * Key: '' Required object key
  967. * UploadId: '' Required 初始化分块上传时获取的上传id
  968. * Signature: '' not required, 请求签名,从服务端获取
  969. * }
  970. * @param cb
  971. */
  972. Ks3.upload_list_part = function(params,cb){
  973. var bucketName = params.Bucket || Ks3.config.bucket || '';
  974. var key = Ks3.encodeKey(params.Key) || null;
  975. var uploadId = params.UploadId || '';
  976. if (!bucketName || !key) {
  977. throw new Error('require the bucketName and object key');
  978. }
  979. if (!uploadId) {
  980. throw new Error('require the uploadId');
  981. }
  982. var resource = key + '?uploadId='+uploadId;
  983. resource = resource.replace(/\/\//g, "/%2F");
  984. var url = Ks3.config.protocol + '://' + Ks3.config.baseUrl + '/' + bucketName + '/' + resource;
  985. var type = 'GET';
  986. var signature = params.Signature || Ks3.generateToken(Ks3.config.SK, bucketName, resource, type, '','', '');
  987. var xhr = new XMLHttpRequest();
  988. xhr.overrideMimeType('text/xml'); //兼容火狐
  989. xhr.onreadystatechange = function() {
  990. if (xhr.readyState == 4) {
  991. if(xhr.status >= 200 && xhr.status < 300 || xhr.status == 304){
  992. var res = Ks3.xmlToJson(xhr.responseXML);
  993. cb(null, res);
  994. }else {
  995. console.log('status: ' + xhr.status);
  996. cb({"msg":"request failed","status": xhr.status}, res);
  997. }
  998. }
  999. };
  1000. xhr.open(type, url, true);
  1001. xhr.setRequestHeader('Authorization','KSS ' + Ks3.config.AK + ':' + signature );
  1002. xhr.send(null);
  1003. }
  1004. /**
  1005. * 判断字符串是否以给定的字符串结尾
  1006. * @param str
  1007. * @returns {boolean}
  1008. */
  1009. String.prototype.endWith = function(str){
  1010. var reg=new RegExp(str+"$");
  1011. return reg.test(this);
  1012. }
  1013. /**
  1014. * change string to XML DOM
  1015. * @param oString
  1016. * @returns {*}
  1017. */
  1018. Ks3.parseStringToXML = function(oString) {
  1019. if (document.implementation && document.implementation.createDocument) {
  1020. var xmlDoc = new DOMParser().parseFromString(oString, 'text/xml');
  1021. }
  1022. else if (window.ActiveXObject) {
  1023. var xmlDoc = new ActiveXObject("Microsoft.XMLDOM");
  1024. xmlDoc.loadXML(oString);
  1025. }
  1026. else
  1027. {
  1028. alert('浏览器不支持xml解析,请升级浏览器');
  1029. return null;
  1030. }
  1031. return xmlDoc;
  1032. }