Javascript para executar o processamento após o download de um arquivo

Página atualizada :
Data de criação de página :

Ambiente de verificação de operação

Estúdio Visual
  • Visual Studio 2022
ASP.NET Núcleo
  • 8.0 (Páginas Razpr, MVC)
Navegadores da Web
  • Borda 119

Ambiente operacional

Visual Studio (se você também incluir programas de servidor)
  • Visual Studio 2022
ASP.NET Core (se também incluir programas de servidor)
  • 8.0 (Páginas Razpr, MVC)
Navegadores da Web
  • Borda
  • Google Chrome
  • Outros navegadores (nem todos marcados)

(* O corpo principal desta dica é o processo do lado do cliente, então o lado do servidor pode ser qualquer coisa)

Inicialmente

O foco principal dessas dicas é o programa cliente (Javascript), e o programa servidor está lá apenas para baixar arquivos. Portanto, não importa qual é o programa do servidor, desde que ele possa fazer você baixar o arquivo.

Fazer com que os usuários baixem arquivos quando eles são acessados no servidor

Mr./Ms. permite que você baixe arquivos quando receber uma solicitação. Nesse momento, esperamos deliberadamente por um certo período de tempo no servidor para que seja fácil entender o início e o fim do download.

Aqui está o que acontece no lado do servidor do Razor Pages e do MVC: Você pode implementá-lo em outros projetos, como API Web.

Páginas Navalha : Páginas/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");
    }
  }
}

Processamento do cliente

Normalmente, você baixa um arquivo acessando uma URL especificada em um navegador da Web. Se você quiser fazer algo depois que o download for concluído, você pode executar o download com Javascript.

Existem muitas maneiras de fazer isso, mas neste caso, usaremos , que também XMLHttpRequest é a origem do processamento assíncrono. Você também pode usar funções jQuery ajax ou a API Fetch.

ahref A URL de download é gravada na tag e id o processo é executado quando o definido como download é clicado.

$('#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 você deixar o elemento clicado, o processo de download padrão será movido, então e.preventDefault(); chamamos para desabilitar o processo padrão.

href Obtenha o URL de download de e XMLHttpRequest GET defina-o para obtê-lo de .

XMLHttpRequest.responseTypeblob para instruir os dados binários a serem baixados.

XMLHttpRequest.onload Como o processo após a conclusão do download dos dados pode ser descrito no evento, o processo após a conclusão do download é escrito aqui. Como os dados só foram baixados para o cliente, o arquivo não é realmente armazenado localmente. Para salvar um arquivo localmente, você pode adicionar uma tag que a contenha pseudodados e fazê-lo se comportar como se você tivesse clicado em um link e salvo o arquivo. Os dados nesse momento podem window.URL.createObjectURL ser convertidos em uma URL pela função, para href que você possa configurá-los e fazê-los funcionar.

O nome do arquivo a ser salvo pode ser recuperado do cabeçalho da resposta se estiver incluído na resposta do Content-Disposition servidor. Como é um pouco complicado de adquirir, acho que o código deve ser usado como está. Se o nome do arquivo não for especificado no servidor, ele não poderá ser ajudado, então acho que ele será definido como o nome de arquivo padrão ou o nome do arquivo no final do caminho da URL.

Como desta vez só o exibi no console depois de salvar o arquivo, acho que a operação desejada pode ser executada reescrevendo essa parte com código arbitrário.

Uma vez que o processo de download de dados é descrito, a última coisa que queremos fazer é XMLHttpRequest.send chamar uma função para realmente iniciar a solicitação.

Baixar link de execução

Mr./Ms. Code fornece links para o padrão de download do arquivo diretamente e o padrão de baixá-lo com Javascript. a Você pode escrever a URL diretamente na href tag , mas se escrever o seguinte no ASP.NET Core, a URL será expandida automaticamente href para .

Páginas Razor : 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 : Visualizações/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>