用於在下載檔後執行處理的 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>