Javascript til at udføre behandling efter download af en fil

Side opdateret :
Dato for oprettelse af side :

Miljø til driftsbekræftelse

Visual Studio
  • Visual Studio 2022
ASP.NET kerne
  • 8.0 (Razpr sider, MVC)
Webbrowsere
  • Kant 119

Driftsmiljø

Visual Studio (hvis du også inkluderer serverprogrammer)
  • Visual Studio 2022
ASP.NET Core (hvis det også omfatter serverprogrammer)
  • 8.0 (Razpr sider, MVC)
Webbrowsere
  • Rand
  • Google Chrome
  • Andre browsere (ikke alle markeret)

(* Hoveddelen af dette tip er klientsideprocessen, så serversiden kan være hvad som helst)

Først

Hovedfokus for disse tip er klientprogrammet (Javascript), og serverprogrammet er der kun for at downloade filer. Derfor er det ligegyldigt, hvad serverprogrammet er, så længe det kan få dig til at downloade filen.

Få brugerne til at downloade filer, når de åbnes på serveren

Mr./Ms. giver dig mulighed for at downloade filer, når du modtager en anmodning. På det tidspunkt venter vi bevidst på en vis tid på serveren, så det er let at forstå starten og slutningen af download.

Her er hvad der sker på serversiden af Razor Pages og MVC: Du kan implementere det i andre projekter, såsom Web API.

Razor Sider : Sider / Index.cshtml.cs

// 省略

namespace DownloadCompleteNotifyRazorPages.Pages
{
  public class IndexModel : PageModel
  {
    // 省略

    /// <summary>時間をかけてファイルをダウンロードします。</summary>
    public async Task<IActionResult> OnGetDownload()
    {
      // ダウンロード開始と完了を明確にする目的で待機を入れる
      await Task.Delay(5000);

      // 適当にファイルを作って返す
      var fileSize = 10_000_000;
      var sb = new System.Text.StringBuilder(fileSize);
      for (int i = 0; i < fileSize; i++) sb.Append('a');
      using var stream = new MemoryStream(System.Text.Encoding.UTF8.GetBytes(sb.ToString()));
      return File(stream.ToArray(), "text/plain", $"ダウンロード.txt");
    }
  }
}

MVC : Coletollers / HomeController.cs

// 省略

namespace DownloadCompleteNotifyMvc.Controllers
{
  public class HomeController : Controller
  {
    // 省略

    /// <summary>時間をかけてファイルをダウンロードします。</summary>
    public async Task<IActionResult> Download()
    {
      // ダウンロード開始と完了を明確にする目的で待機を入れる
      await Task.Delay(5000);

      // 適当にファイルを作って返す
      var fileSize = 10_000_000;
      var sb = new System.Text.StringBuilder(fileSize);
      for (int i = 0; i < fileSize; i++) sb.Append('a');
      using var stream = new MemoryStream(System.Text.Encoding.UTF8.GetBytes(sb.ToString()));
      return File(stream.ToArray(), "text/plain", $"ダウンロード.txt");
    }
  }
}

Behandling af klienter

Normalt downloader du en fil ved at få adgang til en bestemt URL i en webbrowser. Hvis du vil gøre noget, når overførslen er fuldført, kan du køre overførslen med Javascript.

Der er mange måder at gøre dette på, men i dette tilfælde vil vi bruge , som også XMLHttpRequest er oprindelsen til asynkron behandling. Du kan også bruge jQuery ajax-funktioner eller Fetch API.

ahref Download-URL'en skrives i -tagget, og id processen udføres, når der klikkes på den, der er indstillet tildownload.

$('#download').click(function (e) {
  console.log('ダウンロードを開始します。');
  e.preventDefault();  // href による画面遷移を抑止
  let url = $(e.target).attr('href');  // href からダウンロード URL 取得

  const xhr = new XMLHttpRequest();
  xhr.open('GET', url, true);   // ダウンロード先 URL 設定
  xhr.responseType = 'blob';   // バイナリデータ取得であることを指示

  // ダウンロード完了後の処理を設定。この時点ではデータは取得してクライアントにありますが保存はしていません。
  xhr.onload = function (oEvent) {
    if (xhr.status !== 200) {
      console.log(`データの取得に失敗しました。(status=${xhr.status})`);
    } else {
      // 取得したデータ
      let blob = xhr.response;

      // レスポンスヘッダーからサーバーから送られてきたファイル名を取得する
      let fileName = '';
      let disposition = xhr.getResponseHeader('Content-Disposition');
      if (disposition && disposition.indexOf('attachment') !== -1) {
        let filenameRegex = /filename[^;=\n]=((['"]).*?\2|[^;\n]*)/;
        let matches = filenameRegex.exec(disposition);
        if (matches != null && matches[1]) {
          // 「filename*=UTF-8''%E3%83%87%E3%83%BC%E3%82%BF.txt;」からファイル名を取得
          fileName = decodeURI(matches[1].replace(/['"]/g, '').replace('utf-8', '').replace('UTF-8', ''));
        }
      }
      if (fileName === '') {
        // ファイル名を取得できなかったら念のため URL をファイル名とする
        let fileName = url.match('.+/(.+?)([\?#;].*)?$')[1];
      }

      // Blob オブジェクトを指す URL オブジェクトを作る
      let objectURL = window.URL.createObjectURL(blob);
      // リンク(<a>要素)を生成し、JavaScript からクリックする
      let link = document.createElement('a');
      document.body.appendChild(link);
      link.href = objectURL;
      link.download = fileName;   // download を指定するとブラウザで開くことなくダウンロードになる
      link.click();
      document.body.removeChild(link);

      console.log('ダウンロードを完了しました。');
    }
  };

  // リクエスト開始
  xhr.send();
});

a Normalt, hvis du lader elementet klikke, flyttes standarddownloadprocessen, så e.preventDefault(); vi opfordrer til at deaktivere standardprocessen.

href Hent download-URL'en fra, og XMLHttpRequest GET indstil den til at hente den fra .

XMLHttpRequest.responseTypeblob for at instruere de binære data, der skal downloades.

XMLHttpRequest.onload Da processen efter dataoverførslen er afsluttet kan beskrives i tilfælde af, skrives processen efter download er afsluttet her. Da dataene kun er downloadet til klienten, gemmes filen faktisk ikke lokalt. Hvis du vil gemme en fil lokalt, kan du tilføje et tag, der a indeholder pseudodata, og få det til at opføre sig, som om du havde klikket på et link og gemt filen. Dataene på det tidspunkt kan window.URL.createObjectURL konverteres til en URL af funktionen, så href du kan indstille dem til og få det til at fungere.

Det filnavn, der skal gemmes, kan hentes fra svaroverskriften, hvis det er inkluderet i svaret fra Content-Disposition serveren. Da det er lidt kompliceret at erhverve, synes jeg, at koden skal bruges som den er. Hvis filnavnet ikke er angivet på serveren, kan det ikke hjælpes, så jeg tror, at det vil blive indstillet til standardfilnavnet eller filnavnet i slutningen af URL-stien.

Siden denne gang viser jeg det kun i konsollen efter at have gemt filen, tror jeg, at den ønskede operation kan udføres ved at omskrive denne del med vilkårlig kode.

Når dataoverførselsprocessen er beskrevet, er XMLHttpRequest.send det sidste, vi vil gøre, at kalde en funktion for faktisk at starte anmodningen.

Download kørselslink

Mr. / Ms. Code giver links til mønsteret for at downloade filen direkte og mønsteret for at downloade den med Javascript. a Du kan skrive URL-adressen direkte i -tagget href , men hvis du skriver følgende i ASP.NET Core, udvides URL-adressen automatisk href til .

Razor Sider : Sider / Index.cshtml

<ul>
  <li><a asp-page-handler="Download">ダウンロード (Javascript なし)</a></li>
  <li><a asp-page-handler="Download" id="download">ダウンロード (Javascript あり)</a></li>
</ul>

MVC : Visninger / Hjem / Index.cshtml

<ul>
  <li><a asp-controller="Home" asp-action="Download">ダウンロード (Javascript なし)</a></li>
  <li><a asp-controller="Home" asp-action="Download" id="download">ダウンロード (Javascript あり)</a></li>
</ul>