Javascript pour effectuer un traitement après le téléchargement d’un fichier

Page mise à jour :
Date de création de la page :

Environnement de vérification des opérations

Studio visuel
  • Visual Studio 2022
ASP.NET Noyau
  • 8.0 (Pages Razpr, MVC)
Navigateurs Web
  • Bord 119

Environnement d’exploitation

Visual Studio (si vous incluez également des programmes serveur)
  • Visual Studio 2022
ASP.NET Core (s’il comprend également des programmes serveur)
  • 8.0 (Pages Razpr, MVC)
Navigateurs Web
  • Bord
  • Google Chrome
  • Autres navigateurs (pas tous cochés)

(* Le corps principal de cette astuce est le processus côté client, donc le côté serveur peut être n’importe quoi)

Au début

L’objectif principal de ces conseils est le programme client (Javascript), et le programme serveur n’est là que pour télécharger des fichiers. Par conséquent, peu importe le programme serveur, tant qu’il peut vous faire télécharger le fichier.

Demandez aux utilisateurs de télécharger des fichiers lorsqu’ils sont consultés sur le serveur

M./Mme. vous permet de télécharger des fichiers lorsque vous recevez une demande. À ce moment-là, nous attendons délibérément un certain temps sur le serveur afin qu’il soit facile de comprendre le début et la fin du téléchargement.

Voici ce qui se passe côté serveur de Razor Pages et MVC : Vous pouvez l’implémenter dans d’autres projets, tels que l’API Web.

Razor Pages : Pages/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");
    }
  }
}

Traitement des clients

Normalement, vous téléchargez un fichier en accédant à une URL spécifiée dans un navigateur Web. Si vous souhaitez faire quelque chose une fois le téléchargement terminé, vous pouvez exécuter le téléchargement avec Javascript.

Il existe de nombreuses façons de le faire, mais dans ce cas, nous utiliserons , qui est également XMLHttpRequest à l’origine du traitement asynchrone. Vous pouvez également utiliser les fonctions ajax jQuery ou l’API Fetch.

ahref L’URL de téléchargement est écrite dans la balise et id le processus est exécuté lorsque l’on clique sur celle définie surdownload.

$('#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 Normalement, si vous laissez l’élément cliqué, le processus de téléchargement par défaut se déplacera, nous appelons donc e.preventDefault(); pour désactiver le processus par défaut.

href Obtenez l’URL de téléchargement à partir de et XMLHttpRequest GET configurez-la pour l’obtenir à partir de .

XMLHttpRequest.responseTypeblob pour indiquer les données binaires à télécharger.

XMLHttpRequest.onload Étant donné que le processus après la fin du téléchargement des données peut être décrit dans l’événement, le processus après la fin du téléchargement est écrit ici. Comme les données n’ont été téléchargées que sur le client, le fichier n’est pas réellement stocké localement. Pour enregistrer un fichier localement, vous pouvez ajouter une balise contenant a des pseudo-données et la faire se comporter comme si vous aviez cliqué sur un lien et enregistré le fichier. Les données à ce moment-là peuvent window.URL.createObjectURL être converties en URL par la fonction, vous pouvez donc href la définir et la faire fonctionner.

Le nom du fichier à enregistrer peut être récupéré à partir de l’en-tête de réponse s’il est inclus dans la réponse du Content-Disposition serveur. Comme il est un peu compliqué à acquérir, je pense que le code doit être utilisé tel quel. Si le nom du fichier n’est pas spécifié sur le serveur, il ne peut pas être aidé, donc je pense qu’il sera défini sur le nom de fichier par défaut ou le nom de fichier à la fin du chemin d’URL.

Comme cette fois je ne l’affiche dans la console qu’après avoir enregistré le fichier, je pense que l’opération souhaitée peut être exécutée en réécrivant cette partie avec du code arbitraire.

Une fois le processus de téléchargement des données décrit, la dernière chose que nous voulons faire est XMLHttpRequest.send d’appeler une fonction pour démarrer la requête.

Télécharger le lien de l’exécution

Mr./Ms. Code fournit des liens vers le modèle de téléchargement direct du fichier et le modèle de téléchargement avec Javascript. a Vous pouvez écrire l’URL directement dans la href balise, mais si vous écrivez ce qui suit dans ASP.NET Core, l’URL se développera automatiquement href en .

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 : Vues/Accueil/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>