참고 항목
이 문서의 최신 버전은 아닙니다. 현재 릴리스는 이 문서의 .NET 9 버전을 참조 하세요.
Important
이 정보는 상업적으로 출시되기 전에 실질적으로 수정될 수 있는 시험판 제품과 관련이 있습니다. Microsoft는 여기에 제공된 정보에 대해 어떠한 명시적, 또는 묵시적인 보증을 하지 않습니다.
현재 릴리스는 이 문서의 .NET 9 버전을 참조 하세요.
이 문서에서는 Blazor Hybrid 앱에서 정적 자산 파일을 사용하는 방법을 설명합니다.
Blazor Hybrid 앱에서 정적 파일은 다음 방법을 사용하여 Razor 구성 요소가 액세스하는 앱 리소스입니다.
정적 자산이 Razor 구성 요소에서만 사용되는 경우 Blazor WebAssembly 및 Blazor Server 앱과 비슷한 방식으로 웹 루트(wwwroot
폴더)에서 정적 자산을 사용할 수 있습니다. 자세한 내용은 Razor 구성 요소로 제한된 정적 자산 섹션을 참조하세요.
.NET MAUI
.NET MAUI 앱에서 MauiAsset
빌드 작업 및 .NET MAUI file system helpers를 사용하는 원시 자산은 정적 자산에 사용됩니다.
참고 항목
파일 선택, 기본 설정 저장 및 보안 스토리지 사용과 같은 기능을 위해 지원되는 모든 플랫폼에서 디바이스의 스토리지와 함께 작동하는 인터페이스, 클래스 및 지원 형식이 네임스페이스에 있습니다 Microsoft.Maui.Storage . 네임스페이스는 MAUI Blazor Hybrid 앱 전체에서 사용할 수 있으므로 클래스 파일에 문을 지정하거나 @using
Razor 네임스페이스에 대한 구성 요소의 Razor 지시문을 지정할 using
필요가 없습니다.
원시 자산을 앱의 Resources/Raw
폴더에 배치합니다. 이 섹션의 예제에서는 정적 텍스트 파일을 사용합니다.
Resources/Raw/Data.txt
:
This is text from a static text file resource.
다음 Razor 구성 요소는
- OpenAppPackageFileAsync를 호출하여 리소스에 대한 Stream을 가져옵니다.
- StreamReader를 사용하여 Stream을 읽습니다.
- StreamReader.ReadToEndAsync를 호출하여 파일을 읽습니다.
Pages/StaticAssetExample.razor
:
@page "/static-asset-example"
@using System.IO
@using Microsoft.Extensions.Logging
@inject ILogger<StaticAssetExample> Logger
<h1>Static Asset Example</h1>
<p>@dataResourceText</p>
@code {
public string dataResourceText = "Loading resource ...";
protected override async Task OnInitializedAsync()
{
try
{
using var stream =
await FileSystem.OpenAppPackageFileAsync("Data.txt");
using var reader = new StreamReader(stream);
dataResourceText = await reader.ReadToEndAsync();
}
catch (FileNotFoundException ex)
{
dataResourceText = "Data file not found.";
Logger.LogError(ex, "'Resource/Raw/Data.txt' not found.");
}
}
}
자세한 내용은 다음 리소스를 참조하세요.
WPF
자산을 앱의 폴더(일반적으로 프로젝트의 루트(예: Resources
폴더))에 배치합니다. 이 섹션의 예제에서는 정적 텍스트 파일을 사용합니다.
Resources/Data.txt
:
This is text from a static text file resource.
앱에 Properties
폴더가 없는 경우 앱의 루트에 Properties
폴더를 만듭니다.
Properties
폴더에 리소스 파일(Resources.resx
)이 없는 경우 추가>새 항목 바로 가기 메뉴 명령을 사용하여 솔루션 탐색기에 파일을 만듭니다.
Resource.resx
파일을 두 번 클릭합니다.
드롭다운 목록에서 문자열>파일을 선택합니다.
리소스 추가>기존 파일 추가를 선택합니다. Visual Studio에 파일 편집을 확인하라는 메시지가 표시되면 예를 선택합니다. Resources
폴더로 이동하여 Data.txt
파일을 선택한 다음 열기를 선택합니다.
다음 예제 구성 요소에서 ResourceManager.GetString은 표시할 문자열 리소스의 텍스트를 가져옵니다.
Warning
신뢰할 수 없는 데이터와 함께 ResourceManager 메서드를 사용하지 마세요.
StaticAssetExample.razor
:
@page "/static-asset-example"
@using System.Resources
<h1>Static Asset Example</h1>
<p>@dataResourceText</p>
@code {
public string dataResourceText = "Loading resource ...";
protected override void OnInitialized()
{
var resources =
new ResourceManager(typeof(WpfBlazor.Properties.Resources));
dataResourceText = resources.GetString("Data") ?? "'Data' not found.";
}
}
Windows Forms
자산을 앱의 폴더(일반적으로 프로젝트의 루트(예: Resources
폴더))에 배치합니다. 이 섹션의 예제에서는 정적 텍스트 파일을 사용합니다.
Resources/Data.txt
:
This is text from a static text file resource.
솔루션 탐색기에서 Form1
과 연결된 파일을 검사합니다. Form1
에 리소스 파일(.resx
)이 없는 경우 추가>새 항목 바로 가기 메뉴 명령을 사용하여 Form1.resx
파일을 추가합니다.
Form1.resx
파일을 두 번 클릭합니다.
드롭다운 목록에서 문자열>파일을 선택합니다.
리소스 추가>기존 파일 추가를 선택합니다. Visual Studio에 파일 편집을 확인하라는 메시지가 표시되면 예를 선택합니다. Resources
폴더로 이동하여 Data.txt
파일을 선택한 다음 열기를 선택합니다.
다음 예제 구성 요소에서:
WinFormsBlazor
은 앱의 어셈블리 이름입니다. ResourceManager의 기본 이름은Form1
의 어셈블리 이름(WinFormsBlazor.Form1
)으로 설정됩니다.- ResourceManager.GetString은 표시할 문자열 리소스의 텍스트를 가져옵니다.
Warning
신뢰할 수 없는 데이터와 함께 ResourceManager 메서드를 사용하지 마세요.
StaticAssetExample.razor
:
@page "/static-asset-example"
@using System.Resources
<h1>Static Asset Example</h1>
<p>@dataResourceText</p>
@code {
public string dataResourceText = "Loading resource ...";
protected override async Task OnInitializedAsync()
{
var resources =
new ResourceManager("WinFormsBlazor.Form1", this.GetType().Assembly);
dataResourceText = resources.GetString("Data") ?? "'Data' not found.";
}
}
Razor 구성 요소로 제한된 정적 자산
BlazorWebView
컨트롤에는 구성된 호스트 파일(HostPage), 일반적으로 wwwroot/index.html
이 있습니다. HostPage 경로는 프로젝트에 상대적입니다. BlazorWebView
에서 참조되는 모든 정적 웹 자산(스크립트, CSS 파일, 이미지 및 기타 파일)은 구성된 HostPage를 기준으로 합니다.
RCL(Razor 클래스 라이브러리)의 정적 웹 자산은 특수 경로 _content/{PACKAGE ID}/{PATH AND FILE NAME}
를 사용합니다. {PACKAGE ID}
자리 표시자는 라이브러리의 패키지 ID입니다. <PackageId>
가 프로젝트 파일에 지정되지 않은 경우 패키지 ID는 기본적으로 프로젝트의 어셈블리 이름으로 설정됩니다. {PATH AND FILE NAME}
자리 표시자는 wwwroot
아래의 경로 및 파일 이름입니다. 이러한 경로는 실제로 다른 패키지 또는 프로젝트에서 들어오지만 앱 wwwroot
폴더의 논리적 하위 경로입니다. 구성 요소별 CSS 스타일 번들도 wwwroot
폴더의 루트에 빌드됩니다.
HostPage의 웹 루트는 사용할 수 있는 정적 자산의 하위 집합을 결정합니다.
wwwroot/index.html
(권장): 하위 폴더(예: 사용 가능)를 포함하여 앱 폴더의wwwroot
모든 자산을 사용할/image.png
수 있습니다(예:wwwroot/image.png
wwwroot/subfolder/image.png
다음에서/subfolder/image.png
사용 가능). 하위 폴더(예:_content/{PACKAGE ID}/subfolder/image.png
경로에서wwwroot/subfolder/image.png
사용 가능) RCLwwwroot
폴더의 RCL 정적 자산을 사용할 수 있습니다(예:_content/{PACKAGE ID}/image.png
경로에서wwwroot/image.png
사용 가능).wwwroot/{PATH}/index.html
: 앱의wwwroot/{PATH}
폴더에 있는 모든 자산은 앱 웹 루트 상대 경로를 사용하여 사용할 수 있습니다. RCL 정적 자산은wwwroot/{PATH}
지원되는 상대 경로가 아닌 등 존재하지 않는 이론적 위치에../../_content/{PACKAGE ID}/{PATH}
있기 때문입니다.wwwroot/_content/{PACKAGE ID}/index.html
: RCL의wwwroot/{PATH}
폴더에 있는 모든 자산은 RCL 웹 루트 상대 경로를 사용하여 사용할 수 있습니다. 앱의 정적 자산wwwroot/{PATH}
은 지원되는 상대 경로가 아닌 등 존재하지 않는 이론적 위치에../../{PATH}
있기 때문이 아닙니다.
대부분의 앱에서는 앱, RCL, 앱 및 RCL의 하위 폴더를 통해 정적 자산을 제공하는 가장 큰 유연성을 제공하는 앱 wwwroot
폴더의 루트에 HostPage를 배치 하는 것이 좋습니다.
다음 예제에서는 wwwroot
폴더에 HostPage 루트가 있는 앱의 웹 루트(wwwroot
폴더)에서 정적 자산을 참조하는 방법을 보여줍니다.
wwwroot/data.txt
:
This is text from a static text file resource.
wwwroot/scripts.js
:
export function showPrompt(message) {
return prompt(message, 'Type anything here');
}
다음 Jeep® 이미지는 이 섹션의 예제에서도 사용됩니다. 다음 이미지를 마우스 오른쪽 단추로 클릭하여 로컬 테스트 앱에서 사용할 수 있도록 로컬로 저장할 수 있습니다.
wwwroot/jeep-yj.png
:
Razor 구성 요소에서:
- 정적 텍스트 파일 내용은 다음 기술을 사용하여 읽을 수 있습니다.
- .NET MAUI: .NET MAUI file system helpers (OpenAppPackageFileAsync)
- WPF 및 Windows Forms: StreamReader.ReadToEndAsync
- JavaScript 파일은
./
경로를 사용하는wwwroot
의 논리적 하위 경로에서 사용할 수 있습니다. - 이미지는 이미지 태그(
<img>
)의 원본 특성(src
)일 수 있습니다.
StaticAssetExample2.razor
:
@page "/static-asset-example-2"
@using Microsoft.Extensions.Logging
@implements IAsyncDisposable
@inject IJSRuntime JS
@inject ILogger<StaticAssetExample2> Logger
<h1>Static Asset Example 2</h1>
<h2>Read a file</h2>
<p>@dataResourceText</p>
<h2>Call JavaScript</h2>
<p>
<button @onclick="TriggerPrompt">Trigger browser window prompt</button>
</p>
<p>@result</p>
<h2>Show an image</h2>
<p><img alt="1991 Jeep YJ" src="/jeep-yj.png" /></p>
<p>
<em>Jeep</em> and <em>Jeep YJ</em> are registered trademarks of
<a href="https://www.stellantis.com">FCA US LLC (Stellantis NV)</a>.
</p>
@code {
private string dataResourceText = "Loading resource ...";
private IJSObjectReference? module;
private string result;
protected override async Task OnInitializedAsync()
{
try
{
dataResourceText = await ReadData();
}
catch (FileNotFoundException ex)
{
dataResourceText = "Data file not found.";
Logger.LogError(ex, "'wwwroot/data.txt' not found.");
}
}
protected override async Task OnAfterRenderAsync(bool firstRender)
{
if (firstRender)
{
module = await JS.InvokeAsync<IJSObjectReference>("import",
"./scripts.js");
}
}
private async Task TriggerPrompt()
{
result = await Prompt("Provide some text");
}
public async ValueTask<string> Prompt(string message) =>
module is not null ?
await module.InvokeAsync<string>("showPrompt", message) : null;
async ValueTask IAsyncDisposable.DisposeAsync()
{
if (module is not null)
{
try
{
await module.DisposeAsync();
}
catch (JSDisconnectedException)
{
}
}
}
}
.NET MAUI 앱에서 이전 구성 요소의 @code
블록에 다음 ReadData
메서드를 추가합니다.
private async Task<string> ReadData()
{
using var stream = await FileSystem.OpenAppPackageFileAsync("wwwroot/data.txt");
using var reader = new StreamReader(stream);
return await reader.ReadToEndAsync();
}
WPF 및Windows Forms 앱에서 이전 구성 요소의 @code
블록에 다음 ReadData
메서드를 추가합니다.
private async Task<string> ReadData()
{
using var reader = new StreamReader("wwwroot/data.txt");
return await reader.ReadToEndAsync();
}
배치된 JavaScript 파일은 wwwroot
의 논리적 하위 경로에서도 액세스할 수 있습니다. wwwroot/scripts.js
의 showPrompt
함수에 대해 앞에서 설명한 스크립트를 사용하는 대신, StaticAssetExample2
구성 요소에 대해 다음과 같은 배치된 JavaScript 파일도 함수를 사용할 수 있게 합니다.
Pages/StaticAssetExample2.razor.js
:
export function showPrompt(message) {
return prompt(message, 'Type anything here');
}
StaticAssetExample2
구성 요소에서 모듈 개체 참조를 수정하여 배치된 JavaScript 파일 경로(./Pages/StaticAssetExample2.razor.js
)를 사용합니다.
module = await JS.InvokeAsync<IJSObjectReference>("import",
"./Pages/StaticAssetExample2.razor.js");
상표
Jeep 및 Jeep YJ는 FCA US LLC(Stellantis NV)의 상표로 등록되어 있습니다.
추가 리소스
ASP.NET Core