Javascript per eseguire l'elaborazione dopo aver scaricato un file

Pagina aggiornata :
Data di creazione della pagina :

Ambiente di verifica del funzionamento

Visual Studio
  • Visual Studio 2022
ASP.NET Core
  • 8.0 (Pagine Razpr, MVC)
Browser Web
  • Bordo 119

Ambiente operativo

Visual Studio (se si includono anche programmi server)
  • Visual Studio 2022
ASP.NET Core (se include anche programmi server)
  • 8.0 (Pagine Razpr, MVC)
Browser Web
  • Bordo
  • Google Chrome
  • Altri browser (non tutti controllati)

(* Il corpo principale di questo suggerimento è il processo lato client, quindi il lato server può essere qualsiasi cosa)

Dapprima

L'obiettivo principale di questi suggerimenti è il programma client (Javascript) e il programma server è lì solo per scaricare i file. Pertanto, non importa quale sia il programma server, purché possa farti scaricare il file.

Fare in modo che gli utenti scarichino i file quando accedono al server

Mr./Ms. ti consente di scaricare i file quando ricevi una richiesta. A quel punto, aspettiamo deliberatamente un certo periodo di tempo sul server in modo che sia facile capire l'inizio e la fine del download.

Ecco cosa succede sul lato server di Razor Pages e MVC: È possibile implementarlo in altri progetti, ad esempio l'API Web.

Razor Pages : Pagine/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");
    }
  }
}

Elaborazione del cliente

In genere, si scarica un file accedendo a un URL specificato in un browser Web. Se si desidera eseguire un'operazione dopo il completamento del download, è possibile eseguire il download con Javascript.

Ci sono molti modi per farlo, ma in questo caso useremo , che è anche XMLHttpRequest l'origine dell'elaborazione asincrona. È inoltre possibile utilizzare le funzioni ajax jQuery o l'API Fetch.

ahref L'URL di download viene scritto nel tag e id il processo viene eseguito quando si fa clic su quello impostato sudownload.

$('#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 Normalmente, se lasci l'elemento cliccato, il processo di download predefinito si sposterà, quindi e.preventDefault(); chiamiamo per disabilitare il processo predefinito.

href Ottenere l'URL di download da e XMLHttpRequest GET impostarlo per ottenerlo da .

XMLHttpRequest.responseTypeblob per istruire i dati binari da scaricare.

XMLHttpRequest.onload Poiché il processo dopo il completamento del download dei dati può essere descritto nell'evento, il processo dopo il completamento del download è scritto qui. Poiché i dati sono stati scaricati solo sul client, il file non viene effettivamente archiviato localmente. Per salvare un file in locale, è possibile aggiungere un tag che contiene pseudo-dati e fare in modo che a si comporti come se si fosse fatto clic su un collegamento e salvato il file. I dati in quel momento possono window.URL.createObjectURL essere convertiti in un URL dalla funzione, in modo da href poterli impostare e far funzionare.

Il nome del file da salvare può essere recuperato dall'intestazione della risposta se è incluso nella risposta del Content-Disposition server. Dal momento che è un po' complicato da acquisire, penso che il codice dovrebbe essere usato così com'è. Se il nome del file non è specificato sul server, non può essere aiutato, quindi penso che verrà impostato sul nome del file predefinito o sul nome del file alla fine del percorso dell'URL.

Dato che questa volta lo visualizzo nella console solo dopo aver salvato il file, penso che l'operazione desiderata possa essere eseguita riscrivendo questa parte con codice arbitrario.

Una volta descritto il processo di download dei dati, l'ultima cosa che vogliamo fare è XMLHttpRequest.send chiamare una funzione per avviare effettivamente la richiesta.

Link per il download dell'esecuzione

Mr./Ms. Code fornisce collegamenti al modello di download diretto del file e al modello di download con Javascript. a Puoi scrivere l'URL direttamente nel href tag, ma se scrivi quanto segue in ASP.NET Core, l'URL si espanderà automaticamente href in .

Razor Pages : Pages/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 : Views/Home/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>