使文件缓冲区在 Javascript 中的回调函数之外可访问的最佳方法用于大文件?
Best way to make file buffer accessible outside a callback function in Javascript for large files?
我是 JS 新手,我需要加载一个文件 1,将其中的一部分解压到文件 2,然后将解压后的文件 2 提供给用户下载——完全在浏览器端(没有 Node.js 等)。
解压我有:
let fb;
const decB = document.querySelector('button[id="dec"]')
const inputB = document.querySelector('input[type="file"]')
input.addEventListener('change', function(e) {
const r = new FileReader()
r.onload = function () {
const archive = new Uint8Array(r.result, start, length)
try {
fb = pako.inflate(archive);
} catch (err) {
console.log(err);
}
}
r.readAsArrayBuffer(input.files[0])
}, false)
decB.addEventListener("click", function(e) {
try {
const t = new TextDecoder().decode(fb)
console.log(t)
} catch(err) {
console.log(err)
}
}, false)
我希望能够在其他函数中访问 result
的内容。使用全局变量是最好的方法,还是有更合适的解决方案?
这是一个无依赖的小变体
function decompressBlob(blob) {
const ds = new DecompressionStream('gzip');
const decompressedStream = blob.stream().pipeThrough(ds);
return new Response(decompressedStream).blob();
}
function compressBlob(blob) {
const ds = new CompressionStream('gzip');
const decompressedStream = blob.stream().pipeThrough(ds);
return new Response(decompressedStream).blob();
}
const file = new File(['abc'.repeat(100)], 'filename.txt')
console.log('original file size', file.size)
compressBlob(file).then(async newBlob => {
console.log('compressed blob size:', newBlob.size)
const decompressedBlob = await decompressBlob(newBlob)
const content1 = await decompressedBlob.text()
const content2 = await file.text()
const expected = 'abc'.repeat(100)
console.log('same content:', content1 === expected)
console.log('same content:', content2 === expected)
})
然后,如果您想下载它,请创建一个对象 url 并将其附加到具有下载属性的 link
a = document.createElement('a')
a.href = Object.createObjectURL(blob)
a.download = originalFile.name + '.gz'
a.click()
我想如果你想避免回调并且没有一个巨大的代码块,那么你可以尝试使用 async/await 而不是在 blob 本身上使用新的基于承诺的读取方法(https://developer.mozilla.org/en-US/docs/Web/API/Blob/arrayBuffer)
input.addEventListener('change', async evt => {
const [file] = input.files
if (file) {
const arrayBuffer = await file.slice(28, 7412).arrayBuffer()
const compressed = new Uint8Array(arrayBuffer)
fileBuffer = pako.inflate(compressed)
document.getElementById('Decompress').disabled = false
} else {
// input was cleared
}
})
我是 JS 新手,我需要加载一个文件 1,将其中的一部分解压到文件 2,然后将解压后的文件 2 提供给用户下载——完全在浏览器端(没有 Node.js 等)。
解压我有:
let fb;
const decB = document.querySelector('button[id="dec"]')
const inputB = document.querySelector('input[type="file"]')
input.addEventListener('change', function(e) {
const r = new FileReader()
r.onload = function () {
const archive = new Uint8Array(r.result, start, length)
try {
fb = pako.inflate(archive);
} catch (err) {
console.log(err);
}
}
r.readAsArrayBuffer(input.files[0])
}, false)
decB.addEventListener("click", function(e) {
try {
const t = new TextDecoder().decode(fb)
console.log(t)
} catch(err) {
console.log(err)
}
}, false)
我希望能够在其他函数中访问 result
的内容。使用全局变量是最好的方法,还是有更合适的解决方案?
这是一个无依赖的小变体
function decompressBlob(blob) {
const ds = new DecompressionStream('gzip');
const decompressedStream = blob.stream().pipeThrough(ds);
return new Response(decompressedStream).blob();
}
function compressBlob(blob) {
const ds = new CompressionStream('gzip');
const decompressedStream = blob.stream().pipeThrough(ds);
return new Response(decompressedStream).blob();
}
const file = new File(['abc'.repeat(100)], 'filename.txt')
console.log('original file size', file.size)
compressBlob(file).then(async newBlob => {
console.log('compressed blob size:', newBlob.size)
const decompressedBlob = await decompressBlob(newBlob)
const content1 = await decompressedBlob.text()
const content2 = await file.text()
const expected = 'abc'.repeat(100)
console.log('same content:', content1 === expected)
console.log('same content:', content2 === expected)
})
然后,如果您想下载它,请创建一个对象 url 并将其附加到具有下载属性的 link
a = document.createElement('a')
a.href = Object.createObjectURL(blob)
a.download = originalFile.name + '.gz'
a.click()
我想如果你想避免回调并且没有一个巨大的代码块,那么你可以尝试使用 async/await 而不是在 blob 本身上使用新的基于承诺的读取方法(https://developer.mozilla.org/en-US/docs/Web/API/Blob/arrayBuffer)
input.addEventListener('change', async evt => {
const [file] = input.files
if (file) {
const arrayBuffer = await file.slice(28, 7412).arrayBuffer()
const compressed = new Uint8Array(arrayBuffer)
fileBuffer = pako.inflate(compressed)
document.getElementById('Decompress').disabled = false
} else {
// input was cleared
}
})