جافا سكريبت لإجراء المعالجة بعد تنزيل ملف
بيئة التحقق من العملية
- فيجوال ستوديو
-
- فيجوال ستوديو 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 أو واجهة برمجة تطبيقات الجلب.
a
href
تتم كتابة عنوان 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.responseType
blob
لإرشاد البيانات الثنائية المراد تنزيلها.
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>