ASP.NET Core에서 이미지 및 문서 표시 Blazor

참고 항목

이 문서의 최신 버전은 아닙니다. 현재 릴리스는 이 문서의 .NET 8 버전을 참조 하세요.

Warning

이 버전의 ASP.NET Core는 더 이상 지원되지 않습니다. 자세한 내용은 .NET 및 .NET Core 지원 정책을 참조 하세요. 현재 릴리스는 이 문서의 .NET 8 버전을 참조 하세요.

Important

이 정보는 상업적으로 출시되기 전에 실질적으로 수정될 수 있는 시험판 제품과 관련이 있습니다. Microsoft는 여기에 제공된 정보에 대해 어떠한 명시적, 또는 묵시적인 보증을 하지 않습니다.

현재 릴리스는 이 문서의 .NET 8 버전을 참조 하세요.

이 문서에서는 앱에서 Blazor 이미지 및 문서를 표시하는 방법을 설명합니다.

이 문서의 예제는 샘플 앱에서 Blazor 검사하고 사용할 수 있습니다.

dotnet/blazor-samplesGitHub 리포지토리: (8.0 이상), (7.0 이하) BlazorSample_Server 또는 BlazorSample_WebAssemblyBlazorSample_BlazorWebApp 으로 이동합니다.

동적으로 이미지 소스 설정

다음 예제에서는 C# 필드를 사용하여 이미지의 소스를 동적으로 설정하는 방법을 보여 줍니다.

이 섹션의 예제에서는 세 개의 이미지 파일(이름 image1.png, image2.pngimage3.png.)을 사용합니다. 이미지는 앱의 웹 루트(wwwroot)에 있는 폴더 images 에 배치됩니다. images 폴더는 시연 목적으로만 사용합니다. 폴더에서 직접 자산을 제공하는 것을 포함하여 원하는 모든 폴더 레이아웃에서 wwwroot 정적 자산을 구성할 수 있습니다.

다음은 ShowImage1 구성 요소에 대한 설명입니다.

  • 이미지의 소스(src)는 C#에서 imageSource 값으로 동적으로 설정됩니다.
  • ShowImage 메서드는 메서드에 전달된 이미지 id 인수를 기준으로 imageSource 필드를 업데이트합니다.
  • 렌더링된 단추는 images 폴더의 사용 가능한 세 이미지 각각에 대해 이미지 인수를 사용하여 ShowImage 메서드를 호출합니다. 파일 이름은 메서드에 전달된 인수를 사용하여 구성되며 images 폴더의 세 이미지 중 하나와 일치합니다.

ShowImage1.razor:

@page "/show-image-1"

<PageTitle>Show Image 1</PageTitle>

<h1>Show Image Example 1</h1>

@if (imageSource is not null)
{
    <p>
        <img src="@imageSource" />
    </p>
}

@for (var i = 1; i <= 3; i++)
{
    var imageId = i;
    <button @onclick="() => ShowImage(imageId)">
        Image @imageId
    </button>
}

@code {
    private string? imageSource;

    private void ShowImage(int id) => imageSource = $"images/image{id}.png";
}
@page "/show-image-1"

<PageTitle>Show Image 1</PageTitle>

<h1>Show Image Example 1</h1>

@if (imageSource is not null)
{
    <p>
        <img src="@imageSource" />
    </p>
}

@for (var i = 1; i <= 3; i++)
{
    var imageId = i;
    <button @onclick="() => ShowImage(imageId)">
        Image @imageId
    </button>
}

@code {
    private string? imageSource;

    private void ShowImage(int id) => imageSource = $"images/image{id}.png";
}
@page "/show-image-1"

<h1>Dynamic Image Source Example</h1>

@if (imageSource is not null)
{
    <p>
        <img src="@imageSource" />
    </p>
}

@for (var i = 1; i <= 3; i++)
{
    var imageId = i;
    <button @onclick="() => ShowImage(imageId)">
        Image @imageId
    </button>
}

@code {
    private string? imageSource;

    private void ShowImage(int id)
    {
        imageSource = $"images/image{id}.png";
    }
}
@page "/show-image-1"

<h1>Dynamic Image Source Example</h1>

@if (imageSource is not null)
{
    <p>
        <img src="@imageSource" />
    </p>
}

@for (var i = 1; i <= 3; i++)
{
    var imageId = i;
    <button @onclick="() => ShowImage(imageId)">
        Image @imageId
    </button>
}

@code {
    private string? imageSource;

    private void ShowImage(int id)
    {
        imageSource = $"images/image{id}.png";
    }
}

앞의 예제에서는 C# 필드를 사용하여 이미지의 소스 데이터를 저장하지만 C# 속성을 사용하여 데이터를 저장할 수도 있습니다.

for 루프 예제의 i와 같이 람다 식에서 직접 루프 변수를 사용하지 않습니다. 직접 사용하는 경우 모든 람다 식에서 동일한 변수가 사용되어 모든 람다에서 동일한 값이 사용됩니다. 로컬 변수에서 변수의 값을 캡처합니다. 앞의 예에서:

  • 루프 변수 iimageId에 할당됩니다.
  • imageId는 람다 식에서 사용됩니다.

또는 위의 문제가 발생하지 않는 Enumerable.Range를 가진 foreach 루프를 사용합니다.

@foreach (var imageId in Enumerable.Range(1, 3))
{
    <button @onclick="() => ShowImage(imageId)">
        Image @imageId
    </button>
}

이벤트 처리가 있는 람다 식에 대한 자세한 내용은 ASP.NET Core Blazor 이벤트 처리를 참조하세요.

이미지 또는 문서 데이터 스트리밍

이미지 또는 PDF와 같은 다른 문서 형식은 공용 URL에서 파일을 호스팅하는 대신 '스트리밍 interop 기능을 사용하여 Blazor클라이언트로 직접 전송할 수 있습니다.

이 섹션의 예제는 JavaScript(JS) interop을 사용하여 원본 데이터를 스트리밍합니다. 다음 setSourceJS 함수는 다음 작업을 수행합니다.

  • 다음 요소<body><link><embed><img><track><iframe><object><script><style>대한 콘텐츠를 스트리밍하는 데 사용할 수 있습니다.
  • id 파일의 콘텐츠, 문서의 데이터 스트림, 콘텐츠 형식 및 표시 요소의 제목을 표시하는 요소를 허용합니다.

함수:

  • 제공된 스트림을 ArrayBuffer로 읽어옵니다.
  • Blob Blob의 콘텐츠 형식을 ArrayBuffer설정하는 래핑을 만듭니다.
  • 표시할 문서의 주소로 사용할 개체 URL을 만듭니다.
  • 매개 변수에서 title 요소의 제목(title)을 설정하고 만든 개체 URL에서 요소의 원본(src)을 설정합니다.
  • 메모리 누수 방지를 위해 함수는 요소가 리소스(load이벤트)를 로드한 후 개체 URL을 삭제하도록 호출 revokeObjectURL 합니다.
<script>
  window.setSource = async (elementId, stream, contentType, title) => {
    const arrayBuffer = await stream.arrayBuffer();
    let blobOptions = {};
    if (contentType) {
      blobOptions['type'] = contentType;
    }
    const blob = new Blob([arrayBuffer], blobOptions);
    const url = URL.createObjectURL(blob);
    const element = document.getElementById(elementId);
    element.title = title;
    element.onload = () => {
      URL.revokeObjectURL(url);
    }
    element.src = url;
  }
</script>

참고 항목

위치 및 프로덕션 앱에 JS 대한 권장 사항에 대한 일반적인 지침은 ASP.NET Core Blazor 앱의 JavaScript 위치를 참조하세요.

다음 ShowImage2 구성 요소는

  • System.Net.Http.HttpClientMicrosoft.JSInterop.IJSRuntime에 대한 서비스를 삽입합니다.
  • 이미지를 표시하는 <img> 태그를 포함시킵니다.
  • 이미지에 대한 Stream을(를) 검색할 GetImageStreamAsync C# 메서드가 있습니다. 프로덕션 앱은 특정 사용자에 따라 이미지를 동적으로 생성하거나 스토리지에서 이미지를 검색할 수 있습니다. 다음 예제에서는 dotnet GitHub 리포지토리에 대한 .NET 아바타를 검색합니다.
  • 사용자가 단추를 선택할 때 트리거되는 SetImageAsync 메서드가 있습니다. SetImageAsync 에서는 다음 단계를 수행합니다.
    • GetImageStreamAsync에서 Stream을 검색합니다.
    • DotNetStreamReferenceStream을 래핑하면 이미지 데이터를 클라이언트에 스트리밍할 수 있습니다.
    • 클라이언트에서 데이터를 허용하는 setSource JavaScript 함수를 호출합니다.

참고 항목

서버 쪽 앱은 전용 HttpClient 서비스를 사용하여 요청을 수행하므로 서비스 등록 HttpClient 을 위해 서버 쪽 Blazor 앱의 개발자는 아무런 조치도 필요하지 않습니다. 클라이언트 쪽 앱은 프로젝트 템플릿에서 앱을 만들 때 기본 HttpClient 서비스 등록을 갖 Blazor 습니다. HttpClient 클라이언트 쪽 앱의 파일에 서비스 등록이 Program 없는 경우 다음을 추가하여 builder.Services.AddHttpClient();제공합니다. 자세한 내용은 ASP.NET Core에서 IHttpClientFactory를 사용하여 HTTP 요청 만들기를 참조하세요.

ShowImage2.razor:

@page "/show-image-2"
@inject HttpClient Http
@inject IJSRuntime JS

<PageTitle>Show Image 2</PageTitle>

<h1>Show Image Example 2</h1>

<button @onclick="SetImageAsync">
    Set Image
</button>

<div class="p-3">
    <img id="avatar" />
</div>

@code {
    private async Task<Stream> GetImageStreamAsync() => 
        await Http.GetStreamAsync("https://avatars.githubusercontent.com/u/9141961");

    private async Task SetImageAsync()
    {
        var imageStream = await GetImageStreamAsync();
        var strRef = new DotNetStreamReference(imageStream);
        await JS.InvokeVoidAsync("setSource", "avatar", strRef, "image/png", 
            ".NET GitHub avatar");
    }
}
@page "/show-image-2"
@inject HttpClient Http
@inject IJSRuntime JS

<PageTitle>Show Image 2</PageTitle>

<h1>Show Image Example 2</h1>

<button @onclick="SetImageAsync">
    Set Image
</button>

<div class="p-3">
    <img id="avatar" />
</div>

@code {
    private async Task<Stream> GetImageStreamAsync() => 
        await Http.GetStreamAsync("https://avatars.githubusercontent.com/u/9141961");

    private async Task SetImageAsync()
    {
        var imageStream = await GetImageStreamAsync();
        var strRef = new DotNetStreamReference(imageStream);
        await JS.InvokeVoidAsync("setSource", "avatar", strRef, "image/png", 
            ".NET GitHub avatar");
    }
}
@page "/show-image-2"
@inject HttpClient Http
@inject IJSRuntime JS

<h1>Show Image Example 2</h1>

<button @onclick="SetImageAsync">
    Set Image
</button>

<div class="p-3">
    <img id="avatar" />
</div>

@code {
    private async Task<Stream> GetImageStreamAsync()
    {
        return await Http.GetStreamAsync(
            "https://avatars.githubusercontent.com/u/9141961");
    }

    private async Task SetImageAsync()
    {
        var imageStream = await GetImageStreamAsync();
        var strRef = new DotNetStreamReference(imageStream);
        await JS.InvokeVoidAsync("setSource", "avatar", strRef, "image/png", 
            ".NET GitHub avatar");
    }
}
@page "/show-image-2"
@inject HttpClient Http
@inject IJSRuntime JS

<h1>Show Image Example 2</h1>

<button @onclick="SetImageAsync">
    Set Image
</button>

<div class="p-3">
    <img id="avatar" />
</div>

@code {
    private async Task<Stream> GetImageStreamAsync()
    {
        return await Http.GetStreamAsync(
            "https://avatars.githubusercontent.com/u/9141961");
    }

    private async Task SetImageAsync()
    {
        var imageStream = await GetImageStreamAsync();
        var strRef = new DotNetStreamReference(imageStream);
        await JS.InvokeVoidAsync("setSource", "avatar", strRef, "image/png", 
            ".NET GitHub avatar");
    }
}

다음 ShowFile 구성 요소는 텍스트 파일() 또는 PDF 파일(files/quote.txt)을 요소(files/quote.pdfMDN 설명서)<iframe> 로드합니다.

주의

<iframe> 다음 예제에서 요소를 사용하는 것은 안전하며 신뢰할 수 있는 원본인 앱에서 콘텐츠가 로드되므로 샌드박싱이 필요하지 않습니다.

신뢰할 수 없는 원본 또는 사용자 입력에서 콘텐츠를 로드할 때 잘못 구현된 <iframe> 요소는 보안 취약성을 초래할 위험이 있습니다.

ShowFile.razor:

@page "/show-file"
@inject NavigationManager NavigationManager
@inject HttpClient Http
@inject IJSRuntime JS

<PageTitle>Show File</PageTitle>

<div class="d-flex flex-column">
    <h1>Show File Example</h1>
    <div class="mb-4">
        <button @onclick="@(() => ShowFileAsync("files/quote.txt", 
                "General Ravon quote (text file)"))">
            Show text ('quote.txt')
        </button>
        <button @onclick="@(() => ShowFileAsync("files/quote.pdf", 
                "General Ravon quote (PDF file)"))">
            Show PDF ('quote.pdf')
        </button>
    </div>
    <iframe id="iframe" style="height: calc(100vh - 200px)" />
</div>

@code
{
    private async Task<(Stream, string?)> DownloadFileAsync(string url)
    {
        var absoluteUrl = NavigationManager.ToAbsoluteUri(url);
        Console.WriteLine($"Downloading file from {absoluteUrl}");

        var response = await Http.GetAsync(absoluteUrl);
        string? contentType = null;

        if (response.Content.Headers.TryGetValues("Content-Type", out var values))
        {
            contentType = values.FirstOrDefault();
        }

        return (await response.Content.ReadAsStreamAsync(), contentType);
    }

    private async Task ShowFileAsync(string url, string title)
    {
        var (fileStream, contentType) = await DownloadFileAsync(url);
        var strRef = new DotNetStreamReference(fileStream);
        await JS.InvokeVoidAsync("setSource", "iframe", strRef, contentType, title);
    }
}
@page "/show-file"
@inject NavigationManager NavigationManager
@inject HttpClient Http
@inject IJSRuntime JS

<PageTitle>Show File</PageTitle>

<div class="d-flex flex-column">
    <h1>Show File Example</h1>
    <div class="mb-4">
        <button @onclick="@(() => ShowFileAsync("files/quote.txt", 
                "General Ravon quote (text file)"))">
            Show text ('quote.txt')
        </button>
        <button @onclick="@(() => ShowFileAsync("files/quote.pdf", 
                "General Ravon quote (PDF file)"))">
            Show PDF ('quote.pdf')
        </button>
    </div>
    <iframe id="iframe" style="height: calc(100vh - 200px)" />
</div>

@code
{
    private async Task<(Stream, string?)> DownloadFileAsync(string url)
    {
        var absoluteUrl = NavigationManager.ToAbsoluteUri(url);
        Console.WriteLine($"Downloading file from {absoluteUrl}");

        var response = await Http.GetAsync(absoluteUrl);
        string? contentType = null;

        if (response.Content.Headers.TryGetValues("Content-Type", out var values))
        {
            contentType = values.FirstOrDefault();
        }

        return (await response.Content.ReadAsStreamAsync(), contentType);
    }

    private async Task ShowFileAsync(string url, string title)
    {
        var (fileStream, contentType) = await DownloadFileAsync(url);
        var strRef = new DotNetStreamReference(fileStream);
        await JS.InvokeVoidAsync("setSource", "iframe", strRef, contentType, title);
    }
}
@page "/show-file"
@inject NavigationManager NavigationManager
@inject HttpClient Http
@inject IJSRuntime JS

<div class="d-flex flex-column">
    <h1>Show File Example</h1>
    <div class="mb-4">
        <button @onclick="@(() => ShowFileAsync("files/quote.txt", 
                "General Ravon quote (text file)"))">
            Show text ('quote.txt')
        </button>
        <button @onclick="@(() => ShowFileAsync("files/quote.pdf", 
                "General Ravon quote (PDF file)"))">
            Show PDF ('quote.pdf')
        </button>
    </div>
    <iframe id="iframe" style="height: calc(100vh - 200px)" />
</div>

@code
{
    private async Task<(Stream, string?)> DownloadFileAsync(string url)
    {
        var absoluteUrl = NavigationManager.ToAbsoluteUri(url);
        Console.WriteLine($"Downloading file from {absoluteUrl}");

        var response = await Http.GetAsync(absoluteUrl);
        string? contentType = null;

        if (response.Content.Headers.TryGetValues("Content-Type", out var values))
        {
            contentType = values.FirstOrDefault();
        }

        return (await response.Content.ReadAsStreamAsync(), contentType);
    }

    private async Task ShowFileAsync(string url, string title)
    {
        var (fileStream, contentType) = await DownloadFileAsync(url);
        var strRef = new DotNetStreamReference(fileStream);
        await JS.InvokeVoidAsync("setSource", "iframe", strRef, contentType, title);
    }
}
@page "/show-file"
@inject NavigationManager NavigationManager
@inject HttpClient Http
@inject IJSRuntime JS

<div class="d-flex flex-column">
    <h1>Show File Example</h1>
    <div class="mb-4">
        <button @onclick="@(() => ShowFileAsync("files/quote.txt", 
                "General Ravon quote (text file)"))">
            Show text ('quote.txt')
        </button>
        <button @onclick="@(() => ShowFileAsync("files/quote.pdf", 
                "General Ravon quote (PDF file)"))">
            Show PDF ('quote.pdf')
        </button>
    </div>
    <iframe id="iframe" style="height: calc(100vh - 200px)" />
</div>

@code
{
    private async Task<(Stream, string?)> DownloadFileAsync(string url)
    {
        var absoluteUrl = NavigationManager.ToAbsoluteUri(url);
        Console.WriteLine($"Downloading file from {absoluteUrl}");

        var response = await Http.GetAsync(absoluteUrl);
        string? contentType = null;

        if (response.Content.Headers.TryGetValues("Content-Type", out var values))
        {
            contentType = values.FirstOrDefault();
        }

        return (await response.Content.ReadAsStreamAsync(), contentType);
    }

    private async Task ShowFileAsync(string url, string title)
    {
        var (fileStream, contentType) = await DownloadFileAsync(url);
        var strRef = new DotNetStreamReference(fileStream);
        await JS.InvokeVoidAsync("setSource", "iframe", strRef, contentType, title);
    }
}

추가 리소스