Streaming large remote files

Hello! Is it possible to stream large files through Worker? I always get ‘script exceeded time limit’.

addEventListener(“fetch”, event => {
event.respondWith(fetchAndStream(event.request))
});

async function fetchAndStream() {
    // Fetch from origin server.
    let response = await fetch('https://www.dropbox.com/s/9x3yzowigc0sswh/alfa.mp4?dl=1');

    // Create an identity TransformStream (a.k.a. a pipe).
    // The readable side will become our new response body.
    let { readable, writable } = new TransformStream();

    // Start pumping the body. NOTE: No await!
    streamBody(response.body, writable);

    const responseInit = {
        headers: {
            'Content-Type': 'video/mp4',
            'Content-Disposition' : 'attachment; filename="video.mp4"'
        }
    };

    // ... and deliver our Response while that's running.
    return new Response(readable, responseInit)
}

async function streamBody(readable, writable) {
    let reader = readable.getReader();
    let writer = writable.getWriter();

    while (true) {
        const { done, value } = await reader.read();
        if (done) break;
        // Optionally transform value's bytes here.
        await writer.write(value);
    }

    await writer.close();
}

My first question is, do you actually need a TransformStream? Are you hoping to transform the response, or are you just looking for the response to be passed to the original request?

I need to change response headers and pass it to the original request.

You don’t need TransformStream for that, it’s needed only to modify actual body. Instead, you can pass response.body to the new Response constructor directly.

Thank you. The code below works perfectly. Is this usage of the Worker allowed by Cloudflare? I mean to stream remote files through the Worker.

addEventListener("fetch", event => {
  event.respondWith(fetchAndStream(event.request))
});

async function fetchAndStream() {
    // Fetch from origin server.
    let response = await fetch('https://www.dropbox.com/s/9x3yzowigc0sswh/alfa.mp4?dl=1');

    const responseInit = {
        headers: {
            'Content-Type': 'video/mp4',
            'Content-Disposition' : 'attachment; filename="video.mp4"'
        }
    };

    // ... and deliver our Response while that's running.
    return new Response(response.body, responseInit)
}
1 Like

@jiri, yes, this is no problem, and an intended use case.

1 Like

Great, thank you.

ty for your code