diff --git a/packages/interface-ipfs-core/package.json b/packages/interface-ipfs-core/package.json index 1ff79ce8e3..30a369b572 100644 --- a/packages/interface-ipfs-core/package.json +++ b/packages/interface-ipfs-core/package.json @@ -112,7 +112,8 @@ "pako": "^2.0.4", "readable-stream": "^4.0.0", "sinon": "^14.0.0", - "uint8arrays": "^4.0.2" + "uint8arrays": "^4.0.2", + "wherearewe": "^2.0.1" }, "browser": { "fs": false, diff --git a/packages/interface-ipfs-core/src/files/stat.js b/packages/interface-ipfs-core/src/files/stat.js index 04e949764f..3b63389c4a 100644 --- a/packages/interface-ipfs-core/src/files/stat.js +++ b/packages/interface-ipfs-core/src/files/stat.js @@ -11,6 +11,7 @@ import { identity } from 'multiformats/hashes/identity' import { randomBytes } from 'iso-random-stream' import isShardAtPath from '../utils/is-shard-at-path.js' import * as raw from 'multiformats/codecs/raw' +import { isBrowser } from 'wherearewe' /** * @typedef {import('ipfsd-ctl').Factory} Factory @@ -103,6 +104,27 @@ export function testStat (factory, options) { }) }) + it('should stat a large browser File', async function () { + if (!isBrowser) { + this.skip() + } + + const filePath = `/stat-${Math.random()}/large-file-${Math.random()}.txt` + const blob = new Blob([largeFile]) + + await ipfs.files.write(filePath, blob, { + create: true, + parents: true + }) + + await expect(ipfs.files.stat(filePath)).to.eventually.include({ + size: largeFile.length, + cumulativeSize: 490800, + blocks: 2, + type: 'file' + }) + }) + it('stats a raw node', async () => { const filePath = `/stat-${Math.random()}/large-file-${Math.random()}.txt` diff --git a/packages/ipfs-core/package.json b/packages/ipfs-core/package.json index 36e6c546eb..aac1e417ce 100644 --- a/packages/ipfs-core/package.json +++ b/packages/ipfs-core/package.json @@ -102,6 +102,7 @@ "any-signal": "^3.0.0", "array-shuffle": "^3.0.0", "blockstore-core": "^2.0.1", + "browser-readablestream-to-it": "^2.0.0", "dag-jose": "^3.0.1", "datastore-core": "^8.0.1", "datastore-pubsub": "^6.0.0", diff --git a/packages/ipfs-core/src/components/files/utils/to-async-iterator.js b/packages/ipfs-core/src/components/files/utils/to-async-iterator.js index 06f7a9ee5c..219b959a19 100644 --- a/packages/ipfs-core/src/components/files/utils/to-async-iterator.js +++ b/packages/ipfs-core/src/components/files/utils/to-async-iterator.js @@ -1,9 +1,7 @@ import errCode from 'err-code' import { logger } from '@libp2p/logger' -import { - MFS_MAX_CHUNK_SIZE -} from '../../../utils.js' import { fromString as uint8ArrayFromString } from 'uint8arrays/from-string' +import browserStreamToIt from 'browser-readablestream-to-it' const log = logger('ipfs:mfs:utils:to-async-iterator') @@ -44,52 +42,7 @@ export function toAsyncIterator (content) { if (global.Blob && content instanceof global.Blob) { // HTML5 Blob objects (including Files) log('Content was an HTML5 Blob') - - let index = 0 - - const iterator = { - next: () => { - if (index > content.size) { - return { - done: true - } - } - - return new Promise((resolve, reject) => { - const chunk = content.slice(index, MFS_MAX_CHUNK_SIZE) - index += MFS_MAX_CHUNK_SIZE - - const reader = new global.FileReader() - - /** - * @param {{ error?: Error }} ev - */ - const handleLoad = (ev) => { - // @ts-expect-error No overload matches this call. - reader.removeEventListener('loadend', handleLoad, false) - - if (ev.error) { - return reject(ev.error) - } - - resolve({ - done: false, - value: new Uint8Array(/** @type {ArrayBuffer} */(reader.result)) - }) - } - - // @ts-expect-error No overload matches this call. - reader.addEventListener('loadend', handleLoad) - reader.readAsArrayBuffer(chunk) - }) - } - } - - return { - [Symbol.asyncIterator]: () => { - return iterator - } - } + return browserStreamToIt(content.stream()) } throw errCode(new Error(`Don't know how to convert ${content} into an async iterator`), 'ERR_INVALID_PARAMS')