skip to Main Content

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);

2

Answers


  1. Chosen as BEST ANSWER
    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


  2. javascript:

    window.downloadFileFromStream = async function (fileName, streamRef) {
        const response = await streamRef.stream();
        const reader = response.getReader();
    
        const writableStream = new WritableStream({
            async write(chunk, controller) {
                await writer.write(chunk);
            },
            close() {
                writer.close();
            }
        });
    
        const writer = writableStream.getWriter();
    
        const pump = () => reader.read().then(({ done, value }) => {
            if (done) {
                writer.close();
                return;
            }
            return writer.write(value).then(pump);
        });
    
        await pump();
    }
    

    Include this js file.

    @page "/download"
    @inject IJSRuntime JS
    
    <button @onclick="DownloadFile">Download File</button>
    
    @code {
        private async Task DownloadFile()
        {
            var streamRef = new DotNetStreamReference(await GetFileStream());
            await JS.InvokeVoidAsync("downloadFileFromStream", "example.txt", streamRef);
        }
    
        private async Task<Stream> GetFileStream()
        {
            var stream = new MemoryStream();
            using (var writer = new StreamWriter(stream, leaveOpen: true))
            {
                await writer.WriteAsync("Example file content");
            }
            stream.Position = 0;
            return stream;
        }
    }
    
    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search