Search code examples
javascriptdownloadstreamblazorblazor-webassembly

downloading file-stream from browser get request


Im working on a service to download large files. There is a web frontend, that sends a get request, which recieves the file as a stream. I have looked into Streamsaver.js, but i dont want the mitm. Currently using it like this

async function downloadFileFromStream(fileName, streamRef) {
    // Get the stream from the .NET stream reference
    const response = await streamRef.stream();
    const readableStream = response.getReader();
    const fileStream = streamSaver.createWriteStream(fileName);

    if (window.WritableStream && readableStream.pipeTo) {
        await readableStream.pipeTo(fileStream);
        return;
    }

    const writer = fileStream.getWriter();
    

    const pump = () => readableStream.read()
        .then(({ done, value }) => {
            if (done) {
                writer.close();
                return;
            }
            return writer.write(value).then(pump);
        });

    await pump();
}

// To register the function in the global window object so it can be called from C#
window.downloadFileFromStream = downloadFileFromStream;

I would like to know if there is a way similar to how i would have done it in C#

psudo-code

Readstream r;
Writestream w;

r.copyToAsync(w);


Solution

  • window.downloadFileFromStream = async function (fileName, streamRef) {
        // Get the response from the stream reference
        const response = await streamRef.stream();
        const reader = response.getReader();
    
        // Show file picker to choose save location
        const handle = await window.showSaveFilePicker({
            suggestedName: fileName
        });
    
        // Create a writable stream and wait for it to be ready
        const writableStream = await handle.createWritable();
    
        // Function to pump data from the reader to the writable stream
        const pump = async () => {
            const { done, value } = await reader.read();
            if (done) {
                await writableStream.close();
                console.log("done");
                return;
            }
            await writableStream.write(value);
            return pump(); // Call pump again for the next chunk
        };
    
        // Start pumping data
        await pump();
    }
    

    I tried this, and got it to work if anyone still has this issue. The only problem i see in this is that it does not show the progress in the browser downloadstab, only in the filesystem downloads