Javascript để thực hiện xử lý sau khi tải xuống tệp

Trang Cập Nhật :
Ngày tạo trang :

Môi trường xác minh hoạt động

Visual Studio
  • Visual Studio 2022
Lõi ASP.NET
  • 8.0 (Trang Razpr, MVC)
Trình duyệt web
  • Cạnh 119

Môi trường hoạt động

Visual Studio (nếu bạn cũng bao gồm các chương trình máy chủ)
  • Visual Studio 2022
ASP.NET Core (nếu nó cũng bao gồm các chương trình máy chủ)
  • 8.0 (Trang Razpr, MVC)
Trình duyệt web
  • Cạnh
  • Google Chrome
  • Các trình duyệt khác (không phải tất cả đều được chọn)

(* Phần chính của mẹo này là quy trình phía máy khách, vì vậy phía máy chủ có thể là bất cứ thứ gì)

Lúc đầu

Trọng tâm chính của các mẹo này là chương trình máy khách (Javascript) và chương trình máy chủ chỉ ở đó để tải xuống tệp. Do đó, không quan trọng chương trình máy chủ là gì, miễn là nó có thể khiến bạn tải xuống tệp.

Yêu cầu người dùng tải xuống tệp khi chúng được truy cập trên máy chủ

Ông / Bà cho phép bạn tải xuống các tệp khi bạn nhận được yêu cầu. Khi đó, chúng tôi cố tình đợi một khoảng thời gian nhất định trên máy chủ để dễ hiểu khi bắt đầu và kết thúc quá trình tải xuống.

Đây là những gì xảy ra ở phía máy chủ của Razor Pages và MVC: Bạn có thể triển khai nó trong các dự án khác, chẳng hạn như API Web.

Trang dao cạo: Trang/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");
    }
  }
}

Xử lý khách hàng

Thông thường, bạn tải xuống tệp bằng cách truy cập URL được chỉ định trong trình duyệt web. Nếu bạn muốn làm điều gì đó sau khi quá trình tải xuống hoàn tất, bạn có thể chạy tải xuống bằng Javascript.

Có nhiều cách để làm điều này, nhưng trong trường hợp này, chúng tôi sẽ sử dụng , đó cũng XMLHttpRequest là nguồn gốc của xử lý không đồng bộ. Bạn cũng có thể sử dụng các hàm ajax jQuery hoặc API Fetch.

ahref URL tải xuống được ghi trong thẻ và id quá trình được thực thi khi nhấp vào URL được đặt thànhdownload.

$('#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 Thông thường, nếu bạn để phần tử được nhấp, quá trình tải xuống mặc định sẽ di chuyển, vì vậy e.preventDefault(); chúng tôi gọi để vô hiệu hóa quá trình mặc định.

href Lấy URL tải xuống từ và XMLHttpRequest GET đặt nó để lấy nó từ .

XMLHttpRequest.responseTypeblob để hướng dẫn dữ liệu nhị phân được tải xuống.

XMLHttpRequest.onload Vì quá trình sau khi tải xuống dữ liệu hoàn tất có thể được mô tả trong sự kiện, quá trình sau khi tải xuống hoàn tất được viết ở đây. Vì dữ liệu chỉ được tải xuống máy khách, tệp không thực sự được lưu trữ cục bộ. Để lưu tệp cục bộ, bạn có thể thêm thẻ a chứa dữ liệu giả và làm cho thẻ hoạt động như thể bạn đã nhấp vào liên kết và lưu tệp. Dữ liệu tại thời điểm đó có thể window.URL.createObjectURL được chuyển đổi thành URL bằng hàm, vì vậy href bạn có thể đặt nó thành và làm cho nó hoạt động.

Tên tệp được lưu có thể được truy xuất từ tiêu đề phản hồi nếu nó được bao gồm trong phản hồi từ Content-Disposition máy chủ. Vì nó hơi phức tạp để có được, tôi nghĩ rằng mã nên được sử dụng như hiện tại. Nếu tên tệp không được chỉ định trên máy chủ, nó không thể được trợ giúp, vì vậy tôi nghĩ rằng nó sẽ được đặt thành tên tệp mặc định hoặc tên tệp ở cuối đường dẫn URL.

Vì lần này tôi chỉ hiển thị nó trong bảng điều khiển sau khi lưu tệp, tôi nghĩ rằng thao tác mong muốn có thể được thực thi bằng cách viết lại phần này bằng mã tùy ý.

Khi quá trình tải xuống dữ liệu được mô tả, điều cuối cùng chúng ta muốn làm là XMLHttpRequest.send gọi một hàm để thực sự bắt đầu yêu cầu.

Liên kết chạy tải xuống

Mr./Ms. Code cung cấp các liên kết đến mẫu tải xuống tệp trực tiếp và mẫu tải xuống bằng Javascript. a Bạn có thể viết URL trực tiếp vào href thẻ nhưng nếu bạn viết như sau trong ASP.NET Core, URL sẽ tự động href mở rộng thành .

Trang dao cạo: 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 : Lượt xem/Trang chủ/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>