用于在下载文件后执行处理的 Javascript
操作验证环境
- Visual 工作室
-
- Visual Studio 2022
- ASP.NET 核心
-
- 8.0 (Razpr Pages, MVC)
- Web 浏览器
-
- 边缘 119
操作环境
- Visual Studio(如果还包括服务器程序)
-
- Visual Studio 2022
- ASP.NET Core(如果还包括服务器程序)
-
- 8.0 (Razpr Pages, MVC)
- Web 浏览器
-
- 边缘
- 谷歌浏览器
- 其他浏览器(未全部选中)
(* 这个技巧的主体是客户端进程,所以服务器端可以是任何东西)
起先
这些提示的主要重点是客户端程序(Javascript),而服务器程序仅用于下载文件。 因此,服务器程序是什么并不重要,只要它能让你下载文件就行。
让用户在服务器上访问文件时下载文件
Mr./Ms. 允许您在收到请求时下载文件。 这时,我们特意在服务器上等待一定的时间,以便于理解下载的开始和结束。
下面是 Razor Pages 和 MVC 服务器端发生的情况: 可以在其他项目(如 Web API)中实现它。
Razor 页数:页数/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");
}
}
}
客户端处理
通常,您可以通过访问 Web 浏览器中的指定 URL 来下载文件。 如果要在下载完成后执行某些操作,可以使用 Javascript 运行下载。
有很多方法可以做到这一点,但在这种情况下,我们将使用 ,这也是 XMLHttpRequest
异步处理的起源。
您还可以使用 jQuery ajax 函数或 Fetch API。
a
href
下载 URL 写入标签id
中,并在单击设置为download
的 URL 时执行该过程。
$('#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 提供了直接下载文件的模式和使用 Javascript 下载文件的模式的链接。
a
您可以直接在标记中 href
写入 URL,但如果在 ASP.NET Core 中写入以下内容,则 URL 将自动 href
展开为 。
Razor Pages: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:Views/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>