Bir dosyayı indirdikten sonra işlem yapmak için Javascript
Operasyon doğrulama ortamı
- Visual Studio
-
- Visual Studio 2022
- ASP.NET Çekirdeği
-
- 8.0 (Razpr Sayfaları, MVC)
- İnternet Tarayıcıları
-
- Kenar 119
Çalışma ortamı
- Visual Studio (sunucu programlarını da dahil ediyorsanız)
-
- Visual Studio 2022
- ASP.NET Core (sunucu programlarını da içeriyorsa)
-
- 8.0 (Razpr Sayfaları, MVC)
- İnternet Tarayıcıları
-
- Kenar
- Google Chrome
- Diğer tarayıcılar (tümü işaretli değil)
(* Bu ipucunun ana gövdesi istemci tarafı işlemidir, bu nedenle sunucu tarafı herhangi bir şey olabilir)
İlk başta
Bu ipuçlarının ana odak noktası istemci programıdır (Javascript) ve sunucu programı yalnızca dosyaları indirmek için oradadır. Bu nedenle, dosyayı indirmenizi sağlayabildiği sürece sunucu programının ne olduğu önemli değildir.
Kullanıcıların, sunucudan erişilen dosyaları indirmelerini sağlayın
Mr./Ms. bir istek aldığınızda dosyaları indirmenize izin verir. O zaman, indirmenin başlangıcını ve sonunu anlamanın kolay olması için sunucuda kasıtlı olarak belirli bir süre bekleriz.
Razor Pages ve MVC'nin sunucu tarafında şunlar olur: Bunu Web API'si gibi diğer projelerde uygulayabilirsiniz.
Razor Sayfaları: Sayfa/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");
}
}
}
İstemci işleme
Normalde, bir web tarayıcısında belirli bir URL'ye erişerek bir dosya indirirsiniz. İndirme işlemi tamamlandıktan sonra bir şeyler yapmak isterseniz, indirmeyi Javascript ile çalıştırabilirsiniz.
Bunu yapmanın birçok yolu vardır, ancak bu durumda, aynı zamanda XMLHttpRequest
asenkron işlemenin kaynağı olan 'yi kullanacağız.
jQuery ajax işlevlerini veya Fetch API'sini de kullanabilirsiniz.
a
href
İndirme URL'si etikete yazılır ve id
olarak download
ayarlanan URL'ye tıklandığında işlem yürütülür.
$('#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
Normalde, öğeyi tıklı bırakırsanız, varsayılan indirme işlemi hareket eder, bu nedenle e.preventDefault();
varsayılan işlemi devre dışı bırakmak için çağrıda bulunuruz.
href
İndirme URL'sini şuradan alın ve XMLHttpRequest
GET
adresinden alacak şekilde ayarlayın.
XMLHttpRequest.responseType
blob
ikili verilerin indirilmesi talimatını vermek için.
XMLHttpRequest.onload
Veri indirme işlemi tamamlandıktan sonraki işlem olayda açıklanabileceğinden, indirme işlemi tamamlandıktan sonraki işlem buraya yazılır.
Veriler yalnızca istemciye indirildiğinden, dosya aslında yerel olarak depolanmaz.
Bir dosyayı yerel olarak kaydetmek için, sahte veriler içeren bir etiket a
ekleyebilir ve bir bağlantıya tıklayıp dosyayı kaydetmişsiniz gibi davranmasını sağlayabilirsiniz.
O andaki window.URL.createObjectURL
veriler işlev tarafından bir URL'ye dönüştürülebilir, böylece href
onu ayarlayabilir ve çalışmasını sağlayabilirsiniz.
Kaydedilecek dosya adı, sunucudan gelen yanıta dahil edilmişse, yanıt başlığından Content-Disposition
alınabilir.
Edinilmesi biraz karmaşık olduğu için kodun olduğu gibi kullanılması gerektiğini düşünüyorum.
Dosya adı sunucuda belirtilmemişse, yardımcı olunamaz, bu yüzden varsayılan dosya adına veya URL yolunun sonundaki dosya adına ayarlanacağını düşünüyorum.
Bu sefer sadece dosyayı kaydettikten sonra konsolda gösterdiğim için, bu kısmı isteğe bağlı kodla yeniden yazarak istenen işlemin gerçekleştirilebileceğini düşünüyorum.
Veri indirme işlemi açıklandıktan sonra, yapmak XMLHttpRequest.send
istediğimiz son şey, isteği gerçekten başlatmak için bir işlev çağırmaktır.
Çalıştırma bağlantısını indir
Mr./Ms. Code, dosyayı doğrudan indirme modeline ve Javascript ile indirme modeline bağlantılar sağlar.
a
URL'yi doğrudan etikete href
yazabilirsiniz, ancak aşağıdakileri ASP.NET Core'a yazarsanız, URL otomatik olarak href
genişleyecektir.
Razor Sayfalar: 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: Görünümler/Ana Sayfa/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>