onnxruntime
87 строк · 3.0 Кб
1// Copyright (c) Microsoft Corporation. All rights reserved.
2// Licensed under the MIT License.
3
4import { isNode } from './wasm-utils-env';
5
6/**
7* Load a file into a Uint8Array.
8*
9* @param file - the file to load. Can be a URL/path, a Blob, an ArrayBuffer, or a Uint8Array.
10* @returns a Uint8Array containing the file data.
11*/
12export const loadFile = async (file: string | Blob | ArrayBufferLike | Uint8Array): Promise<Uint8Array> => {
13if (typeof file === 'string') {
14if (isNode) {
15// load file into ArrayBuffer in Node.js
16try {
17const { readFile } = require('node:fs/promises');
18return new Uint8Array(await readFile(file));
19} catch (e) {
20if (e.code === 'ERR_FS_FILE_TOO_LARGE') {
21// file is too large, use fs.createReadStream instead
22const { createReadStream } = require('node:fs');
23const stream = createReadStream(file);
24const chunks: Uint8Array[] = [];
25for await (const chunk of stream) {
26chunks.push(chunk);
27}
28return new Uint8Array(Buffer.concat(chunks));
29}
30throw e;
31}
32} else {
33// load file into ArrayBuffer in browsers
34const response = await fetch(file);
35if (!response.ok) {
36throw new Error(`failed to load external data file: ${file}`);
37}
38const contentLengthHeader = response.headers.get('Content-Length');
39const fileSize = contentLengthHeader ? parseInt(contentLengthHeader, 10) : 0;
40if (fileSize < 1073741824 /* 1GB */) {
41// when Content-Length header is not set, we cannot determine the file size. We assume it is small enough to
42// load into memory.
43return new Uint8Array(await response.arrayBuffer());
44} else {
45// file is too large, use stream instead
46if (!response.body) {
47throw new Error(`failed to load external data file: ${file}, no response body.`);
48}
49const reader = response.body.getReader();
50
51let buffer;
52try {
53// try to create ArrayBuffer directly
54buffer = new ArrayBuffer(fileSize);
55} catch (e) {
56if (e instanceof RangeError) {
57// use WebAssembly Memory to allocate larger ArrayBuffer
58const pages = Math.ceil(fileSize / 65536);
59buffer = new WebAssembly.Memory({ initial: pages, maximum: pages }).buffer;
60} else {
61throw e;
62}
63}
64
65let offset = 0;
66// eslint-disable-next-line no-constant-condition
67while (true) {
68const { done, value } = await reader.read();
69if (done) {
70break;
71}
72const chunkSize = value.byteLength;
73const chunk = new Uint8Array(buffer, offset, chunkSize);
74chunk.set(value);
75offset += chunkSize;
76}
77return new Uint8Array(buffer, 0, fileSize);
78}
79}
80} else if (file instanceof Blob) {
81return new Uint8Array(await file.arrayBuffer());
82} else if (file instanceof Uint8Array) {
83return file;
84} else {
85return new Uint8Array(file);
86}
87};
88