JavaScript Tips | 文字列ユーティリティ:URL 系 - ファイル名取得

JavaScript JavaScript
スポンサーリンク

何をしたいユーティリティか:「ファイル名取得」

ここで作りたいのは、URL やパス文字列から「ファイル名だけ」を取り出す小さな関数です。

例えば、こういうイメージです。

https://example.com/assets/logo.png"logo.png"
/downloads/archive.zip"archive.zip"
/path/to/dir/""(ファイル名なしとみなす)
/path/to/file"file"

「拡張子取得」と違って、ここでは「最後のパス要素そのもの」が欲しい、というユーティリティです。
ダウンロード時のデフォルトファイル名に使ったり、ログ表示に使ったり、地味だけどよく出てきます。


ファイル名取得の基本的な考え方

どこからどこまでを「ファイル名」とみなすか

ファイル名取得でやりたいことは、ざっくり言うとこうです。

  1. URL からクエリ(?以降)やハッシュ(#以降)を取り除く。
  2. 残ったパスのうち、「最後の / 以降」をファイル名とみなす。
  3. その部分が空なら「ファイル名なし」と判断する。

例えば、https://example.com/assets/logo.png?version=1#top なら、

URL 全体 → https://example.com/assets/logo.png?version=1#top
クエリ・ハッシュ除去 → https://example.com/assets/logo.png
最後の / 以降 → logo.png

という流れです。


一番シンプルな「ファイル名取得」関数

URL 文字列からファイル名を取る getFileName

まずは、クエリやハッシュを無視して、「パス部分だけからファイル名を取る」関数を作ります。

function getFileName(url) {
  if (!url) return "";

  const str = String(url);

  const pathWithoutQuery = str.split(/[?#]/)[0];

  const lastSlashIndex = pathWithoutQuery.lastIndexOf("/");

  const filename =
    lastSlashIndex >= 0
      ? pathWithoutQuery.slice(lastSlashIndex + 1)
      : pathWithoutQuery;

  if (!filename) {
    return "";
  }

  return filename;
}
JavaScript

重要なポイントをかみ砕いて説明する

ここがこのユーティリティの核なので、順番に見ていきます。

クエリとハッシュを先に落とす

const pathWithoutQuery = str.split(/[?#]/)[0];
JavaScript

URL には、? 以降のクエリや # 以降のハッシュが付いていることがよくあります。

/assets/logo.png?version=1#top のようなケースです。

ファイル名を取りたいのは「パス部分」だけなので、
? または # で分割して、一番前の部分だけを使います。

結果として、/assets/logo.png だけが残ります。

最後の / 以降を「ファイル名」とみなす

const lastSlashIndex = pathWithoutQuery.lastIndexOf("/");

const filename =
  lastSlashIndex >= 0
    ? pathWithoutQuery.slice(lastSlashIndex + 1)
    : pathWithoutQuery;
JavaScript

lastIndexOf("/") は「一番後ろの / の位置」を返します。

/assets/logo.png の場合、/assets/logo.png の境目の / の位置が返ってきます。
そこから +1 した位置から最後までを slice すると、logo.png になります。

もし / が含まれていない場合(単なる "logo.png""file" など)は、
全体をそのままファイル名とみなします。

ファイル名が空なら「なし」とみなす

if (!filename) {
  return "";
}
JavaScript

/path/to/dir/ のように、最後が / で終わっている場合を考えます。

"/path/to/dir/".lastIndexOf("/") は末尾の / の位置になります。
そこから +1 して slice すると、空文字列になります。

この場合は「ファイル名ではなくディレクトリ」とみなして、空文字を返すようにしています。


実際の動きを例で確認する

典型的な URL の例

getFileName("https://example.com/assets/logo.png");
// "logo.png"

getFileName("/downloads/archive.zip");
// "archive.zip"

getFileName("/path/to/file");
// "file"
JavaScript

最後のパス要素が、そのままファイル名として取れているのが分かると思います。

クエリやハッシュ付きの例

getFileName("/assets/logo.png?version=1");
// "logo.png"

getFileName("/assets/logo.png#top");
// "logo.png"

getFileName("/assets/logo.png?version=1#top");
// "logo.png"
JavaScript

クエリやハッシュは先に切り落としているので、
ファイル名取得には影響しません。

ディレクトリっぽいパスの例

getFileName("/path/to/dir/");
// ""(ファイル名なし)

getFileName("/path/to/dir");
// "dir"(最後の要素をファイル名とみなす)
JavaScript

ここは設計の好みが分かれるところですが、
「末尾が / で終わっているものはディレクトリ扱い」として、
ファイル名なし(空文字)を返すようにしています。


拡張子取得と組み合わせる

ファイル名と拡張子を両方使いたい場合

前に作った getExtension と組み合わせると、
「ファイル名」と「拡張子」を両方扱えるようになります。

例えば、こんなユーティリティが書けます。

function getFileNameWithoutExtension(url) {
  const filename = getFileName(url);
  if (!filename) return "";

  const lastDotIndex = filename.lastIndexOf(".");
  if (lastDotIndex <= 0) {
    return filename;
  }

  return filename.slice(0, lastDotIndex);
}
JavaScript

動きはこうです。

getFileNameWithoutExtension("https://example.com/assets/logo.png");
// "logo"

getFileNameWithoutExtension("/downloads/archive.tar.gz");
// "archive.tar"

getFileNameWithoutExtension("/path/to/file");
// "file"

getFileNameWithoutExtension("/path/to/dir/");
// ""
JavaScript

getFileName で「最後の要素」を取り、
そこからさらに「最後のドットより前」を取り出す、という二段構えです。


実務での使いどころと設計のポイント

ダウンロード時のデフォルト名に使う

例えば、API から返ってきた URL をそのままダウンロードリンクに使うとき、
「保存ダイアログに出すデフォルト名」を決めたいことがあります。

const url = "https://example.com/files/report_2025-01-01.xlsx";

const filename = getFileName(url) || "download.dat";
JavaScript

こうしておけば、URL にファイル名が含まれていればそれを使い、
なければフォールバックの名前を使う、という挙動にできます。

ログや UI 表示で「最後の要素だけ見せたい」場合

長いパス全体ではなく、「最後のファイル名だけ」を表示したい場面も多いです。

const url = "/uploads/user/12345/avatar.png";

console.log("アップロードされたファイル:", getFileName(url));
// "アップロードされたファイル: avatar.png"
JavaScript

ユーザーに見せるときも、
/uploads/user/12345/avatar.png より avatar.png の方が親切なことが多いです。

「パスの構造」と「ファイル名」を分けて考える

URL を扱うときは、

パス全体(どこにあるか)
ファイル名(何という名前か)
拡張子(どんな種類か)

を分けて考えると、設計がきれいになります。

今回の getFileName は、そのうち「ファイル名」の部分だけを取り出す役割です。
joinPathgetExtension と組み合わせると、URL 周りの処理がかなり整理されます。


ちょっとだけ手を動かしてみる

コンソールで、次のあたりを試してみてください。

getFileName("https://example.com/assets/logo.png");
getFileName("/downloads/archive.zip?version=3");
getFileName("/path/to/file");
getFileName("/path/to/dir/");
getFileName("file-only.txt");
JavaScript

「どの部分がファイル名として取れて、どのケースで空文字になるか」を、
自分の目で確認してみてください。

そのうえで、自分のプロジェクトに

export function getFileName(url) { ... }
export function getFileNameWithoutExtension(url) { ... }
JavaScript

を置いて、

ファイル名が欲しくなったら、
毎回 split("/") ではなく、必ず getFileName を通す、というルールにしてみてください。

それだけで、あなたの「ファイル名扱い」は、
場当たり的な文字列操作から、意図がはっきりした“業務レベルのファイル名取得ユーティリティ”に一段レベルアップします。

タイトルとURLをコピーしました