fileSender.js 2.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106
  1. import Nanobus from 'nanobus';
  2. import OwnedFile from './ownedFile';
  3. import Keychain from './keychain';
  4. import { arrayToB64, bytes } from './utils';
  5. import { uploadWs } from './api';
  6. import { encryptedSize } from './utils';
  7. export default class FileSender extends Nanobus {
  8. constructor() {
  9. super('FileSender');
  10. this.keychain = new Keychain();
  11. this.reset();
  12. }
  13. get progressRatio() {
  14. return this.progress[0] / this.progress[1];
  15. }
  16. get progressIndefinite() {
  17. return (
  18. ['fileSizeProgress', 'notifyUploadEncryptDone'].indexOf(this.msg) === -1
  19. );
  20. }
  21. get sizes() {
  22. return {
  23. partialSize: bytes(this.progress[0]),
  24. totalSize: bytes(this.progress[1])
  25. };
  26. }
  27. reset() {
  28. this.uploadRequest = null;
  29. this.msg = 'importingFile';
  30. this.progress = [0, 1];
  31. this.cancelled = false;
  32. }
  33. cancel() {
  34. this.cancelled = true;
  35. if (this.uploadRequest) {
  36. this.uploadRequest.cancel();
  37. }
  38. }
  39. async upload(archive, bearerToken) {
  40. if (this.cancelled) {
  41. throw new Error(0);
  42. }
  43. this.msg = 'encryptingFile';
  44. this.emit('encrypting');
  45. const totalSize = encryptedSize(archive.size);
  46. const encStream = await this.keychain.encryptStream(archive.stream);
  47. const metadata = await this.keychain.encryptMetadata(archive);
  48. const authKeyB64 = await this.keychain.authKeyB64();
  49. this.uploadRequest = uploadWs(
  50. encStream,
  51. metadata,
  52. authKeyB64,
  53. archive.timeLimit,
  54. archive.dlimit,
  55. bearerToken,
  56. p => {
  57. this.progress = [p, totalSize];
  58. this.emit('progress');
  59. }
  60. );
  61. if (this.cancelled) {
  62. throw new Error(0);
  63. }
  64. this.msg = 'fileSizeProgress';
  65. this.emit('progress'); // HACK to kick MS Edge
  66. try {
  67. const result = await this.uploadRequest.result;
  68. this.msg = 'notifyUploadEncryptDone';
  69. this.uploadRequest = null;
  70. this.progress = [1, 1];
  71. const secretKey = arrayToB64(this.keychain.rawSecret);
  72. const ownedFile = new OwnedFile({
  73. id: result.id,
  74. url: `${result.url}#${secretKey}`,
  75. name: archive.name,
  76. size: archive.size,
  77. manifest: archive.manifest,
  78. time: result.duration,
  79. speed: archive.size / (result.duration / 1000),
  80. createdAt: Date.now(),
  81. expiresAt: Date.now() + archive.timeLimit * 1000,
  82. secretKey: secretKey,
  83. nonce: this.keychain.nonce,
  84. ownerToken: result.ownerToken,
  85. dlimit: archive.dlimit,
  86. timeLimit: archive.timeLimit
  87. });
  88. return ownedFile;
  89. } catch (e) {
  90. this.msg = 'errorPageHeader';
  91. this.uploadRequest = null;
  92. throw e;
  93. }
  94. }
  95. }