IF YOU WOULD LIKE TO GET AN ACCOUNT, please write an email to s dot adaszewski at gmail dot com. User accounts are meant only to report issues and/or generate pull requests. This is a purpose-specific Git hosting for ADARED projects. Thank you for your understanding!
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

134 lines
3.6KB

  1. //
  2. // Copyright (C) Stanislaw Adaszewski, 2020
  3. // Contact: s.adaszewski@gmail.com
  4. // Website: https://adared.ch/wba
  5. // License: GNU Affero General Public License, Version 3
  6. //
  7. import { h, Component } from 'preact';
  8. import makeArvadosRequest from 'make-arvados-request';
  9. function contentTypeFromFilename(name) {
  10. let ext = name.split('.');
  11. ext = ext[ext.length - 1].toUpperCase();
  12. if (ext === 'TXT')
  13. return 'text/plain; charset=utf-8';
  14. if (ext === 'JPG' || ext === 'JPEG')
  15. return 'image/jpeg';
  16. if (ext === 'PNG')
  17. return 'image/png';
  18. return 'application/octet-stream; charset=utf-8';
  19. }
  20. class WBDownloadPage extends Component {
  21. componentDidMount() {
  22. const { app, blocksBlobUrl, inline } = this.props;
  23. const { arvHost, arvToken } = app.state;
  24. let prom = new Promise((accept, reject) => {
  25. const xhr = new XMLHttpRequest();
  26. xhr.open('GET', blocksBlobUrl);
  27. xhr.onreadystatechange = () => {
  28. if (xhr.readyState !== 4)
  29. return;
  30. if (xhr.status !== 200)
  31. reject(xhr);
  32. else
  33. accept(xhr);
  34. };
  35. xhr.responseType = 'blob';
  36. xhr.send();
  37. });
  38. prom = prom.then(xhr => xhr.response.text());
  39. let name, file;
  40. const { streamSaver, location } = window;
  41. streamSaver.mitm = location.protocol + '//' +
  42. location.hostname + (location.port ?
  43. ':' + location.port : '') + '/mitm.html';
  44. let fileStream;
  45. let writer;
  46. let done = false;
  47. prom = prom.then(text => {
  48. let _;
  49. [ _, _, name, file ] = JSON.parse(text);
  50. fileStream = streamSaver.createWriteStream(name, {
  51. size: file[1],
  52. inline: inline,
  53. contentType: contentTypeFromFilename(name)
  54. });
  55. writer = fileStream.getWriter();
  56. window.onunload = () => {
  57. writer.abort()
  58. };
  59. window.onbeforeunload = evt => {
  60. if (!done) {
  61. evt.returnValue = `Are you sure you want to leave?`;
  62. }
  63. };
  64. const filters = [
  65. ['service_type', '=', 'proxy']
  66. ];
  67. return makeArvadosRequest(arvHost, arvToken,
  68. '/arvados/v1/keep_services?filters=' +
  69. encodeURIComponent(JSON.stringify(filters)));
  70. });
  71. prom = prom.then(xhr => {
  72. const services = xhr.response.items;
  73. const i = Math.floor(Math.random() * services.length);
  74. const proxy = services[i];
  75. let prom_1 = new Promise(accept => accept());
  76. for (let k = 0; k < file[0].length; k++) {
  77. const loc = file[0][k];
  78. prom_1 = prom_1.then(() => makeArvadosRequest(
  79. proxy.service_host + ':' + proxy.service_port,
  80. arvToken,
  81. '/' + loc[0],
  82. { 'useSsl': proxy.service_ssl_flag,
  83. 'responseType': 'arraybuffer' }
  84. ));
  85. prom_1 = prom_1.then(xhr_1 => {
  86. const blk = xhr_1.response.slice(loc[1], loc[2]);
  87. // const r = new Response(blk);
  88. // r.body.pipeTo(fileStream);
  89. return writer.write(new Uint8Array(blk));
  90. });
  91. }
  92. return prom_1;
  93. });
  94. prom = prom.then(() => {
  95. writer.close();
  96. done = true;
  97. });
  98. }
  99. render() {
  100. return (
  101. <div class="container-fluid">
  102. <div class="card my-3">
  103. <div class="card-body">
  104. Downloading, please wait...
  105. </div>
  106. </div>
  107. <div class="alert alert-danger" role="alert">
  108. Do not close this window until the download is finished.
  109. </div>
  110. </div>
  111. );
  112. }
  113. }
  114. export default WBDownloadPage;