"Javascript", kad būtų galima atlikti apdorojimą atsisiuntus failą

Puslapis atnaujintas :
Puslapio sukūrimo data :

Veikimo tikrinimo aplinka

Vizualinė studija
  • "Visual Studio 2022"
ASP.NET branduolys
  • 8.0 ("Razpr" puslapiai, MVC)
Žiniatinklio naršyklės
  • kraštas 119

Darbo aplinka

"Visual Studio" (jei taip pat įtraukiate serverio programas)
  • "Visual Studio 2022"
ASP.NET Core (jei jame taip pat yra serverio programų)
  • 8.0 ("Razpr" puslapiai, MVC)
Žiniatinklio naršyklės
  • Kraštas
  • "Google Chrome"
  • Kitos naršyklės (ne visos patikrintos)

(* Pagrindinis šio patarimo elementas yra kliento pusės procesas, todėl serverio pusė gali būti bet kas)

Iš pradžių

Pagrindinis šių patarimų dėmesys skiriamas kliento programai ("Javascript"), o serverio programa yra tik failams atsisiųsti. Todėl nesvarbu, kokia yra serverio programa, jei ji gali priversti jus atsisiųsti failą.

Ar vartotojai atsisiunčia failus, kai jie pasiekiami serveryje

Mr./Ms. leidžia atsisiųsti failus, kai gaunate užklausą. Tuo metu mes sąmoningai laukiame tam tikro laiko serveryje, kad būtų lengva suprasti atsisiuntimo pradžią ir pabaigą.

Štai kas vyksta "Razor Pages" ir "MVC" serverio pusėje: Jį galite įdiegti kituose projektuose, pvz., žiniatinklio API.

Skustuvo puslapiai : Puslapiai/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");
    }
  }
}

Kliento apdorojimas

Paprastai failą atsisiunčiate žiniatinklio naršyklėje pasiekdami nurodytą URL. Jei norite ką nors padaryti, kai atsisiuntimas bus baigtas, galite paleisti atsisiuntimą naudodami "Javascript".

Yra daug būdų tai padaryti, tačiau šiuo atveju mes naudosime , kuris taip pat XMLHttpRequest yra asinchroninio apdorojimo kilmė. Taip pat galite naudoti jQuery ajax funkcijas arba Fetch API.

ahref Atsisiuntimo URL įrašomas į žymą ir id procesas vykdomas, kai spustelėjamas tas, kuris nustatytas į download būseną.

$('#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 Paprastai, jei paliksite elementą spustelėtą, numatytasis atsisiuntimo procesas bus perkeltas, todėl e.preventDefault(); raginame išjungti numatytąjį procesą.

href Gaukite atsisiuntimo URL iš ir XMLHttpRequest GET nustatykite, kad jis gautų iš .

XMLHttpRequest.responseTypeblob nurodyti atsisiųsti dvejetainius duomenis.

XMLHttpRequest.onload Kadangi procesas po duomenų atsisiuntimo gali būti aprašytas įvykio metu, procesas po atsisiuntimo yra parašytas čia. Kadangi duomenys buvo atsisiųsti tik į klientą, failas iš tikrųjų nėra saugomas vietoje. Norėdami išsaugoti failą vietoje, galite pridėti žymą, kurioje a yra pseudoduomenų, ir priversti jį elgtis taip, lyg būtumėte spustelėję nuorodą ir išsaugoję failą. Tuo metu duomenis funkcija gali window.URL.createObjectURL konvertuoti į URL, kad href galėtumėte juos nustatyti ir priversti juos veikti.

Įrašytiną failo vardą galima nuskaityti iš atsakymo antraštės, jei jis įtrauktas į serverio atsakymą Content-Disposition . Kadangi tai yra šiek tiek sudėtinga įsigyti, manau, kad kodas turėtų būti naudojamas toks, koks yra. Jei failo vardas nenurodytas serveryje, jam negalima padėti, todėl manau, kad URL kelio pabaigoje jis bus nustatytas į numatytąjį failo pavadinimą arba failo pavadinimą.

Kadangi šį kartą aš jį rodau konsolėje tik išsaugojęs failą, manau, kad norimą operaciją galima atlikti perrašant šią dalį savavališku kodu.

Aprašius duomenų atsisiuntimo procesą, paskutinis dalykas, kurį norime padaryti, yra XMLHttpRequest.send iškviesti funkciją, kad iš tikrųjų pradėtume užklausą.

Atsisiųskite paleidimo nuorodą

Mr./Ms. Code pateikia nuorodas į tiesioginio failo atsisiuntimo modelį ir jo atsisiuntimo naudojant "Javascript" modelį. a URL galite įrašyti tiesiai į href žymą, bet jei "ASP.NET Core" parašysite toliau nurodytus dalykus, URL bus automatiškai href išplėstas į .

Skustuvo puslapiai : 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 : Peržiūros/Pagrindinis/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>