Blob.js 3.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141
  1. /**
  2. * Copyright (c) Facebook, Inc. and its affiliates.
  3. *
  4. * This source code is licensed under the MIT license found in the
  5. * LICENSE file in the root directory of this source tree.
  6. *
  7. * @flow
  8. * @format
  9. */
  10. 'use strict';
  11. import type {BlobData, BlobOptions} from './BlobTypes';
  12. /**
  13. * Opaque JS representation of some binary data in native.
  14. *
  15. * The API is modeled after the W3C Blob API, with one caveat
  16. * regarding explicit deallocation. Refer to the `close()`
  17. * method for further details.
  18. *
  19. * Example usage in a React component:
  20. *
  21. * class WebSocketImage extends React.Component {
  22. * state = {blob: null};
  23. * componentDidMount() {
  24. * let ws = this.ws = new WebSocket(...);
  25. * ws.binaryType = 'blob';
  26. * ws.onmessage = (event) => {
  27. * if (this.state.blob) {
  28. * this.state.blob.close();
  29. * }
  30. * this.setState({blob: event.data});
  31. * };
  32. * }
  33. * componentUnmount() {
  34. * if (this.state.blob) {
  35. * this.state.blob.close();
  36. * }
  37. * this.ws.close();
  38. * }
  39. * render() {
  40. * if (!this.state.blob) {
  41. * return <View />;
  42. * }
  43. * return <Image source={{uri: URL.createObjectURL(this.state.blob)}} />;
  44. * }
  45. * }
  46. *
  47. * Reference: https://developer.mozilla.org/en-US/docs/Web/API/Blob
  48. */
  49. class Blob {
  50. _data: ?BlobData;
  51. /**
  52. * Constructor for JS consumers.
  53. * Currently we only support creating Blobs from other Blobs.
  54. * Reference: https://developer.mozilla.org/en-US/docs/Web/API/Blob/Blob
  55. */
  56. constructor(parts: Array<Blob | string> = [], options?: BlobOptions) {
  57. const BlobManager = require('./BlobManager');
  58. this.data = BlobManager.createFromParts(parts, options).data;
  59. }
  60. /*
  61. * This method is used to create a new Blob object containing
  62. * the data in the specified range of bytes of the source Blob.
  63. * Reference: https://developer.mozilla.org/en-US/docs/Web/API/Blob/slice
  64. */
  65. set data(data: ?BlobData) {
  66. this._data = data;
  67. }
  68. get data(): BlobData {
  69. if (!this._data) {
  70. throw new Error('Blob has been closed and is no longer available');
  71. }
  72. return this._data;
  73. }
  74. slice(start?: number, end?: number): Blob {
  75. const BlobManager = require('./BlobManager');
  76. let {offset, size} = this.data;
  77. if (typeof start === 'number') {
  78. if (start > size) {
  79. start = size;
  80. }
  81. offset += start;
  82. size -= start;
  83. if (typeof end === 'number') {
  84. if (end < 0) {
  85. end = this.size + end;
  86. }
  87. size = end - start;
  88. }
  89. }
  90. return BlobManager.createFromOptions({
  91. blobId: this.data.blobId,
  92. offset,
  93. size,
  94. });
  95. }
  96. /**
  97. * This method is in the standard, but not actually implemented by
  98. * any browsers at this point. It's important for how Blobs work in
  99. * React Native, however, since we cannot de-allocate resources automatically,
  100. * so consumers need to explicitly de-allocate them.
  101. *
  102. * Note that the semantics around Blobs created via `blob.slice()`
  103. * and `new Blob([blob])` are different. `blob.slice()` creates a
  104. * new *view* onto the same binary data, so calling `close()` on any
  105. * of those views is enough to deallocate the data, whereas
  106. * `new Blob([blob, ...])` actually copies the data in memory.
  107. */
  108. close() {
  109. const BlobManager = require('./BlobManager');
  110. BlobManager.release(this.data.blobId);
  111. this.data = null;
  112. }
  113. /**
  114. * Size of the data contained in the Blob object, in bytes.
  115. */
  116. get size(): number {
  117. return this.data.size;
  118. }
  119. /*
  120. * String indicating the MIME type of the data contained in the Blob.
  121. * If the type is unknown, this string is empty.
  122. */
  123. get type(): string {
  124. return this.data.type || '';
  125. }
  126. }
  127. module.exports = Blob;