1
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

【React】Qiita記事を.mdで複数ダウンロードできないバグを解決した話

Posted at

はじめに

Qiita API から取得したQiitaに投稿された記事を、React で .md ファイルとしてダウンロードできるアプリを作っていましたが、
「複数チェックして一括ダウンロードしているのに、1件しか落ちない」 という問題にハマりました。

この記事では、実際に起きた症状、なぜ 1 件しかダウンロードされなかったのか(根本原因)を整理して共有します。

原因

結論から言うと、URL.revokeObjectURL(url) を早く呼びすぎたことが原因でした。

一括ダウンロードの処理の流れを整理すると以下のようになります。

1.記事本文から Blob を作る(Blobとはデータを入れておくための箱、ファイルの中身をJavascriptで扱うための仕組み)

2.URL.createObjectURL(blob) で “一時的なURL” を作る(URL.createObjectURL(blob)とは、Blobにアクセスするための一時的にURLを自動生成する関数)

3.a.href = url → click() でダウンロードを開始

使い終わったら URL.revokeObjectURL(url) で破棄
(URL.revokeObjectURL(url)とは、一時URLを削除する関数)

以下のコードに今回の問題点があります。

const url = URL.createObjectURL(blob);
a.href = url;
a.click();
URL.revokeObjectURL(url); // ← ここをすぐ呼んでいた

ブラウザがまだダウンロードを開始しきっていない状態で URL を破棄してしまうため、
1 件目は動いたのですが、2 件目以降の URL が無効になってしまい、結果 1 件しか落ちないという現象になっていました。

解決方法

URL.revokeObjectURL(url) を少し遅らせて呼ぶよう修正しました。

最終的に安定動作したコード

const handleDownload = (title: string, body: string) => {
  const blob = new Blob([body], { type: "text/markdown" });
  const url = URL.createObjectURL(blob);

  const a = document.createElement("a");
  a.href = url;
  a.download = `${title}.md`;
  a.click();

  // すぐ破棄するとダウンロードが壊れる → 少し待つ
  setTimeout(() => URL.revokeObjectURL(url), 100);
};

複数記事をチェックして一括ダウンロードしても、すべて正常に保存されるようになりました。

まとめ

適切に遅延させると複数ダウンロードが安定して動く

1
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?