Sdílet prostřednictvím


stahování souborů ASP.NET Core Blazor

Poznámka:

Toto není nejnovější verze tohoto článku. Aktuální verzi najdete v tomto článku ve verzi .NET 9.

Upozorňující

Tato verze ASP.NET Core se už nepodporuje. Další informace najdete v tématu .NET a .NET Core Zásady podpory. Aktuální verzi najdete ve verzi .NET 8 tohoto článku.

Důležité

Tyto informace se týkají předběžného vydání produktu, který může být podstatně změněn před komerčním vydáním. Microsoft neposkytuje žádné záruky, výslovné ani předpokládané, týkající se zde uváděných informací.

Aktuální verzi najdete v tomto článku ve verzi .NET 9.

Tento článek vysvětluje, jak stahovat soubory v Blazor aplikacích.

Stažení souborů

Tento článek popisuje přístupy pro následující scénáře, kdy by se soubor neměl otevírat v prohlížeči, ale stahovat a ukládat do klienta:

Při stahování souborů z jiného původu než aplikace platí důležité informace o sdílení prostředků mezi zdroji (CORS). Další informace najdete v části Sdílení prostředků mezi zdroji (CORS).

Bezpečnostní aspekty

Při poskytování uživatelů s možností stahovat soubory ze serveru buďte opatrní. Cyberattackers může spouštět útoky DoS (Denial of Service), útoky na zneužití rozhraní API nebo se pokoušet o ohrožení sítí a serverů jinými způsoby.

Bezpečnostní kroky, které snižují pravděpodobnost úspěšného útoku:

  • Stáhněte si soubory z vyhrazené oblasti pro stahování souborů na serveru, nejlépe z nesystémové jednotky. Použití vyhrazeného umístění usnadňuje ukládání bezpečnostních omezení pro soubory ke stažení. Zakažte oprávnění ke spuštění v oblasti pro stahování souborů.
  • Kontroly zabezpečení na straně klienta se dají snadno obejít škodlivými uživateli. Na serveru vždy proveďte také kontroly zabezpečení na straně klienta.
  • Nepřijmete soubory od uživatelů nebo jiných nedůvěryhodných zdrojů a pak soubory zpřístupníte k okamžitému stažení, aniž byste u souborů provedli kontroly zabezpečení. Další informace najdete v tématu Nahrání souborů v ASP.NET Core.

Stažení ze streamu

Tato část se týká souborů, které mají obvykle velikost až 250 MB.

Doporučeným přístupem ke stažení relativně malých souborů (<250 MB) je streamování obsahu souboru do nezpracované binární vyrovnávací paměti dat v klientovi pomocí interoperability JavaScriptu (JS). Tento přístup je účinný pro komponenty, které přijímají interaktivní režim vykreslování, ale ne komponenty, které přijímají statické vykreslování na straně serveru (statické SSR).

Doporučeným přístupem ke stažení relativně malých souborů (<250 MB) je streamování obsahu souboru do nezpracované binární vyrovnávací paměti dat v klientovi pomocí interoperability JavaScriptu (JS).

Upozorňující

Přístup v této části přečte obsah souboru do JS ArrayBuffersouboru . Tento přístup načte celý soubor do paměti klienta, což může ovlivnit výkon. Pokud chcete stáhnout relativně velké soubory (>= 250 MB), doporučujeme postupovat podle pokynů v části Stažení z adresy URL .

downloadFileFromStreamJS Následující funkce:

  • Načte zadaný datový proud do objektu ArrayBuffer.
  • Blob Vytvoří pro zabalení objektu ArrayBuffer.
  • Vytvoří adresu URL objektu, která bude sloužit jako adresa pro stažení souboru.
  • Vytvoří ( HTMLAnchorElement<a> element).
  • Přiřadí název souboru () a adresu URL (fileNameurl) ke stažení.
  • Aktivuje stahování spuštěním click události na elementu ukotvení.
  • Odebere prvek ukotvení.
  • Odvolá adresu URLurl objektu voláním URL.revokeObjectURL. Jedná se o důležitý krok k zajištění nevracení paměti v klientovi.
<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>

Poznámka:

Obecné pokyny k JS umístění a doporučení pro produkční aplikace najdete v tématu o umístění JavaScriptu v aplikacích ASP.NET CoreBlazor.

Následující komponenta:

  • Používá nativní interoperabilitu bajtů streamování k zajištění efektivního přenosu souboru do klienta.
  • Má metodu pojmenovanou GetFileStream Stream k načtení souboru, který se stáhne do klientů. Mezi alternativní přístupy patří načtení souboru z úložiště nebo dynamické generování souboru v kódu jazyka C#. Pro tuto ukázku aplikace vytvoří soubor 50 kB náhodných dat z nového bajtového pole (new byte[]). Bajty jsou zabalené jako MemoryStream dynamicky vygenerovaný binární soubor příkladu.
  • Metoda DownloadFileFromStream :
    • Načte Stream z GetFileStream.
    • Určuje název souboru, když je soubor uložen na počítači uživatele. Následující příklad pojmenuje soubor quote.txt.
    • Zabalí soubor do objektu Stream DotNetStreamReference, který umožňuje streamování dat souboru do klienta.
    • downloadFileFromStreamJS Vyvolá funkci pro přijetí dat v klientovi.

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

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

Pro komponentu v aplikaci na straně serveru, která musí vrátit Stream pro fyzický soubor, může komponenta volat File.OpenRead, jak ukazuje následující příklad:

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

V předchozím příkladu {PATH} je zástupný symbol cestou k souboru. Předpona @ označuje, že řetězec je doslovný řetězcový literál, který umožňuje použití zpětných lomítek (\) v cestě operačního systému Windows a vložené dvojité uvozovky ("") pro jednu uvozovku v cestě. Případně se vyhněte řetězcovém literálu (@) a použijte některý z následujících přístupů:

  • Použijte uvozovky (\\) a uvozovky (\").
  • Použijte lomítka (/) v cestě, které jsou podporovány napříč platformami v aplikacích ASP.NET Core a uvozovky (\").

Stažení z adresy URL

Tato část se týká souborů, které jsou relativně velké, obvykle 250 MB nebo větší.

Doporučený postup pro stahování relativně velkých souborů (>= 250 MB) s interaktivně vykreslenými komponentami nebo soubory libovolné velikosti pro staticky vykreslené komponenty je použít JS k aktivaci elementu ukotvení s názvem a adresou URL souboru.

Doporučeným přístupem ke stažení relativně velkých souborů (>= 250 MB) je použití JS k aktivaci elementu ukotvení s názvem a adresou URL souboru.

Příklad v této části používá soubor ke stažení s názvem quote.txt, který se umístí do složky pojmenované files ve webovém kořenovém adresáři aplikace (wwwroot složce). Použití files složky je pouze pro demonstrační účely. Soubory ke stažení můžete uspořádat v libovolném rozložení složek v kořenovém adresáři webu (wwwroot složce), které chcete, včetně poskytování souborů přímo ze wwwroot složky.

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/p00vd5g2)
  Copyright 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/p00vd5g2)
  Copyright 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/p00vd5g2)
  Copyright 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/p00vd5g2)
  Copyright 1975 BBC (https://www.bbc.co.uk/)

triggerFileDownloadJS Následující funkce:

  • Vytvoří ( HTMLAnchorElement<a> element).
  • Přiřadí název souboru () a adresu URL (fileNameurl) ke stažení.
  • Aktivuje stahování spuštěním click události na elementu ukotvení.
  • Odebere prvek ukotvení.
<script>
  window.triggerFileDownload = (fileName, url) => {
    const anchorElement = document.createElement('a');
    anchorElement.href = url;
    anchorElement.download = fileName ?? '';
    anchorElement.click();
    anchorElement.remove();
  }
</script>

Poznámka:

Obecné pokyny k JS umístění a doporučení pro produkční aplikace najdete v tématu o umístění JavaScriptu v aplikacích ASP.NET CoreBlazor.

Následující ukázková komponenta stáhne soubor ze stejného původu, který aplikace používá. Pokud se o stažení souboru pokusíte z jiného zdroje, nakonfigurujte sdílení prostředků mezi zdroji (CORS). Další informace najdete v části Sdílení prostředků mezi zdroji (CORS).

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

U interaktivních komponent tlačítko v předchozím příkladu volá obslužnou rutinu DownloadFileFromURL pro vyvolání funkce triggerFileDownloadJavaScriptu (JS).

Pokud komponenta přijímá statické vykreslování na straně serveru (statické SSR), přidejte obslužnou rutinu události pro tlačítko (addEventListener(dokumentace MDN)) k volání triggerFileDownload podle pokynů v ASP.NET Core Blazor JavaScriptu se statickým vykreslováním na straně serveru (statická SSR).

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

U interaktivních komponent tlačítko v předchozím příkladu volá obslužnou rutinu DownloadFileFromURL pro vyvolání funkce triggerFileDownloadJavaScriptu (JS).

Pokud komponenta přijímá statické vykreslování na straně serveru (statické SSR), přidejte obslužnou rutinu události pro tlačítko (addEventListener(dokumentace MDN)) k volání triggerFileDownload podle pokynů v ASP.NET Core Blazor JavaScriptu se statickým vykreslováním na straně serveru (statická SSR).

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

Změňte port v předchozím příkladu tak, aby odpovídal vývojovému portu místního hostitele vašeho prostředí.

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

Změňte port v předchozím příkladu tak, aby odpovídal vývojovému portu místního hostitele vašeho prostředí.

Cross-Origin Resource Sharing (CORS)

Bez dalších kroků povolení sdílení prostředků mezi zdroji (CORS) pro soubory, které nemají stejný zdroj jako aplikace, stahování souborů neprojde kontrolami CORS provedenými prohlížečem.

Další informace o CORS s aplikacemi ASP.NET Core a dalšími produkty a službami Microsoftu, které hostují soubory ke stažení, najdete v následujících zdrojích informací:

Další materiály