backup.html 3.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127
  1. <!DOCTYPE html>
  2. <html>
  3. <head>
  4. <link rel="icon" href="favicon.ico" type="image/x-icon">
  5. <title>Backup/Restore Configuration</title>
  6. <meta charset="utf-8">
  7. <style>
  8. h1 {font-size: 2em;}
  9. h2 {font-size: 1.5em;}
  10. h3 {font-size: 1.2em;}
  11. p {font-size: 1em;}
  12. input[type=number] {
  13. width: 138px;
  14. padding: 10px 5px;
  15. display: inline-block;
  16. border: 1px solid #ccc;
  17. font-size: 16px;
  18. }
  19. .button {
  20. padding: 10px 20px;
  21. width: 211px;
  22. font-size: 16px;
  23. }
  24. </style>
  25. </head>
  26. <body style="font-family: arial; padding: 0px 10px;">
  27. <h2>Backup Configuration</h2>
  28. <p>With the following action the config folder on the SD-card gets zipped and provided as a download.</p>
  29. <table border="0">
  30. </tr>
  31. <td>
  32. <button class="button" id="doBackup" type="button" onclick="doBackup()">Create Config backup</button>
  33. </td>
  34. <td>
  35. <p id=progress></p>
  36. </td>
  37. </tr>
  38. </table>
  39. <hr>
  40. <h2>Restore Configuration</h2>
  41. <p>Not implemented yet.<br>
  42. But you can use the <a href="/fileserver/config" target="_self">File Server</a> to upload individual files.</p>
  43. </body>
  44. <script src="jszip.min.js"></script>
  45. <script src="FileSaver.min.js"></script>
  46. <script>
  47. function doBackup() {
  48. document.getElementById("progress").innerHTML = "Creating backup...";
  49. // Get hostname
  50. var xhttp = new XMLHttpRequest();
  51. xhttp.open("GET", "/version?type=Hostname", false);
  52. xhttp.send();
  53. hostname = xhttp.responseText;
  54. // get date/time
  55. var dateTime = new Date().toJSON().slice(0,10) + "_" + new Date().toJSON().slice(11,19).replaceAll(":", "-");
  56. zipFilename = hostname + "_" + dateTime + ".zip";
  57. console.log(zipFilename);
  58. // Get files list
  59. var xhttp = new XMLHttpRequest();
  60. xhttp.open("GET", "/fileserver/config/", false);
  61. xhttp.send();
  62. var parser = new DOMParser();
  63. var content = parser.parseFromString(xhttp.responseText, 'text/html');
  64. const list = content.querySelectorAll("a");
  65. var urls = [];
  66. for (a of list) {
  67. url = a.getAttribute("href");
  68. urls.push(url);
  69. }
  70. // Pack as zip and download
  71. saveZip(zipFilename, urls);
  72. }
  73. const saveZip = (filename, urls) => {
  74. if(!urls) return;
  75. const zip = new JSZip();
  76. const folder = zip.folder("");
  77. var i = 0;
  78. urls.forEach((url) => {
  79. const blobPromise = fetch(url).then((r) => {
  80. if (r.status === 200) return r.blob();
  81. return Promise.reject(new Error(r.statusText));
  82. });
  83. const name = url.substring(url.lastIndexOf("/") + 1);
  84. folder.file(name, blobPromise);
  85. });
  86. zip.generateAsync({ type: "blob" },
  87. function updateCallback(metadata) {
  88. var msg = "Progress: " + metadata.percent.toFixed(0) + "%";
  89. if(metadata.currentFile) {
  90. msg += ", " + metadata.currentFile;
  91. }
  92. console.log(msg);
  93. document.getElementById("progress").innerHTML = msg;
  94. }
  95. ).then((blob) => saveAs(blob, filename));
  96. };
  97. </script>
  98. </html>