Javascript per eseguire l'elaborazione dopo aver scaricato un file
Ambiente di verifica del funzionamento
- Visual Studio
-
- Visual Studio 2022
- ASP.NET Core
-
- 8.0 (Pagine Razpr, MVC)
- Browser Web
-
- Bordo 119
Ambiente operativo
- Visual Studio (se si includono anche programmi server)
-
- Visual Studio 2022
- ASP.NET Core (se include anche programmi server)
-
- 8.0 (Pagine Razpr, MVC)
- Browser Web
-
- Bordo
- Google Chrome
- Altri browser (non tutti controllati)
(* Il corpo principale di questo suggerimento è il processo lato client, quindi il lato server può essere qualsiasi cosa)
Dapprima
L'obiettivo principale di questi suggerimenti è il programma client (Javascript) e il programma server è lì solo per scaricare i file. Pertanto, non importa quale sia il programma server, purché possa farti scaricare il file.
Fare in modo che gli utenti scarichino i file quando accedono al server
Mr./Ms. ti consente di scaricare i file quando ricevi una richiesta. A quel punto, aspettiamo deliberatamente un certo periodo di tempo sul server in modo che sia facile capire l'inizio e la fine del download.
Ecco cosa succede sul lato server di Razor Pages e MVC: È possibile implementarlo in altri progetti, ad esempio l'API Web.
Razor Pages : Pagine/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");
}
}
}
Elaborazione del cliente
In genere, si scarica un file accedendo a un URL specificato in un browser Web. Se si desidera eseguire un'operazione dopo il completamento del download, è possibile eseguire il download con Javascript.
Ci sono molti modi per farlo, ma in questo caso useremo , che è anche XMLHttpRequest
l'origine dell'elaborazione asincrona.
È inoltre possibile utilizzare le funzioni ajax jQuery o l'API Fetch.
a
href
L'URL di download viene scritto nel tag e id
il processo viene eseguito quando si fa clic su quello impostato sudownload
.
$('#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
Normalmente, se lasci l'elemento cliccato, il processo di download predefinito si sposterà, quindi e.preventDefault();
chiamiamo per disabilitare il processo predefinito.
href
Ottenere l'URL di download da e XMLHttpRequest
GET
impostarlo per ottenerlo da .
XMLHttpRequest.responseType
blob
per istruire i dati binari da scaricare.
XMLHttpRequest.onload
Poiché il processo dopo il completamento del download dei dati può essere descritto nell'evento, il processo dopo il completamento del download è scritto qui.
Poiché i dati sono stati scaricati solo sul client, il file non viene effettivamente archiviato localmente.
Per salvare un file in locale, è possibile aggiungere un tag che contiene pseudo-dati e fare in modo che a
si comporti come se si fosse fatto clic su un collegamento e salvato il file.
I dati in quel momento possono window.URL.createObjectURL
essere convertiti in un URL dalla funzione, in modo da href
poterli impostare e far funzionare.
Il nome del file da salvare può essere recuperato dall'intestazione della risposta se è incluso nella risposta del Content-Disposition
server.
Dal momento che è un po' complicato da acquisire, penso che il codice dovrebbe essere usato così com'è.
Se il nome del file non è specificato sul server, non può essere aiutato, quindi penso che verrà impostato sul nome del file predefinito o sul nome del file alla fine del percorso dell'URL.
Dato che questa volta lo visualizzo nella console solo dopo aver salvato il file, penso che l'operazione desiderata possa essere eseguita riscrivendo questa parte con codice arbitrario.
Una volta descritto il processo di download dei dati, l'ultima cosa che vogliamo fare è XMLHttpRequest.send
chiamare una funzione per avviare effettivamente la richiesta.
Link per il download dell'esecuzione
Mr./Ms. Code fornisce collegamenti al modello di download diretto del file e al modello di download con Javascript.
a
Puoi scrivere l'URL direttamente nel href
tag, ma se scrivi quanto segue in ASP.NET Core, l'URL si espanderà automaticamente href
in .
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>