[블레이저] 메모리 스트림 다운로더

OpenXml 등 stream 을 지원하는 객체를 사용자의 컴퓨터에 파일로 다운로드 하기 위한 레이저 컴포넌트 예제입니다.

js 를 통해 구현되었고, js 는 콜레이션 파일에 두었습니다.

./Component/StreamDownloader.razor

@inject IJSRuntime JS
@implements IAsyncDisposable

@code {
    IJSObjectReference? _module;

    protected override async Task OnAfterRenderAsync(bool firstRender)
    {
        if(firstRender)
        {
            _module = await JS.InvokeAsync<IJSObjectReference>("import",
                "./Component/StreamDownloader.razor.js");
        }
    }

    public async Task StartAsync(string fileName, Stream stream)
    {
        if(_module is not null)
        {
            using var streamRef = new DotNetStreamReference(stream);
            await _module.InvokeVoidAsync("downloadStream", fileName, streamRef);
        }
    }

    async ValueTask IAsyncDisposable.DisposeAsync()
    {
        if(_module is not null)
        {
            // for client-side blazor
            await _module.DisposeAsync();

            // if server-side blazor
            // try 
            // {
            //     await _module.DisposeAsync(); 
            // } 
            // catch (JSDisconnectedException) 
            // { 
            //     // trap exception from websocket connection failure
            // }
        }
    }
}

아래는 콜레이션 js 파일입니다.

./Component/StreamDownloader.razor.js

export async function downloadStream(fileName, contentStreamReference) {
    const arrayBuffer = await contentStreamReference.arrayBuffer();
    const blob = new Blob([arrayBuffer]);
    const url = URL.createObjectURL(blob);
    const anchr = document.createElement('a');
    anchr.href = url;
    anchr.download = fileName ?? '';
    anchr.click();
    anchr.remove();
    URL.revokeObjectURL(url);
}

사용코드

Home.razor

@using System.Text;

<StreamDownloader @ref="_downLoader" />
<button class="btn btn-primary" @onclick="ExecuteDownload">Download</button>

@code {

    StreamDownloader? _downLoader;

    private async void ExecuteDownload()
    {
        var content = "Hello world";

        var bytes = Encoding.UTF8.GetBytes(content);
        using var stream = new MemoryStream(bytes);

        if (_downLoader is not null)
            await _downLoader.StartAsync("test.txt", stream);
    }
}

참조

3개의 좋아요