upload.html 16 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618
  1. <!DOCTYPE html>
  2. <html>
  3. <head>
  4. <style type="text/css">
  5. html{
  6. background-color:#ebebec;
  7. background-image:-webkit-radial-gradient(center, #ebebec, #b4b4b4);
  8. background-image:-moz-radial-gradient(center, #ebebec, #b4b4b4);
  9. background-image:radial-gradient(center, #ebebec, #b4b4b4);
  10. }
  11. body{
  12. font:15px/1.3 Arial, sans-serif;
  13. color: #4f4f4f;
  14. margin:0;
  15. padding:0;
  16. overflow-x:hidden;
  17. }
  18. a, a:visited {
  19. outline:none;
  20. color:#389dc1;
  21. }
  22. a:hover{
  23. text-decoration:none;
  24. }
  25. section, footer, header, aside{
  26. display: block;
  27. }
  28. .dropBox {width:100vw; height:100vh; margin-top: -200px; padding-top: 200px;}
  29. #uploaddir{
  30. background-color: #2E3134;
  31. font-size:16px;
  32. font-weight:bold;
  33. color:#7f858a;
  34. padding: 40px 50px;
  35. margin-bottom: 30px;
  36. }
  37. #uploaddir a{
  38. background-color:#007a96;
  39. padding:12px 26px;
  40. color:#fff;
  41. font-size:14px;
  42. border-radius:2px;
  43. cursor:pointer;
  44. margin-top:12px;
  45. line-height:1;
  46. margin-left: 10px;
  47. }
  48. #selectedDir {
  49. margin-top:20px;
  50. }
  51. #upload{
  52. font-family:'PT Sans Narrow', sans-serif;
  53. background-color:#373a3d;
  54. background-image:-webkit-linear-gradient(top, #373a3d, #313437);
  55. background-image:-moz-linear-gradient(top, #373a3d, #313437);
  56. background-image:linear-gradient(top, #373a3d, #313437);
  57. width:450px;
  58. padding:30px;
  59. border-radius:3px;
  60. margin:10px auto 10px;
  61. box-shadow: 0 0 10px rgba(0, 0, 0, 0.3);
  62. }
  63. #drop{
  64. background-color: #2E3134;
  65. padding: 40px 50px;
  66. margin-bottom: 30px;
  67. border: 20px solid rgba(0, 0, 0, 0);
  68. border-radius: 3px;
  69. /* no external files */
  70. border-image: url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAGQAAABkCAYAAABw4pVUAAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAA2RpVFh0WE1MOmNvbS5hZG9iZS54bXAAAAAAADw/eHBhY2tldCBiZWdpbj0i77u/IiBpZD0iVzVNME1wQ2VoaUh6cmVTek5UY3prYzlkIj8+IDx4OnhtcG1ldGEgeG1sbnM6eD0iYWRvYmU6bnM6bWV0YS8iIHg6eG1wdGs9IkFkb2JlIFhNUCBDb3JlIDUuMC1jMDYwIDYxLjEzNDc3NywgMjAxMC8wMi8xMi0xNzozMjowMCAgICAgICAgIj4gPHJkZjpSREYgeG1sbnM6cmRmPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5LzAyLzIyLXJkZi1zeW50YXgtbnMjIj4gPHJkZjpEZXNjcmlwdGlvbiByZGY6YWJvdXQ9IiIgeG1sbnM6eG1wTU09Imh0dHA6Ly9ucy5hZG9iZS5jb20veGFwLzEuMC9tbS8iIHhtbG5zOnN0UmVmPSJodHRwOi8vbnMuYWRvYmUuY29tL3hhcC8xLjAvc1R5cGUvUmVzb3VyY2VSZWYjIiB4bWxuczp4bXA9Imh0dHA6Ly9ucy5hZG9iZS5jb20veGFwLzEuMC8iIHhtcE1NOk9yaWdpbmFsRG9jdW1lbnRJRD0ieG1wLmRpZDo0MUU5RTNGRDk4QjFFMjExODE0NkUyMUJBNERDNDk0NyIgeG1wTU06RG9jdW1lbnRJRD0ieG1wLmRpZDo0OEZGM0JBREI3RTcxMUUyODFDRkE4MTU1MDRCRkVBRCIgeG1wTU06SW5zdGFuY2VJRD0ieG1wLmlpZDo0OEZGM0JBQ0I3RTcxMUUyODFDRkE4MTU1MDRCRkVBRCIgeG1wOkNyZWF0b3JUb29sPSJBZG9iZSBQaG90b3Nob3AgQ1M1IFdpbmRvd3MiPiA8eG1wTU06RGVyaXZlZEZyb20gc3RSZWY6aW5zdGFuY2VJRD0ieG1wLmlpZDo0MUU5RTNGRDk4QjFFMjExODE0NkUyMUJBNERDNDk0NyIgc3RSZWY6ZG9jdW1lbnRJRD0ieG1wLmRpZDo0MUU5RTNGRDk4QjFFMjExODE0NkUyMUJBNERDNDk0NyIvPiA8L3JkZjpEZXNjcmlwdGlvbj4gPC9yZGY6UkRGPiA8L3g6eG1wbWV0YT4gPD94cGFja2V0IGVuZD0iciI/PmuiwCwAAAF7SURBVHja7NpRSsMwAIDhZJbdoNLhdXwSvIBPg11CUBS9h7AnbyYr9hAxfRmIfRDdlqx8P2SwPqwjH01gS7y+uV2GEJ7yWOdxFf5RSikMfb9/H2MMbdeFYzWj+33ksc3jtckvL3ncB5VsfBAe8rhY5JeN+aimzQjSmodqahfmoK6aqYufu93BNsFDfdYc73e5Wv245gmpLCBABASIgAARECACAkRABASI/lRzyp+r9b2pufeEWLIE5Jz2kKm/Ee0rp8lfuJYsAQEiIEAEBIiACAgQAQEiIEAEBIiACAgQAQEiILPM2d6COdtryRKQc99DnO0tl7O9liwBASIgQAQEiIAICBABASIgQAQEiIAICBABASIgs8zZ3oI522vJEpBz30Oc7S2Xs72WLAEBIiBABASIgAgIEAEBIiBzrZm6OPWz8G9KKYWh7/fvY4yh7bqjffk53s8TUuGSNZiGahpGkDfzUE3bcQ95zmOZx10enTkp0rgxvefx+CXAAFXjX+IoV9pGAAAAAElFTkSuQmCC') 25 repeat;
  71. text-align: center;
  72. text-transform: uppercase;
  73. font-size:16px;
  74. font-weight:bold;
  75. color:#7f858a;
  76. }
  77. #drop a{
  78. background-color:#007a96;
  79. padding:12px 26px;
  80. color:#fff;
  81. font-size:14px;
  82. border-radius:2px;
  83. cursor:pointer;
  84. display:block;
  85. margin-top:12px;
  86. line-height:1;
  87. width:100px;
  88. margin-left: 75px;
  89. }
  90. #drop a:hover{
  91. background-color:#0986a3;
  92. }
  93. #drop input{
  94. display:none;
  95. }
  96. #upload ul{
  97. list-style:none;
  98. margin:0 -30px;
  99. border-top:1px solid #2b2e31;
  100. border-bottom:1px solid #3d4043;
  101. padding: 0;
  102. }
  103. #upload ul li{
  104. background-color:#333639;
  105. background-image:-webkit-linear-gradient(top, #333639, #303335);
  106. background-image:-moz-linear-gradient(top, #333639, #303335);
  107. background-image:linear-gradient(top, #333639, #303335);
  108. border-top:1px solid #3d4043;
  109. border-bottom:1px solid #2b2e31;
  110. padding:15px;
  111. height: 52px;
  112. position: relative;
  113. }
  114. #upload ul li input{
  115. display: none;
  116. }
  117. #upload ul li p{
  118. width: 300px;
  119. overflow: hidden;
  120. white-space: nowrap;
  121. color: #EEE;
  122. font-size: 16px;
  123. font-weight: bold;
  124. position: absolute;
  125. top: 8px;
  126. left: 100px;
  127. }
  128. #upload ul li i{
  129. font-weight: normal;
  130. font-style:normal;
  131. color:#7f7f7f;
  132. display:block;
  133. }
  134. #upload ul li canvas{
  135. top: 5px;
  136. left: 20px;
  137. position: absolute;
  138. }
  139. .delete:after{
  140. color: #ff0000;
  141. content: "\2718";
  142. }
  143. .uploaded:after{
  144. color: #00ff00;
  145. content: "\2714";
  146. }
  147. #upload ul li span{
  148. width: 15px;
  149. height: 12px;
  150. cursor:pointer;
  151. position: absolute;
  152. top: 34px;
  153. right: 33px;
  154. font-size:18px;
  155. }
  156. #upload ul li.working span{
  157. height: 16px;
  158. background-position: 0 -12px;
  159. }
  160. #upload ul li.error p{
  161. color:red;
  162. }
  163. .chart {
  164. position:relative;
  165. margin:0px;
  166. width:48px; height:48px;
  167. }
  168. .fileInfo {
  169. text-align: center;
  170. font-size: 16px;
  171. font-weight: bold;
  172. color: #7f858a;
  173. margin-top: 24px;
  174. margin-bottom: 24px;
  175. text-transform: uppercase;
  176. }
  177. </style>
  178. <script>
  179. var files = [];
  180. var sendingOffset = 0;
  181. var lastRequest = '';
  182. var dataView;
  183. var filesCount = 0;
  184. var currentUploadingFile = 0;
  185. var uploadOrder = [];
  186. var uploadingInProgress = 0;
  187. var fileUploadRequest;
  188. var chunkSize = 128;
  189. var totalUploaded = 0;
  190. var tpl = '<li class="working" id="file%filenum%"><div class="chart" id="graph%filenum%" data-percent="0"></div><p>%filename%<i>%filesize%</i></p><span class="delete" id="fileStatus%filenum%" onclick="DeleteFiles(%filenum%);"></span></li>';
  191. document.addEventListener("DOMContentLoaded", function() {
  192. var dropbox;
  193. dropbox = document.getElementById("dropbox");
  194. dropbox.addEventListener("dragenter", dragenter, false);
  195. dropbox.addEventListener("dragover", dragover, false);
  196. dropbox.addEventListener("drop", drop, false);
  197. UpdateFileList();
  198. UploadDir("http");
  199. });
  200. function dragenter(e) {
  201. e.stopPropagation();
  202. e.preventDefault();
  203. }
  204. function dragover(e) {
  205. e.stopPropagation();
  206. e.preventDefault();
  207. }
  208. function drop(e) {
  209. e.stopPropagation();
  210. e.preventDefault();
  211. var dt = e.dataTransfer;
  212. handleFiles(dt.files);
  213. }
  214. function handleFiles(tfiles) {
  215. var filesCount = tfiles.length;
  216. files = tfiles;
  217. currentUploadingFile = 0;
  218. uploadOrder = [];
  219. sendingOffset = 0;
  220. lastRequest = '';
  221. document.getElementById('fileList').innerHTML = '';
  222. var fileNames = {};
  223. for (var i = 0; i < filesCount; i++) {
  224. fileNames[uploadDir + tfiles[i].name] = i;
  225. }
  226. Keys(fileNames).sort(function(a,b){var c=a.toLowerCase(),d=b.toLowerCase();return c<d?-1:c>d?1:0}).forEach(function(item) {
  227. var i = fileNames[item];
  228. var append = tpl.replace(/%filename%/g, uploadDir + tfiles[i].name);
  229. append = append.replace(/%filesize%/g, formatFileSize(tfiles[i].size));
  230. append = append.replace(/%filenum%/g, i);
  231. document.getElementById('fileList').insertAdjacentHTML('beforeend', append);
  232. UpdateGraph(0, i);
  233. uploadOrder.push(i);
  234. });
  235. }
  236. function DeleteFiles(filenum) {
  237. var elem = document.getElementById('file' + filenum.toString());
  238. elem.parentNode.removeChild(elem);
  239. if (uploadingInProgress) {
  240. if (parseInt(filenum) != uploadOrder[currentUploadingFile]) {
  241. for (var i = 0; i < uploadOrder.length; i++) {
  242. if (uploadOrder[i] == filenum) {
  243. delete uploadOrder[i];
  244. }
  245. }
  246. }
  247. else {
  248. uploadingInProgress = 0;
  249. RemoveFile(files[uploadOrder[currentUploadingFile]].name + '.dnl');
  250. for (var i = 0; i < uploadOrder.length; i++) {
  251. if (uploadOrder[i] == filenum) {
  252. delete uploadOrder[i];
  253. }
  254. }
  255. currentUploadingFile++;
  256. totalUploaded = 0;
  257. sendingOffset = 0;
  258. lastRequest = '';
  259. fileUploadRequest.abort();
  260. fileUploadRequest = 0;
  261. UploadFiles();
  262. }
  263. }
  264. else {
  265. for (var i = 0; i < uploadOrder.length; i++) {
  266. if (uploadOrder[i] == filenum) {
  267. delete uploadOrder[i];
  268. }
  269. }
  270. }
  271. }
  272. function UploadFiles() {
  273. if (uploadOrder[currentUploadingFile] === undefined) {
  274. uploadingInProgress = 0;
  275. if (currentUploadingFile < files.length - 1) {
  276. currentUploadingFile++;
  277. UploadFiles();
  278. }
  279. return;
  280. }
  281. var fileNum = uploadOrder[currentUploadingFile];
  282. var file = files[fileNum];
  283. var chunkLen = 0;
  284. var filedata = '';
  285. uploadingInProgress = 1;
  286. var fr = new FileReader();
  287. fr.onload = function() {
  288. dataView = null;
  289. dataView = new Uint8Array(fr.result);
  290. if (file.size <= chunkSize) {
  291. sendingOffset = 0;
  292. chunkLen = file.size;
  293. for (var i = 0; i < dataView.length; i++) {
  294. if (dataView[i] < 16) {
  295. filedata += '0';
  296. }
  297. filedata += dataView[i].toString(16).toUpperCase();
  298. }
  299. }
  300. else {
  301. if (dataView.length - sendingOffset > chunkSize) {
  302. chunkLen = chunkSize;
  303. }
  304. else {
  305. chunkLen = dataView.length - sendingOffset;
  306. }
  307. for (var i = sendingOffset; i < sendingOffset + chunkLen; i++) {
  308. if (dataView[i] < 16) {
  309. filedata += '0';
  310. }
  311. filedata += dataView[i].toString(16).toUpperCase();
  312. }
  313. }
  314. fileUploadRequest = new XMLHttpRequest();
  315. fileUploadRequest.onreadystatechange = function() {
  316. if (fileUploadRequest.readyState != 4) return;
  317. if (fileUploadRequest.status == 200) {
  318. if (chunkLen + sendingOffset < dataView.length) {
  319. totalUploaded += chunkSize;
  320. UpdateGraph(Math.round((totalUploaded / file.size) * 100), uploadOrder[currentUploadingFile]);
  321. sendingOffset += chunkSize;
  322. UploadFiles();
  323. }
  324. else {
  325. var statusElement = document.getElementById('fileStatus' + uploadOrder[currentUploadingFile]);
  326. sendingOffset = 0;
  327. UpdateGraph(100, uploadOrder[currentUploadingFile]);
  328. uploadingInProgress = 0;
  329. UpdateFileList();
  330. totalUploaded = 0;
  331. if (statusElement) {
  332. statusElement.classList.add("uploaded");
  333. }
  334. if (currentUploadingFile < files.length) {
  335. currentUploadingFile++;
  336. UploadFiles();
  337. }
  338. }
  339. }
  340. else {
  341. UploadFiles();
  342. }
  343. fileUploadRequest = 0;
  344. }
  345. lastRequest = 'upload.lua?cmd=upload&filename=' + uploadDir + file.name + '&filesize=' + file.size + '&len=' + chunkLen + '&offset=' + sendingOffset + '&data=' + filedata;
  346. fileUploadRequest.timeout = 5000;
  347. fileUploadRequest.open('GET', lastRequest, true);
  348. fileUploadRequest.send();
  349. };
  350. fr.readAsArrayBuffer(file);
  351. }
  352. function UploadDir(dir) {
  353. if (uploadingInProgress == 0) {
  354. document.getElementById('dir').innerHTML = "/" + dir;
  355. uploadDir = dir;
  356. if (!(uploadDir == "")) {
  357. uploadDir += "/";
  358. }
  359. }
  360. }
  361. function formatFileSize(bytes) {
  362. if (typeof bytes !== 'number') {
  363. return '';
  364. }
  365. if (bytes >= 1073741824) {
  366. return (bytes / 1073741824).toFixed(2) + ' GB';
  367. }
  368. if (bytes >= 1048576) {
  369. return (bytes / 1048576).toFixed(2) + ' MB';
  370. }
  371. return (bytes / 1024).toFixed(2) + ' KB';
  372. }
  373. function UpdateGraph(percent, id) {
  374. var el = document.getElementById('graph' + id); // get canvas
  375. if (!el) {
  376. return;
  377. }
  378. var options = {
  379. percent: el.getAttribute('data-percent') || 0,
  380. size: el.getAttribute('data-size') || 48,
  381. lineWidth: el.getAttribute('data-line') || 8,
  382. rotate: el.getAttribute('data-rotate') || 0
  383. }
  384. var canvas = document.createElement('canvas');
  385. if (typeof(G_vmlCanvasManager) !== 'undefined') {
  386. G_vmlCanvasManager.initElement(canvas);
  387. }
  388. var ctx = canvas.getContext('2d');
  389. canvas.width = canvas.height = options.size;
  390. el.appendChild(canvas);
  391. ctx.translate(options.size / 2, options.size / 2); // change center
  392. ctx.rotate((-1 / 2 + options.rotate / 180) * Math.PI); // rotate -90 deg
  393. var radius = (options.size - options.lineWidth) / 2;
  394. function drawCircle(color, lineWidth, percent) {
  395. if (percent) {
  396. percent = Math.min(Math.max(0, percent), 1);
  397. ctx.beginPath();
  398. ctx.arc(0, 0, radius, 0, Math.PI * 2 * percent, false);
  399. ctx.strokeStyle = color;
  400. ctx.lineCap = 'round'; // butt, round or square
  401. ctx.lineWidth = lineWidth
  402. ctx.stroke();
  403. }
  404. };
  405. options.percent = percent;
  406. drawCircle('#2e3134', options.lineWidth + 1, 100 / 100);
  407. drawCircle('#007a96', options.lineWidth, options.percent / 100);
  408. }
  409. function Keys(obj) {
  410. var keys = [];
  411. for(var key in obj){
  412. if(obj.hasOwnProperty(key)){
  413. keys.push(key);
  414. }
  415. }
  416. return keys;
  417. }
  418. function UpdateFileList() {
  419. var fileListRequest = new XMLHttpRequest();
  420. fileListRequest.onreadystatechange = function() {
  421. if (fileListRequest.readyState != 4) return;
  422. if (fileListRequest.status == 200) {
  423. var fileInfo = JSON.parse(fileListRequest.responseText);
  424. var fileList = fileInfo['files'];
  425. document.getElementById('fileInfo').innerHTML = '';
  426. var tpl = '<li class="working"><p style="left: 30px;">%filenamelink%<i>%filesize%</i></p><span class="delete" id="fileStatus" onclick="RemoveFile(\'%filename%\');"></span></li>';
  427. var tplTotal = '<li class="working"><p style="left: 30px;">Used:<i>%used%</i></p></li><li class="working"><p style="left: 30px;">Free:<i>%free%</i></p></li><li class="working"><p style="left: 30px;">Total:<i>%total%</i></p></li>';
  428. var append, link;
  429. Keys(fileList).sort(function(a,b){var c=a.toLowerCase(),d=b.toLowerCase();return c<d?-1:c>d?1:0}).forEach(function(item) {
  430. if (!item.match(/\.lc$/ig) && item.match(/^http\//ig)) {
  431. link = item.replace(/\.gz$/g, '').replace(/^http\//g, '');
  432. append = tpl.replace(/%filenamelink%/g, '<a href="' + link + '" target="_blank">' + item + '</a>');
  433. }
  434. else {
  435. append = tpl.replace(/%filenamelink%/g, item);
  436. }
  437. append = append.replace(/%filename%/g, item);
  438. append = append.replace(/%filesize%/g, formatFileSize(parseInt(fileList[item])));
  439. document.getElementById('fileInfo').insertAdjacentHTML('beforeend', append);
  440. });
  441. append = tplTotal.replace(/%used%/g, formatFileSize(parseInt(fileInfo['used'])));
  442. append = append.replace(/%free%/g, formatFileSize(parseInt(fileInfo['free'])));
  443. append = append.replace(/%total%/g, formatFileSize(parseInt(fileInfo['total'])));
  444. document.getElementById('fileInfo').insertAdjacentHTML('beforeend', append);
  445. }
  446. else {
  447. }
  448. fileListRequest = null;
  449. }
  450. fileListRequest.open('GET', 'upload.lua?cmd=list', true);
  451. fileListRequest.send();
  452. }
  453. function RemoveFile(name) {
  454. var fileRemoveRequest = new XMLHttpRequest();
  455. fileRemoveRequest.onreadystatechange = function() {
  456. if (fileRemoveRequest.readyState != 4) return;
  457. if (fileRemoveRequest.status == 200) {
  458. UpdateFileList();
  459. }
  460. }
  461. fileRemoveRequest.open('GET', 'upload.lua?cmd=remove&filename=' + name, true);
  462. fileRemoveRequest.send();
  463. }
  464. </script>
  465. </head>
  466. <body>
  467. <div id="dropbox" class="dropBox">
  468. <div id="upload">
  469. <div id="uploaddir" class="uploadDir">
  470. <a onclick='UploadDir("");'>/</a>
  471. <a onclick='UploadDir("http");'>/http</a>
  472. <div id="selectedDir">selected Directory: <div id = "dir">bla</div></div></div>
  473. <div id="drop">
  474. Drop Here
  475. <a onclick='document.getElementById("browseInput").click();'>Browse</a>
  476. <a onclick='UploadFiles();'>Upload</a>
  477. <form><input id="browseInput" type="file" name="upl" onclick="this.form.reset();" onchange="handleFiles(this.files);" multiple /></form>
  478. </div>
  479. <ul id="fileList">
  480. </ul>
  481. <div class="fileInfo">Files on device:</div>
  482. <ul id="fileInfo">
  483. </ul>
  484. </div>
  485. </div>
  486. </body>
  487. </html>