Dela via


ASP.NET Core-filnedladdningar Blazor

Anmärkning

Det här är inte den senaste versionen av den här artikeln. För den nuvarande utgåvan, se .NET 9-versionen av den här artikeln .

Varning

Den här versionen av ASP.NET Core stöds inte längre. Mer information finns i .NET och .NET Core Support Policy. För den nuvarande utgåvan, se .NET 9-versionen av den här artikeln .

Viktigt!

Den här informationen gäller en förhandsversionsprodukt som kan ändras avsevärt innan den släpps kommersiellt. Microsoft lämnar inga garantier, uttryckliga eller underförstådda, med avseende på den information som tillhandahålls här.

För den nuvarande utgåvan, se .NET 9-versionen av den här artikeln .

I den här artikeln beskrivs hur du laddar ned filer i Blazor appar.

Filnedladdningar

Den här artikeln beskriver metoder för följande scenarier, där en fil inte ska öppnas av en webbläsare utan laddas ned och sparas på klienten:

När du laddar ned filer från ett annat ursprung än appen gäller cors-överväganden (Cross-Origin Resource Sharing). Mer information finns i avsnittet Resursdelning mellan ursprung (CORS).

Säkerhetsfrågor

Var försiktig när du ger användarna möjlighet att ladda ned filer från en server. Cyberattacker kan utföra DoS-attacker (Denial of Service),API-exploateringsattacker eller försöka kompromettera nätverk och servrar på andra sätt.

Säkerhetssteg som minskar sannolikheten för ett lyckat angrepp är:

  • Ladda ned filer från ett dedikerat filnedladdningsområde på servern, helst från en enhet som inte är en systemenhet. Om du använder en dedikerad plats blir det enklare att införa säkerhetsbegränsningar för nedladdningsbara filer. Inaktivera exekveringsrättigheter i mappen för filnedladdning.
  • Säkerhetskontroller på klientsidan är lätta att kringgå av skadliga användare. Utför alltid säkerhetskontroller på klientsidan på servern också.
  • Ta inte emot filer från användare eller andra ej betrodda källor och gör sedan filerna tillgängliga för omedelbar nedladdning utan att utföra säkerhetskontroller på filerna. Mer information finns i Ladda upp filer i ASP.NET Core.

Ladda ned från en dataström

Det här avsnittet gäller för filer som vanligtvis är upp till 250 MB stora.

Den rekommenderade metoden för att ladda ned relativt små filer (< 250 MB) är att strömma filinnehåll till en rå binär databuffert på klienten med JavaScript(JS) interop. Den här metoden är effektiv för komponenter som använder ett interaktivt återgivningsläge men inte komponenter som använder statisk återgivning på serversidan (statisk SSR).

Den rekommenderade metoden för att ladda ned relativt små filer (< 250 MB) är att strömma filinnehåll till en rå binär databuffert på klienten med JavaScript(JS) interop.

Varning

Metoden i det här avsnittet läser in filens innehåll i en JS ArrayBuffer. Den här metoden läser in hela filen i klientens minne, vilket kan försämra prestandan. Om du vill ladda ned relativt stora filer (>= 250 MB) rekommenderar vi att du följer riktlinjerna i avsnittet Ladda ned från en URL .

Följande downloadFileFromStreamJS funktion:

  • Läser den angivna strömmen till en ArrayBuffer.
  • Skapar en Blob för att omsluta ArrayBuffer.
  • Skapar en objekt-URL som ska fungera som filens nedladdningsadress.
  • Skapar ett HTMLAnchorElement (<a> -element).
  • Tilldelar filens namn (fileName) och URL (url) för nedladdningen.
  • Utlöser nedladdningen genom att utlösa en click händelse på fästpunktselementet.
  • Tar bort fästpunktselementet.
  • Återkallar objekt-URL:en (url) genom att anropa URL.revokeObjectURL. Det här är ett viktigt steg för att säkerställa att minnet inte läcker på klienten.
<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>

Anmärkning

Allmän vägledning om JS plats och våra rekommendationer för produktionsappar finns i JavaScript-plats i ASP.NET Core Blazor-appar.

Följande komponent:

  • Använder inbyggt byte-streaming-interop för att säkerställa effektiv överföring av filen till klienten.
  • Har en metod med namnet GetFileStream för att hämta en Stream för filen som laddas ned till klienter. Alternativa metoder är att hämta en fil från lagring eller generera en fil dynamiskt i C#-kod. För den här demonstrationen skapar appen en 50 KB-fil med slumpmässiga data från en ny bytematris (new byte[]). Byteen omsluts med en MemoryStream för att fungera som exemplets dynamiskt genererade binära fil.
  • Metoden DownloadFileFromStream :
    • Hämtar Stream från GetFileStream.
    • Anger ett filnamn när filen sparas på användarens dator. I följande exempel namnges filen quote.txt.
    • Omsluter Stream i en DotNetStreamReference, som gör det möjligt att strömma fildata till klienten.
    • Anropar downloadFileFromStreamJS funktionen för att acceptera data på klienten.

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

För en komponent i en app på serversidan som måste returnera en Stream för en fysisk fil kan komponenten anropa File.OpenRead, vilket visas i följande exempel:

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

I det föregående exemplet är platshållaren {PATH} sökvägen till filen. Prefixet @ anger att strängen är en ordagrann sträng, vilket tillåter användning av omvänt snedstreck (\) i en sökväg i Windows OS och inbäddade dubbla citattecken ("") som representerar enkelcitattecken i sökvägen. Du kan också undvika strängliteralen (@) och använda någon av följande metoder:

  • Använd undantagna omvänt snedstreck (\\) och citattecken (\").
  • Använd snedstreck (/) i sökvägen, som stöds på olika plattformar i ASP.NET Core-appar och undantagna citattecken (\").

Ladda ned från en URL

Det här avsnittet gäller för filer som är relativt stora, vanligtvis 250 MB eller större.

Den rekommenderade metoden för att ladda ned relativt stora filer (>= 250 MB) med interaktivt renderade komponenter eller filer av valfri storlek för statiskt renderade komponenter är att använda JS för att utlösa ett fästpunktselement med filens namn och URL.

Den rekommenderade metoden för att ladda ned relativt stora filer (>= 250 MB) är att använda JS för att utlösa ett fästpunktselement med filens namn och URL.

I exemplet i det här avsnittet används en nedladdningsfil med namnet quote.txt, som placeras i en mapp med namnet files i appens webbrot (wwwroot mapp). Användningen av mappen files är endast i demonstrationssyfte. Du kan ordna nedladdningsbara filer i valfri mapplayout i den webbrot (wwwroot mapp) som du föredrar, inklusive att hantera filerna direkt från wwwroot mappen.

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/)

Följande triggerFileDownloadJS funktion:

  • Skapar ett HTMLAnchorElement (<a> -element).
  • Tilldelar filens namn (fileName) och URL (url) för nedladdningen.
  • Utlöser nedladdningen genom att utlösa en click händelse på fästpunktselementet.
  • Tar bort fästpunktselementet.
<script>
  window.triggerFileDownload = (fileName, url) => {
    const anchorElement = document.createElement('a');
    anchorElement.href = url;
    anchorElement.download = fileName ?? '';
    anchorElement.click();
    anchorElement.remove();
  }
</script>

Anmärkning

Allmän vägledning om JS plats och våra rekommendationer för produktionsappar finns i JavaScript-plats i ASP.NET Core Blazor-appar.

Följande exempelkomponent laddar ned filen från samma ursprung som appen använder. Om filnedladdningen görs från ett annat ursprung konfigurerar du CORS (Cross-Origin Resource Sharing). Mer information finns i avsnittet Resursdelning mellan ursprung (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);
    }
}

För interaktiva komponenter anropar knappen i föregående exempel hanteraren DownloadFileFromURL för att anropa JavaScript (JS) funktionen triggerFileDownload.

Om komponenten använder statisk återgivning på serversidan (statisk SSR) lägger du till en händelsehanterare för knappen (addEventListener) för att anropa triggerFileDownload enligt riktlinjerna i ASP.NET Core Blazor JavaScript med statisk återgivning på serversidan (statisk 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);
    }
}

För interaktiva komponenter anropar knappen i föregående exempel hanteraren DownloadFileFromURL för att köra JavaScript-funktionen triggerFileDownload(JS).

Om komponenten använder statisk återgivning på serversidan (statisk SSR) lägger du till en händelsehanterare för knappen (addEventListener) för att anropa triggerFileDownload enligt riktlinjerna i ASP.NET Core Blazor JavaScript med statisk återgivning på serversidan (statisk 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);
    }
}

Ändra porten i föregående exempel så att den matchar localhost-utvecklingsporten för din miljö.

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

Ändra porten i föregående exempel så att den matchar localhost-utvecklingsporten för din miljö.

Resursdelning mellan ursprungsdomäner (CORS)

Utan att vidta ytterligare åtgärder för att aktivera CORS (Cross-Origin Resource Sharing) för filer som inte har samma ursprung som appen, kommer nedladdning av filer inte att klara CORS-kontroller som gjorts av webbläsaren.

Mer information om CORS med ASP.NET Core-appar och andra Microsoft-produkter och -tjänster som är värdar för filer för nedladdning finns i följande resurser:

Ytterligare resurser