جافا سكريبت لإجراء المعالجة بعد تنزيل ملف

تحديث الصفحة :
تاريخ إنشاء الصفحة :

بيئة التحقق من العملية

فيجوال ستوديو
  • فيجوال ستوديو 2022
ASP.NET الأساسية
  • 8.0 (صفحات رازبر، MVC)
متصفحات الويب
  • حافة 119

بيئة التشغيل

Visual Studio (إذا قمت أيضا بتضمين برامج الخادم)
  • فيجوال ستوديو 2022
ASP.NET Core (إذا كان يتضمن أيضا برامج الخادم)
  • 8.0 (صفحات رازبر، MVC)
متصفحات الويب
  • حافة
  • جوجل كروم
  • المتصفحات الأخرى (لم يتم التحقق منها كلها)

(* الجزء الرئيسي من هذه النصيحة هو العملية من جانب العميل ، لذلك يمكن أن يكون جانب الخادم أي شيء)

في البداية

التركيز الرئيسي لهذه النصائح هو برنامج العميل (جافا سكريبت) ، وبرنامج الخادم موجود فقط لتنزيل الملفات. لذلك ، لا يهم ما هو برنامج الخادم ، طالما أنه يمكن أن يجعلك تقوم بتنزيل الملف.

اطلب من المستخدمين تنزيل الملفات عند الوصول إليها على الخادم

يسمح لك السيد / السيدة بتنزيل الملفات عندما تتلقى طلبا. في ذلك الوقت ، ننتظر عمدا قدرا معينا من الوقت على الخادم حتى يسهل فهم بداية التنزيل ونهايته.

إليك ما يحدث على جانب الخادم من Razor Pages و MVC: يمكنك تنفيذه في مشاريع أخرى ، مثل Web API.

صفحات الحلاقة : الصفحات / 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 : كولتولرز / 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");
    }
  }
}

معالجة العميل

عادة ، يمكنك تنزيل ملف عن طريق الوصول إلى عنوان URL محدد في متصفح الويب. إذا كنت تريد القيام بشيء ما بعد اكتمال التنزيل ، فيمكنك تشغيل التنزيل باستخدام Javascript.

هناك العديد من الطرق للقيام بذلك ، ولكن في هذه الحالة ، سوف نستخدم ، وهو أيضا XMLHttpRequest أصل المعالجة غير المتزامنة. يمكنك أيضا استخدام وظائف jQuery ajax أو واجهة برمجة تطبيقات الجلب.

ahref تتم كتابة عنوان URL للتنزيل في العلامة ويتم id تنفيذ العملية عند النقر فوق العنوان الذي تم تعيينه علىdownload.

$('#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 عادة ، إذا تركت العنصر بالنقر فوقه ، فستتحرك عملية التنزيل الافتراضية ، لذلك e.preventDefault(); ندعو لتعطيل العملية الافتراضية.

href احصل على عنوان URL للتنزيل وقم XMLHttpRequest GET بتعيينه للحصول عليه من .

XMLHttpRequest.responseTypeblob لإرشاد البيانات الثنائية المراد تنزيلها.

XMLHttpRequest.onload نظرا لأنه يمكن وصف العملية بعد اكتمال تنزيل البيانات في الحدث ، تتم كتابة العملية بعد اكتمال التنزيل هنا. نظرا لأنه تم تنزيل البيانات إلى العميل فقط ، فلن يتم تخزين الملف فعليا محليا. لحفظ ملف محليا ، يمكنك إضافة علامة a تحتوي على بيانات زائفة وجعلها تتصرف كما لو كنت قد نقرت على ارتباط وحفظت الملف. يمكن window.URL.createObjectURL تحويل البيانات في ذلك الوقت إلى عنوان URL بواسطة الوظيفة ، بحيث href يمكنك تعيينها وجعلها تعمل.

يمكن استرداد اسم الملف المراد حفظه من رأس الاستجابة إذا تم تضمينه في الاستجابة من الخادم Content-Disposition . نظرا لأن الحصول عليها معقد بعض الشيء ، أعتقد أنه يجب استخدام الكود كما هو. إذا لم يتم تحديد اسم الملف على الخادم ، فلا يمكن مساعدته ، لذلك أعتقد أنه سيتم تعيينه على اسم الملف الافتراضي أو اسم الملف في نهاية مسار URL.

نظرا لأن هذه المرة أعرضها فقط في وحدة التحكم بعد حفظ الملف ، أعتقد أنه يمكن تنفيذ العملية المطلوبة عن طريق إعادة كتابة هذا الجزء برمز تعسفي.

بمجرد وصف عملية تنزيل البيانات ، فإن آخر شيء نريد القيام به هو XMLHttpRequest.send استدعاء وظيفة لبدء الطلب بالفعل.

رابط تشغيل التنزيل

يوفر Mr./Ms. Code روابط لنمط تنزيل الملف مباشرة ونمط تنزيله باستخدام جافا سكريبت. a يمكنك كتابة عنوان URL مباشرة في href العلامة ، ولكن إذا كتبت ما يلي في ASP.NET Core ، توسيع عنوان URL تلقائيا href إلى .

صفحات الحلاقة : الصفحات / 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 : مشاهدات/الصفحة الرئيسية/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>