fetch_stream.js 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418
  1. /**
  2. * @licstart The following is the entire license notice for the
  3. * Javascript code in this page
  4. *
  5. * Copyright 2018 Mozilla Foundation
  6. *
  7. * Licensed under the Apache License, Version 2.0 (the "License");
  8. * you may not use this file except in compliance with the License.
  9. * You may obtain a copy of the License at
  10. *
  11. * http://www.apache.org/licenses/LICENSE-2.0
  12. *
  13. * Unless required by applicable law or agreed to in writing, software
  14. * distributed under the License is distributed on an "AS IS" BASIS,
  15. * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  16. * See the License for the specific language governing permissions and
  17. * limitations under the License.
  18. *
  19. * @licend The above is the entire license notice for the
  20. * Javascript code in this page
  21. */
  22. "use strict";
  23. Object.defineProperty(exports, "__esModule", {
  24. value: true
  25. });
  26. exports.PDFFetchStream = void 0;
  27. var _regenerator = _interopRequireDefault(require("@babel/runtime/regenerator"));
  28. var _util = require("../shared/util");
  29. var _network_utils = require("./network_utils");
  30. function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
  31. function asyncGeneratorStep(gen, resolve, reject, _next, _throw, key, arg) { try { var info = gen[key](arg); var value = info.value; } catch (error) { reject(error); return; } if (info.done) { resolve(value); } else { Promise.resolve(value).then(_next, _throw); } }
  32. function _asyncToGenerator(fn) { return function () { var self = this, args = arguments; return new Promise(function (resolve, reject) { var gen = fn.apply(self, args); function _next(value) { asyncGeneratorStep(gen, resolve, reject, _next, _throw, "next", value); } function _throw(err) { asyncGeneratorStep(gen, resolve, reject, _next, _throw, "throw", err); } _next(undefined); }); }; }
  33. function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }
  34. function _defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } }
  35. function _createClass(Constructor, protoProps, staticProps) { if (protoProps) _defineProperties(Constructor.prototype, protoProps); if (staticProps) _defineProperties(Constructor, staticProps); return Constructor; }
  36. function createFetchOptions(headers, withCredentials, abortController) {
  37. return {
  38. method: 'GET',
  39. headers: headers,
  40. signal: abortController && abortController.signal,
  41. mode: 'cors',
  42. credentials: withCredentials ? 'include' : 'same-origin',
  43. redirect: 'follow'
  44. };
  45. }
  46. var PDFFetchStream =
  47. /*#__PURE__*/
  48. function () {
  49. function PDFFetchStream(source) {
  50. _classCallCheck(this, PDFFetchStream);
  51. this.source = source;
  52. this.isHttp = /^https?:/i.test(source.url);
  53. this.httpHeaders = this.isHttp && source.httpHeaders || {};
  54. this._fullRequestReader = null;
  55. this._rangeRequestReaders = [];
  56. }
  57. _createClass(PDFFetchStream, [{
  58. key: "getFullReader",
  59. value: function getFullReader() {
  60. (0, _util.assert)(!this._fullRequestReader);
  61. this._fullRequestReader = new PDFFetchStreamReader(this);
  62. return this._fullRequestReader;
  63. }
  64. }, {
  65. key: "getRangeReader",
  66. value: function getRangeReader(begin, end) {
  67. var reader = new PDFFetchStreamRangeReader(this, begin, end);
  68. this._rangeRequestReaders.push(reader);
  69. return reader;
  70. }
  71. }, {
  72. key: "cancelAllRequests",
  73. value: function cancelAllRequests(reason) {
  74. if (this._fullRequestReader) {
  75. this._fullRequestReader.cancel(reason);
  76. }
  77. var readers = this._rangeRequestReaders.slice(0);
  78. readers.forEach(function (reader) {
  79. reader.cancel(reason);
  80. });
  81. }
  82. }]);
  83. return PDFFetchStream;
  84. }();
  85. exports.PDFFetchStream = PDFFetchStream;
  86. var PDFFetchStreamReader =
  87. /*#__PURE__*/
  88. function () {
  89. function PDFFetchStreamReader(stream) {
  90. var _this = this;
  91. _classCallCheck(this, PDFFetchStreamReader);
  92. this._stream = stream;
  93. this._reader = null;
  94. this._loaded = 0;
  95. this._filename = null;
  96. var source = stream.source;
  97. this._withCredentials = source.withCredentials;
  98. this._contentLength = source.length;
  99. this._headersCapability = (0, _util.createPromiseCapability)();
  100. this._disableRange = source.disableRange || false;
  101. this._rangeChunkSize = source.rangeChunkSize;
  102. if (!this._rangeChunkSize && !this._disableRange) {
  103. this._disableRange = true;
  104. }
  105. if (typeof AbortController !== 'undefined') {
  106. this._abortController = new AbortController();
  107. }
  108. this._isStreamingSupported = !source.disableStream;
  109. this._isRangeSupported = !source.disableRange;
  110. this._headers = new Headers();
  111. for (var property in this._stream.httpHeaders) {
  112. var value = this._stream.httpHeaders[property];
  113. if (typeof value === 'undefined') {
  114. continue;
  115. }
  116. this._headers.append(property, value);
  117. }
  118. var url = source.url;
  119. fetch(url, createFetchOptions(this._headers, this._withCredentials, this._abortController)).then(function (response) {
  120. if (!(0, _network_utils.validateResponseStatus)(response.status)) {
  121. throw (0, _network_utils.createResponseStatusError)(response.status, url);
  122. }
  123. _this._reader = response.body.getReader();
  124. _this._headersCapability.resolve();
  125. var getResponseHeader = function getResponseHeader(name) {
  126. return response.headers.get(name);
  127. };
  128. var _validateRangeRequest = (0, _network_utils.validateRangeRequestCapabilities)({
  129. getResponseHeader: getResponseHeader,
  130. isHttp: _this._stream.isHttp,
  131. rangeChunkSize: _this._rangeChunkSize,
  132. disableRange: _this._disableRange
  133. }),
  134. allowRangeRequests = _validateRangeRequest.allowRangeRequests,
  135. suggestedLength = _validateRangeRequest.suggestedLength;
  136. _this._isRangeSupported = allowRangeRequests;
  137. _this._contentLength = suggestedLength || _this._contentLength;
  138. _this._filename = (0, _network_utils.extractFilenameFromHeader)(getResponseHeader);
  139. if (!_this._isStreamingSupported && _this._isRangeSupported) {
  140. _this.cancel(new _util.AbortException('streaming is disabled'));
  141. }
  142. }).catch(this._headersCapability.reject);
  143. this.onProgress = null;
  144. }
  145. _createClass(PDFFetchStreamReader, [{
  146. key: "read",
  147. value: function () {
  148. var _read = _asyncToGenerator(
  149. /*#__PURE__*/
  150. _regenerator.default.mark(function _callee() {
  151. var _ref, value, done, buffer;
  152. return _regenerator.default.wrap(function _callee$(_context) {
  153. while (1) {
  154. switch (_context.prev = _context.next) {
  155. case 0:
  156. _context.next = 2;
  157. return this._headersCapability.promise;
  158. case 2:
  159. _context.next = 4;
  160. return this._reader.read();
  161. case 4:
  162. _ref = _context.sent;
  163. value = _ref.value;
  164. done = _ref.done;
  165. if (!done) {
  166. _context.next = 9;
  167. break;
  168. }
  169. return _context.abrupt("return", {
  170. value: value,
  171. done: done
  172. });
  173. case 9:
  174. this._loaded += value.byteLength;
  175. if (this.onProgress) {
  176. this.onProgress({
  177. loaded: this._loaded,
  178. total: this._contentLength
  179. });
  180. }
  181. buffer = new Uint8Array(value).buffer;
  182. return _context.abrupt("return", {
  183. value: buffer,
  184. done: false
  185. });
  186. case 13:
  187. case "end":
  188. return _context.stop();
  189. }
  190. }
  191. }, _callee, this);
  192. }));
  193. function read() {
  194. return _read.apply(this, arguments);
  195. }
  196. return read;
  197. }()
  198. }, {
  199. key: "cancel",
  200. value: function cancel(reason) {
  201. if (this._reader) {
  202. this._reader.cancel(reason);
  203. }
  204. if (this._abortController) {
  205. this._abortController.abort();
  206. }
  207. }
  208. }, {
  209. key: "headersReady",
  210. get: function get() {
  211. return this._headersCapability.promise;
  212. }
  213. }, {
  214. key: "filename",
  215. get: function get() {
  216. return this._filename;
  217. }
  218. }, {
  219. key: "contentLength",
  220. get: function get() {
  221. return this._contentLength;
  222. }
  223. }, {
  224. key: "isRangeSupported",
  225. get: function get() {
  226. return this._isRangeSupported;
  227. }
  228. }, {
  229. key: "isStreamingSupported",
  230. get: function get() {
  231. return this._isStreamingSupported;
  232. }
  233. }]);
  234. return PDFFetchStreamReader;
  235. }();
  236. var PDFFetchStreamRangeReader =
  237. /*#__PURE__*/
  238. function () {
  239. function PDFFetchStreamRangeReader(stream, begin, end) {
  240. var _this2 = this;
  241. _classCallCheck(this, PDFFetchStreamRangeReader);
  242. this._stream = stream;
  243. this._reader = null;
  244. this._loaded = 0;
  245. var source = stream.source;
  246. this._withCredentials = source.withCredentials;
  247. this._readCapability = (0, _util.createPromiseCapability)();
  248. this._isStreamingSupported = !source.disableStream;
  249. if (typeof AbortController !== 'undefined') {
  250. this._abortController = new AbortController();
  251. }
  252. this._headers = new Headers();
  253. for (var property in this._stream.httpHeaders) {
  254. var value = this._stream.httpHeaders[property];
  255. if (typeof value === 'undefined') {
  256. continue;
  257. }
  258. this._headers.append(property, value);
  259. }
  260. var rangeStr = begin + '-' + (end - 1);
  261. this._headers.append('Range', 'bytes=' + rangeStr);
  262. var url = source.url;
  263. fetch(url, createFetchOptions(this._headers, this._withCredentials, this._abortController)).then(function (response) {
  264. if (!(0, _network_utils.validateResponseStatus)(response.status)) {
  265. throw (0, _network_utils.createResponseStatusError)(response.status, url);
  266. }
  267. _this2._readCapability.resolve();
  268. _this2._reader = response.body.getReader();
  269. });
  270. this.onProgress = null;
  271. }
  272. _createClass(PDFFetchStreamRangeReader, [{
  273. key: "read",
  274. value: function () {
  275. var _read2 = _asyncToGenerator(
  276. /*#__PURE__*/
  277. _regenerator.default.mark(function _callee2() {
  278. var _ref2, value, done, buffer;
  279. return _regenerator.default.wrap(function _callee2$(_context2) {
  280. while (1) {
  281. switch (_context2.prev = _context2.next) {
  282. case 0:
  283. _context2.next = 2;
  284. return this._readCapability.promise;
  285. case 2:
  286. _context2.next = 4;
  287. return this._reader.read();
  288. case 4:
  289. _ref2 = _context2.sent;
  290. value = _ref2.value;
  291. done = _ref2.done;
  292. if (!done) {
  293. _context2.next = 9;
  294. break;
  295. }
  296. return _context2.abrupt("return", {
  297. value: value,
  298. done: done
  299. });
  300. case 9:
  301. this._loaded += value.byteLength;
  302. if (this.onProgress) {
  303. this.onProgress({
  304. loaded: this._loaded
  305. });
  306. }
  307. buffer = new Uint8Array(value).buffer;
  308. return _context2.abrupt("return", {
  309. value: buffer,
  310. done: false
  311. });
  312. case 13:
  313. case "end":
  314. return _context2.stop();
  315. }
  316. }
  317. }, _callee2, this);
  318. }));
  319. function read() {
  320. return _read2.apply(this, arguments);
  321. }
  322. return read;
  323. }()
  324. }, {
  325. key: "cancel",
  326. value: function cancel(reason) {
  327. if (this._reader) {
  328. this._reader.cancel(reason);
  329. }
  330. if (this._abortController) {
  331. this._abortController.abort();
  332. }
  333. }
  334. }, {
  335. key: "isStreamingSupported",
  336. get: function get() {
  337. return this._isStreamingSupported;
  338. }
  339. }]);
  340. return PDFFetchStreamRangeReader;
  341. }();