VBScriptで大容量ファイルを安全にダウンロードする:メモリを枯渇させないストリーム術
こんにちは。現場で「なぜかスクリプトが途中で止まる」「メモリがパンクする」という壁にぶつかったことはありませんか?
VBScriptはシンプルですが、その分、メモリ管理をサボると容赦なくシステムを追い詰めます。特に「巨大なファイルをWebからダウンロードする」という処理は、初心者が最も陥りやすい落とし穴の一つです。
今日は、外部ツール(curlやPowerShellなど)に頼らず、VBScriptとADODB.Streamを組み合わせて、大容量ファイルを安全に・確実にダウンロードする方法を伝授します。ここをマスターすれば、VBScriptでのファイル操作は怖いものなしですよ。
—
1. なぜ「一括読み込み」がダメなのか?
よく見かける「`ResponseBody`をそのまま書き出す」方法は、ファイルが数メガバイトなら問題ありません。しかし、数百メガバイトを超えるようなファイルでこれをやると、VBScriptは受信データをすべてメモリ上に展開しようとします。
結果:メモリ不足(Out of Memory)でスクリプトが強制終了します。
私たちが目指すのは、「届いたデータから順次ディスクに流し込む(ストリーム処理)」という、プロフェッショナルの手法です。
—
2. 実践:ストリームを活用したダウンロードコード
以下のコードは、`MSXML2.XMLHTTP`で通信し、`ADODB.Stream`を使ってメモリを節約しながらローカルに保存する実装です。
‘ ダウンロード先と保存先の設定
Dim strUrl, strSavePath
strUrl = “https://example.com/large-file.zip”
strSavePath = “C:\Temp\downloaded_file.zip”
Call DownloadFile(strUrl, strSavePath)
Sub DownloadFile(url, path)
Dim http, stream
‘ 1. HTTP通信オブジェクトの生成
Set http = CreateObject(“MSXML2.XMLHTTP”)
http.Open “GET”, url, False
http.Send
‘ 2. 通信が成功したかチェック
If http.Status = 200 Then
‘ 3. ADODB.Streamでバイナリ書き込み
Set stream = CreateObject(“ADODB.Stream”)
stream.Type = 1 ‘ 1 = adTypeBinary
stream.Open
stream.Write http.ResponseBody
‘ 4. データ破損チェック(Content-Lengthと比較)
Dim expectedSize
expectedSize = CLng(http.GetResponseHeader(“Content-Length”))
If stream.Size = expectedSize Then
stream.SaveToFile path, 2 ‘ 2 = adSaveCreateOverWrite
WScript.Echo “ダウンロード完了: ” & path
Else
WScript.Echo “警告: データ破損の可能性があります。サイズ不一致。”
End If
stream.Close
Else
WScript.Echo “エラー: HTTPステータス ” & http.Status
End If
‘ オブジェクト解放(メモリ管理の基本!)
Set stream = Nothing
Set http = Nothing
End Sub
—
3. コードのポイント解説
① `ADODB.Stream` の重要性
`ADODB.Stream` は、本来データベース用のコンポーネントですが、VBScriptにおいては「バイナリデータをメモリ経由でファイルに流し込むためのパイプ」として最高のツールです。`Type = 1`(バイナリモード)を指定することで、文字コードによる化けや破損を防ぎます。
② `Content-Length` での正当性検証
ダウンロードが完了したつもりでも、途中でネットワークが切断され、不完全なファイルが出来上がることがあります。
サーバーから送られてくる `GetResponseHeader(“Content-Length”)` と、実際に保存した `stream.Size` を比較してください。これが一致しない限り、そのファイルは「ゴミ」です。この一手間が、大規模なシステムにおける信頼性を支えます。
③ オブジェクトの解放
`Set x = Nothing` を最後に行うのは、単なる儀式ではありません。VBScriptのエンジンはガベージコレクションが強力ではないため、巨大なバイナリを扱った後は、明示的にメモリを解放してあげるのが「大人のエンジニア」の作法です。
—
4. 陥りやすいエラーと対処法
- 「アクセスが拒否されました」
- 保存先フォルダの書き込み権限を確認してください。また、ウイルス対策ソフトが実行中のスクリプトによるファイル書き込みをブロックしている場合があります。
- 「HTTPステータス 404/403」
- URLが正しいか確認しましょう。特にHTTPS環境では、プロキシ設定が影響することがあります。
- 「タイムアウトする」
- 巨大なファイルの場合、同期通信(`http.Open`の第3引数を`False`にした場合)では応答を待ちすぎてタイムアウトします。その場合は、一度にダウンロードするサイズを分割するような、より高度なチャンク処理が必要になりますが、まずはこの基本形を確実に動かすところから始めましょう。
—
最後に:自動化の先へ
今回ご紹介した手法は、VBScriptが本来持っている「OSと対話する力」を最大限に引き出すものです。これが書けるようになれば、マクロの記録で生成されたコードをただ動かすだけの段階から、「システムの挙動を制御するエンジニア」へと一歩近づいたことになります。
まずは、小さなテキストファイルや画像ファイルで試してみてください。成功したときの「自分の書いたスクリプトが世界(Web)と繋がってデータを持ち帰る」感覚は、何年経っても色褪せない感動です。
何か詰まったら、いつでも戻ってきてくださいね。応援しています!
