ASP.NET Core Blazor dosya indirmeleri

Not

Bu, bu makalenin en son sürümü değildir. Geçerli sürüm için bu makalenin .NET 8 sürümüne bakın.

Önemli

Bu bilgiler, ticari olarak piyasaya sürülmeden önce önemli ölçüde değiştirilebilen bir yayın öncesi ürünle ilgilidir. Burada verilen bilgilerle ilgili olarak Microsoft açık veya zımni hiçbir garanti vermez.

Geçerli sürüm için bu makalenin .NET 8 sürümüne bakın.

Bu makalede, uygulamalardaki Blazor dosyaların nasıl indirilmesi açıklanır.

Dosya indirme işlemleri

Dosyalar uygulamanın kendi statik varlıklarından veya başka bir konumdan indirilebilir:

  • ASP.NET Core uygulamaları, sunucu tarafı uygulamaların istemcilerine dosya sunmak için Statik Dosya Ara Yazılımı kullanır.
  • Bu makaledeki kılavuz, İçerik Teslim Ağları (CDN'ler) gibi .NET kullanmayan diğer dosya sunucusu türleri için de geçerlidir.

Bu makale, bir dosyanın bir tarayıcı tarafından açılmaması ancak istemciye indirilip kaydedilmesi gereken aşağıdaki senaryolara yönelik yaklaşımları kapsar:

  • İstemcideki ham ikili veri arabelleğine dosya içeriği akışı yapma: Bu yaklaşım genellikle nispeten küçük dosyalar (< 250 MB) için kullanılır.
  • Akışı olmayan bir URL aracılığıyla dosya indirme: Genellikle, bu yaklaşım nispeten büyük dosyalar (> 250 MB) için kullanılır.

Uygulamadan farklı bir kaynaktan dosya indirirken Çıkış Noktaları Arası Kaynak Paylaşımı (CORS) konusunda dikkat edilmesi gerekenler geçerlidir. Daha fazla bilgi için Çıkış Noktaları Arası Kaynak Paylaşımı (CORS) bölümüne bakın.

Güvenlik konuları

Kullanıcılara bir sunucudan dosya indirme olanağı sağlarken dikkatli olun. Saldırganlar Hizmet Reddi (DoS) saldırıları, API'den yararlanma saldırıları yürütebilir veya ağların ve sunucuların güvenliğini başka yollarla aşmaya çalışabilir.

Başarılı bir saldırı olasılığını azaltan güvenlik adımları şunlardır:

  • Dosyaları, tercihen sistem dışı bir sürücüden sunucudaki ayrılmış bir dosya indirme alanından indirin. Ayrılmış bir konum kullanmak, indirilebilir dosyalara güvenlik kısıtlamaları uygulamayı kolaylaştırır. Dosya indirme alanında yürütme izinlerini devre dışı bırakın.
  • İstemci tarafı güvenlik denetimleri, kötü amaçlı kullanıcılar tarafından kolayca aşılır. Her zaman sunucuda da istemci tarafı güvenlik denetimleri gerçekleştirin.
  • Kullanıcılardan veya diğer güvenilmeyen kaynaklardan dosya almayın ve ardından dosyalar üzerinde güvenlik denetimleri gerçekleştirmeden dosyaları anında indirilmeye hazır hale getirin. Daha fazla bilgi için bkz . ASP.NET Core'da dosyaları karşıya yükleme.

Akıştan indirme

Bu bölüm genellikle boyutu 250 MB'a kadar olan dosyalar için geçerlidir.

Görece küçük dosyaları (<250 MB) indirmek için önerilen yaklaşım, javaScript (JS) birlikte çalışma özelliğiyle istemcideki ham ikili veri arabelleğine dosya içeriği akışı yapmaktır.

Uyarı

Bu bölümdeki yaklaşım dosyanın içeriğini olarak JS ArrayBufferokur. Bu yaklaşım, dosyanın tamamını istemcinin belleğine yükler ve bu da performansı bozabilir. Görece büyük dosyaları (>= 250 MB) indirmek için URL'den indirme bölümündeki yönergeleri takip etmenizi öneririz.

Aşağıdaki downloadFileFromStreamJS işlev:

  • Sağlanan akışı bir ArrayBufferiçine okur.
  • kaydırmak ArrayBufferiçin bir Blob oluşturur.
  • Dosyanın indirme adresi olarak hizmet vermek için bir nesne URL'si oluşturur.
  • Bir HTMLAnchorElement (<a> öğesi oluşturur.
  • İndirme için dosyanın adını (fileName) ve URL'sini (url) atar.
  • Anchor öğesinde bir click olay tetikleyerek indirmeyi tetikler.
  • Tutturucu öğesini kaldırır.
  • çağırarak URL.revokeObjectURLnesne URL'sini (url) iptal eder. Bu, istemcide belleğin sızmadığından emin olmak için önemli bir adımdır.
<script>
  window.downloadFileFromStream = async (fileName, contentStreamReference) => {
    const arrayBuffer = await contentStreamReference.arrayBuffer();
    const blob = new Blob([arrayBuffer]);
    const url = URL.createObjectURL(blob);
    const anchorElement = document.createElement('a');
    anchorElement.href = url;
    anchorElement.download = fileName ?? '';
    anchorElement.click();
    anchorElement.remove();
    URL.revokeObjectURL(url);
  }
</script>

Not

Konum hakkında genel yönergeler JS ve üretim uygulamalarına yönelik önerilerimiz için bkz . ASP.NET Core Blazor uygulamalarında JavaScript konumu.

Aşağıdaki bileşen:

  • Dosyanın istemciye verimli bir şekilde aktarılmasını sağlamak için yerel bayt akışlı birlikte çalışma kullanır.
  • İstemcilere indirilen dosya için almak Stream için adlı GetFileStream bir yöntemi vardır. Alternatif yaklaşımlar arasında depolama alanından dosya alma veya C# kodunda dinamik olarak dosya oluşturma yer alır. Bu gösterim için uygulama, yeni bir bayt dizisinden (new byte[] ) rastgele verilerden oluşan 50 KB'lık bir dosya oluşturur. Baytlar, örneğin dinamik olarak oluşturulan ikili dosyası olarak hizmet vermek için ile MemoryStream sarmalanmıştır.
  • Yöntemi DownloadFileFromStream :
    • 'den GetFileStreamöğesini Stream alır.
    • Dosya kullanıcının makinesine kaydedildiğinde bir dosya adı belirtir. Aşağıdaki örnek dosyasını quote.txtadlandırın.
    • dosya verilerinin Stream istemciye akışına izin veren bir DotNetStreamReferenceiçinde sarmalar.
    • İstemcideki downloadFileFromStreamJS verileri kabul etmek için işlevini çağırır.

FileDownload1.razor:

@page "/file-download-1"
@using System.IO
@inject IJSRuntime JS

<PageTitle>File Download 1</PageTitle>

<h1>File Download Example 1</h1>

<button @onclick="DownloadFileFromStream">
    Download File From Stream
</button>

@code {
    private Stream GetFileStream()
    {
        var randomBinaryData = new byte[50 * 1024];
        var fileStream = new MemoryStream(randomBinaryData);

        return fileStream;
    }

    private async Task DownloadFileFromStream()
    {
        var fileStream = GetFileStream();
        var fileName = "log.bin";

        using var streamRef = new DotNetStreamReference(stream: fileStream);

        await JS.InvokeVoidAsync("downloadFileFromStream", fileName, streamRef);
    }
}
@page "/file-download-1"
@using System.IO
@inject IJSRuntime JS

<h1>File Download Example</h1>

<button @onclick="DownloadFileFromStream">
    Download File From Stream
</button>

@code {
    private Stream GetFileStream()
    {
        var randomBinaryData = new byte[50 * 1024];
        var fileStream = new MemoryStream(randomBinaryData);

        return fileStream;
    }

    private async Task DownloadFileFromStream()
    {
        var fileStream = GetFileStream();
        var fileName = "log.bin";

        using var streamRef = new DotNetStreamReference(stream: fileStream);

        await JS.InvokeVoidAsync("downloadFileFromStream", fileName, streamRef);
    }
}
@page "/file-download-1"
@using System.IO
@inject IJSRuntime JS

<h1>File Download Example</h1>

<button @onclick="DownloadFileFromStream">
    Download File From Stream
</button>

@code {
    private Stream GetFileStream()
    {
        var randomBinaryData = new byte[50 * 1024];
        var fileStream = new MemoryStream(randomBinaryData);

        return fileStream;
    }

    private async Task DownloadFileFromStream()
    {
        var fileStream = GetFileStream();
        var fileName = "log.bin";

        using var streamRef = new DotNetStreamReference(stream: fileStream);

        await JS.InvokeVoidAsync("downloadFileFromStream", fileName, streamRef);
    }
}

Sunucu tarafı uygulamasında fiziksel bir dosya için döndürmesi Stream gereken bir bileşen için, aşağıdaki örnekte gösterildiği gibi bileşen öğesini çağırabilir File.OpenRead:

private Stream GetFileStream()
{
    return File.OpenRead(@"{PATH}");
}

Yukarıdaki örnekte, {PATH} yer tutucu dosyanın yoludur. Ön @ ek, dizenin bir Windows işletim sistemi yolunda ters eğik çizgi (\) ve yoldaki tek tırnak için katıştırılmış çift tırnak ("") kullanımına izin veren düz bir dize değişmez değeri olduğunu gösterir. Alternatif olarak, dize değişmez değerlerinden (@) kaçının ve aşağıdaki yaklaşımlardan birini kullanın:

  • Kaçış ters eğik çizgilerini (\\) ve tırnakları (\") kullanın.
  • ASP.NET Core uygulamalarında platformlar arasında desteklenen yolda eğik çizgi (/) ve kaçış tırnak işaretleri (\") kullanın.

URL'den indirme

Bu bölüm, genellikle 250 MB veya daha büyük nispeten büyük dosyalar için geçerlidir.

Bu bölümdeki örnekte, uygulamanın web kökünde (wwwroot klasöründe) quote.txtadlı bir klasöre yerleştirilen adlı files bir indirme dosyası kullanılır. Klasörün kullanımı files yalnızca gösterim amaçlıdır. İndirilebilir dosyaları, dosyaları doğrudan klasörden sunma dahil olmak üzere, tercih ettiğiniz web kökündeki (wwwroot klasör) herhangi bir klasör düzeninde wwwroot düzenleyebilirsiniz.

wwwroot/files/quote.txt:

When victory is ours, we'll wipe every trace of the Thals and their city from the face of this land. We will avenge the deaths of all Kaleds who've fallen in the cause of right and justice and build a peace which will be a monument to their sacrifice. Our battle cry will be "Total extermination of the Thals!"

- General Ravon (Guy Siner, http://guysiner.com/)
  Dr. Who: Genesis of the Daleks (https://www.bbc.co.uk/programmes/p00pq2gc)
  ©1975 BBC (https://www.bbc.co.uk/)
When victory is ours, we'll wipe every trace of the Thals and their city from the face of this land. We will avenge the deaths of all Kaleds who've fallen in the cause of right and justice and build a peace which will be a monument to their sacrifice. Our battle cry will be "Total extermination of the Thals!"

- General Ravon (Guy Siner, http://guysiner.com/)
  Dr. Who: Genesis of the Daleks (https://www.bbc.co.uk/programmes/p00pq2gc)
  ©1975 BBC (https://www.bbc.co.uk/)
When victory is ours, we'll wipe every trace of the Thals and their city from the face of this land. We will avenge the deaths of all Kaleds who've fallen in the cause of right and justice and build a peace which will be a monument to their sacrifice. Our battle cry will be "Total extermination of the Thals!"

- General Ravon (Guy Siner, http://guysiner.com/)
  Dr. Who: Genesis of the Daleks (https://www.bbc.co.uk/programmes/p00pq2gc)
  ©1975 BBC (https://www.bbc.co.uk/)

Aşağıdaki triggerFileDownloadJS işlev:

  • Bir HTMLAnchorElement (<a> öğesi oluşturur.
  • İndirme için dosyanın adını (fileName) ve URL'sini (url) atar.
  • Anchor öğesinde bir click olay tetikleyerek indirmeyi tetikler.
  • Tutturucu öğesini kaldırır.
<script>
  window.triggerFileDownload = (fileName, url) => {
    const anchorElement = document.createElement('a');
    anchorElement.href = url;
    anchorElement.download = fileName ?? '';
    anchorElement.click();
    anchorElement.remove();
  }
</script>

Not

Konum hakkında genel yönergeler JS ve üretim uygulamalarına yönelik önerilerimiz için bkz . ASP.NET Core Blazor uygulamalarında JavaScript konumu.

Aşağıdaki örnek bileşen, dosyayı uygulamanın kullandığı kaynaktan indirir. Dosya indirme işlemi farklı bir kaynaktan yapılmaya çalışılırsa Çıkış Noktaları Arası Kaynak Paylaşımı'nı (CORS) yapılandırın. Daha fazla bilgi için Çıkış Noktaları Arası Kaynak Paylaşımı (CORS) bölümüne bakın.

Aşağıdaki örnekteki bağlantı noktasını ortamınızın localhost geliştirme bağlantı noktasıyla eşleşecek şekilde değiştirin.

FileDownload2.razor:

@page "/file-download-2"
@inject IJSRuntime JS

<PageTitle>File Download 2</PageTitle>

<h1>File Download Example 2</h1>

<button @onclick="DownloadFileFromURL">
    Download File From URL
</button>

@code {
    private async Task DownloadFileFromURL()
    {
        var fileName = "quote.txt";
        var fileURL = "/files/quote.txt";
        await JS.InvokeVoidAsync("triggerFileDownload", fileName, fileURL);
    }
}
@page "/file-download-2"
@inject IJSRuntime JS

<h1>File Download Example 2</h1>

<button @onclick="DownloadFileFromURL">
    Download File From URL
</button>

@code {
    private async Task DownloadFileFromURL()
    {
        var fileName = "quote.txt";
        var fileURL = "https://localhost:5001/files/quote.txt";
        await JS.InvokeVoidAsync("triggerFileDownload", fileName, fileURL);
    }
}
@page "/file-download-2"
@inject IJSRuntime JS

<h1>File Download Example 2</h1>

<button @onclick="DownloadFileFromURL">
    Download File From URL
</button>

@code {
    private async Task DownloadFileFromURL()
    {
        var fileName = "quote.txt";
        var fileURL = "https://localhost:5001/files/quote.txt";
        await JS.InvokeVoidAsync("triggerFileDownload", fileName, fileURL);
    }
}

Çıkış Noktaları Arası Kaynak Paylaşma (CORS)

Uygulamayla aynı kaynağa sahip olmayan dosyalar için Çıkış Noktaları Arası Kaynak Paylaşımı'nı (CORS) etkinleştirmeye yönelik başka adımlar atılmadan, dosyaların indirilmesi tarayıcı tarafından yapılan CORS denetimlerini geçemez.

ASP.NET Core uygulamalarıyla CORS ve indirilme amacıyla dosya barındıran diğer Microsoft ürün ve hizmetleri hakkında daha fazla bilgi için aşağıdaki kaynaklara bakın:

Ek kaynaklar