Javascript untuk melakukan pemprosesan selepas memuat turun fail

Laman dikemaskini :
Tarikh penciptaan halaman :

Persekitaran pengesahan operasi

Visual Studio
  • Visual Studio 2022
ASP.NET Teras
  • 8.0 (Halaman Razpr, MVC)
Pelayar Web
  • Tepi 119

Persekitaran operasi

Visual Studio (jika anda juga termasuk program pelayan)
  • Visual Studio 2022
ASP.NET Core (jika ia juga termasuk program pelayan)
  • 8.0 (Halaman Razpr, MVC)
Pelayar Web
  • Pinggir
  • Google Chrome
  • Pelayar lain (tidak semua diperiksa)

(* Badan utama hujung ini adalah proses pihak klien, jadi bahagian pelayan boleh menjadi apa-apa)

Pada mulanya

Fokus utama petua ini ialah program klien (Javascript), dan program pelayan hanya ada untuk memuat turun fail. Oleh itu, tidak kira apa program pelayan, selagi ia boleh membuat anda memuat turun fail.

Minta pengguna memuat turun fail apabila mereka diakses pada pelayan

Mr./Ms. membolehkan anda memuat turun fail apabila anda menerima permintaan. Pada masa itu, kami sengaja menunggu masa tertentu pada pelayan supaya mudah untuk memahami permulaan dan akhir muat turun.

Inilah yang berlaku di bahagian pelayan Halaman Pisau Cukur dan MVC: Anda boleh melaksanakannya dalam projek lain, seperti Web API.

Laman Pisau Cukur : Muka surat/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");
    }
  }
}

Pemprosesan pelanggan

Biasanya, anda memuat turun fail dengan mengakses URL tertentu dalam pelayar web. Jika anda ingin melakukan sesuatu selepas muat turun selesai, anda boleh menjalankan muat turun dengan Javascript.

Terdapat banyak cara untuk melakukan ini, tetapi dalam kes ini, kita akan menggunakan , yang juga XMLHttpRequest merupakan asal pemprosesan tak segerak. Anda juga boleh menggunakan fungsi ajax jQuery atau API Fetch.

ahref URL muat turun ditulis dalam tag dan id proses dilaksanakan apabila satu set untuk download diklik.

$('#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 Biasanya, jika anda membiarkan elemen diklik, proses muat turun lalai akan dialihkan, jadi e.preventDefault(); kami memanggil untuk menyahdayakan proses lalai.

href Dapatkan URL muat turun dan XMLHttpRequest GET tetapkannya untuk mendapatkannya daripada .

XMLHttpRequest.responseTypeblob untuk mengarahkan data binari dimuat turun.

XMLHttpRequest.onload Oleh kerana proses selepas muat turun data selesai dapat diterangkan dalam acara tersebut, proses selepas muat turun selesai ditulis di sini. Oleh kerana data hanya dimuat turun kepada pelanggan, fail itu sebenarnya tidak disimpan secara tempatan. Untuk menyimpan fail secara setempat, anda boleh menambah tag yang a mengandungi data pseudo dan menjadikannya berkelakuan seolah-olah anda telah mengklik pautan dan menyimpan fail. Data pada masa itu boleh window.URL.createObjectURL ditukar kepada URL mengikut fungsi, jadi href anda boleh mengesetkannya dan menjadikannya berfungsi.

Nama fail yang disimpan boleh diambil daripada pengepala respons jika ia disertakan dalam respons daripada Content-Disposition pelayan. Oleh kerana agak rumit untuk diperoleh, saya fikir kod itu harus digunakan seperti sedia ada. Jika nama fail tidak ditentukan pada pelayan, ia tidak dapat dibantu, jadi saya fikir ia akan ditetapkan kepada nama fail lalai atau nama fail pada akhir laluan URL.

Oleh kerana kali ini saya hanya memaparkannya di konsol selepas menyimpan fail, saya fikir operasi yang dikehendaki dapat dilaksanakan dengan menulis semula bahagian ini dengan kod sewenang-wenangnya.

Setelah proses muat turun data diterangkan, perkara terakhir yang ingin kami lakukan ialah XMLHttpRequest.send memanggil fungsi untuk benar-benar memulakan permintaan.

Muat turun pautan run

Mr./Ms. Code menyediakan pautan kepada corak memuat turun fail secara langsung dan corak memuat turunnya dengan Javascript. a Anda boleh menulis URL secara langsung dalam href tag, tetapi jika anda menulis yang berikut dalam ASP.NET Core, URL akan berkembang secara automatik href ke .

Laman Pisau Cukur : Halaman/Indeks.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/Laman Utama/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>