How can I download big files in Deno?

Viewed 1445

I'm trying to download a 10GB file, but only 4GB get saved to disk, and memory is growing a lot.

const res = await fetch('https://speed.hetzner.de/10GB.bin');
const file = await Deno.open('./10gb.bin', { create: true, write: true })

const ab = new Uint8Array(await res.arrayBuffer())
await Deno.writeAll(file, ab)
2 Answers

You're buffering the response, that's why the memory is growing.

Update for latest version


Deno.open now returns a FsFile which contains a WritableStream in .writable property, so you can just pipe the response to it.

const res = await fetch('https://speed.hetzner.de/10GB.bin');
const file = await Deno.open('./10gb.bin', { create: true, write: true })

await res.body.pipeTo(file.writable);
file.close();

Older versions

You can iterate through res.body since it's currently a ReadableStream which implements Symbol.asyncIterator and use Deno.writeAll on each chunk.

for await(const chunk of res.body) {
    await Deno.writeAll(file, chunk);
}
file.close();

You can also pipe it to the file, using writerFromStreamWriter

import { writerFromStreamWriter } from "https://deno.land/std@0.156.0/streams/mod.ts?s=writerFromStreamWriter";


---

You can also use `fromStreamReader`  from `std/io` (`>= std@v0.60.0`) to convert `res.body` to a `Reader` that can be used in `Deno.copy`

import { fromStreamReader } from "https://deno.land/std@v0.60.0/io/streams.ts"; const res = await fetch('https://speed.hetzner.de/10GB.bin'); const file = await Deno.open('./10gb.bin', { create: true, write: true })

const reader = fromStreamReader(res.body!.getReader()); await Deno.copy(reader, file); file.close();


---

Regarding why it stops at 4GB I'm not sure, but it may have to do with `ArrayBuffer` / `UInt8Array` limits, since 4GB is around 2³² bytes, which is the limit of `TypedArray`, [at least in most runtimes][2].


  [1]: https://doc.deno.land/https/github.com/denoland/deno/releases/latest/download/lib.deno.d.ts#Deno.copy
  [2]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Errors/Invalid_array_length

here is another shorter version.

const res = await fetch('https://speed.hetzner.de/10GB.bin');
const file = await Deno.open('./10gb.bin', { create: true, write: true });

await res.body?.pipeTo(file.writable);
file.close();
Related