今回はクラシックASP(Classic ASP)とVBScriptの利用したファイルアップロード用のWebAPIの作成方法を紹介します。
はじめに
自身の職場ではいまだにクラシックASPを使用した業務システムが稼働中であり、今回諸事情があり、試しにファイルをアップロードできるWebAPIを作ってみました。
クラシックASPの記事自体は今でもインターネット上には結構転がっているのですが、「ファイルアップロード」+「WebAPI(ブラウザを使わない)」という条件だとあまり有効な記事も見つからなかったため、ニッチな需要は有るかもと思い記事にしてみます。
正直、requestを投げる先のサーバーでクラシックASP以外のアプリケーションが動かせるなら、そっちを使った方がより楽なので、どうしてもクラシックASPじゃないとダメというケース以外はあまりおすすめしません。
作成するWebAPIの実装概要
今回作るWebAPIでは、以下のような実装をします。
- サーバー側の処理では「クラシックASPとVBScript」+「BASP21」を使用。
- アップロードするファイルはテキスト形式以外にも対応する。
- アップロードするファイルは日本語のファイル名にも対応する。
- クライアント側はVBScriptで作り、バッチ実行を可能とする。
- 認証などのセキュリティへの配慮はしていないので必要によって検討してください。
サンプルブログラム
以下の項目で実際に実装する際のサンプルプログラムを紹介します。
尚、今回のサンプルプログラムを動かすには、ウェブサーバー側に「BASP21」という外部プログラムをインストールする必要があるのと、確実にクラシックASPが動作する環境にしておく必要があるので、そこも併せて紹介します。
事前準備
ASPだけでもサーバー側の実装はできそうな感じもしましたが、「BASP21」は色々と便利そうだったので、今回のサーバー側の処理ではBASP21を利用しています。
よって、対象のウェブサーバーへBASP21のインストールが必要です。
以下のリンクからインストーラーをダウンロードして、サーバーにインストールしてください。
上記サイト内の「Down Load! BASP21-2003-0211.exe (1.44MB) 2003/02/11 Update!」と記載されているリンクが対象のインストーラーです。
尚、自身で検証した結果、インストールしたことによる既存のサーバ環境へ問題は特に発生しませんでしたが、念のため試験環境で検証したうえで導入することを推奨します。
後、現行のIISでクラシックASPの動かす場合、Windows ServerやIISに対していくつかの設定が必要です。
この記事を読んでいるということは、通常はASPを動かせる環境が手元に有るかと思いますが、参考までに以下の記事も目を通しておいてもらうと良いかもしれません。
サーバー側(ASP)プログラム
ファイル名は仮で「file_upload.asp」とします。
以下のプログラムをコピーしてfile_upload.aspに張り付けてください。
<% 'POSTされたファイルが受取れれば1、失敗したら0をResponseで戻します。 Dim objBasp Dim nLength Dim binary Dim UpFileName Dim nRet Dim SaveDir '保存先のディレクトリを指定します。ご自身の環境に合わせて変更してください。' SaveDir = "C:¥UploadedFiles¥" 'BASP21のオブジェクトを生成します。' Set objBasp = Server.CreateObject("basp21") nLength = Request.TotalBytes binary = Request.BinaryRead(nLength) 'カスタムヘッダからファイル名を取得します。' UpFileName = URI_Decode(Request.ServerVariables("HTTP_File-Name")) If Request.TotalBytes Then nRet = objBasp.BinaryWrite(binary,SaveDir & UpFileName) Response.write "1" Else Response.write "0" End If Set objBasp = Nothing 'URIエンコードされた文字列をデコードします。 '関数内部ではJScriptを使用しています。' Function URI_Decode(TargetString) Dim objSC Dim js Dim strDecodeURI Set objSC = CreateObject("ScriptControl") objSC.Language = "JScript" Set js = objSC.CodeObject strDecodeURI = js.decodeURI(TargetString) URI_Decode = strDecodeURI Set objSC = Nothing End Function %>
このサンプルプログラムでは、クライアントからPOSTで渡されたbinary形式のデータをhttp requestで受け取り、request headerに埋め込まれたファイル名を元に、当ASPファイル内で指定されたサーバー内の保存先フォルダにファイルを保存します。
その後データの受け取り結果をResponseでクライアントに返します。
尚、クライアントがファイル名をrequest header内に埋め込み、サーバー側でそのファイル名を取り出す処理では、文字コードを意識しないで実装すると日本語のファイル名は文字化けします。
よって、クライアントがrequest headerにファイル名を埋め込む際に、いったんファイル名をURIエンコードし、当ASPの処理ではファイル名をURIデコードしています。
このエンコードとデコードは共にJScriptを呼び出して処理をさせています。
後、サーバー側で受け取ったファイルの保存先フォルダは、必ずIISの仮想ディレクトリの管轄下に無い、非公開のフォルダを指定してください。
インターネットに公開されているフォルダを保存先に設定してしまうと、インターネットからアップロードしたファイルに自由にアクセスできてしまいます。
クライアント側(VBScript)プログラム
ファイル名は特に指定はないので、自由に決めてください。
取り敢えず今回は仮で「file_upload.vbs」とします。
Option Explicit Call uploadFile Sub uploadFile() Dim Target_URL Dim TargetFileName Dim objHTTP Dim retCd Dim objStream Dim objFS Dim FileName On Error Resume Next 'APIを設置しているURLを指定します。 Target_URL = "http://Target-Server/Test/api/file_upload.asp" 'アップロードするファイル名を指定します。 '※バイナリ形式で送信するため、どんなファイルでも可。 '※後からファイル名もURIエンコードするため、日本語ファイル名も可。 TargetFileName = "C:\upload_file\テストファイル.pdf" '各オブジェクトを生成します。 Set objFS = CreateObject("Scripting.FileSystemObject") Set objHTTP = CreateObject("MSXML2.ServerXMLHTTP") Set objStream = CreateObject("ADODB.Stream") 'ファイルのフルパスからファイル名を取得します。 FileName = objFS.getFileName(TargetFileName) 'ストリームを開きます。 objStream.Open 'ストリームのタイプを1:バイナリで指定します。 objStream.Type = 1 'ストリームにファイルを読み込みます。 objStream.LoadFromFile TargetFileName 'httpメソッドにPOSTを指定して対象のURLを開きます。 objHTTP.Open "POST", Target_URL, False 'ファイル名をRequestHeaderに格納します。 '※日本語ファイル名に対応させるためにURIエンコードします。 objHTTP.setRequestHeader "File-Name",URI_Encode(FileName) 'httpリクエストを送信します。 objHTTP.send objStream.read(objStream.Size) 'ステータスを取得します。 retCd = objHTTP.Status 'ステータスコードで分岐します。 If retCd = 200 Then 'httpステータスが正常時の処理が必要であれば以下に記述します。 'レスポンスの値も受け取り、そこでも然るべき分岐をします。 If objHTTP.ResponseText = "1" Then '然るべき処理。 Else '然るべき処理 End If Else 'httpステータスが正常以外の場合の処理が必要であれば以下に記述します。 End If 'エラー処理 If Err.Number <> 0 Then Msgbox "エラーが発生しました。" & vbCrLf & "エラー番号:" & Err.Number & " エラー内容:" & Err.Description Exit Sub End If '各オブジェクトを破棄します。 objStream.Close Set objFS = Nothing Set objStream = Nothing Set objHTTP = Nothing End Sub '引数の文字列をURIエンコードします。 'VBScriptではちょうど良いエンコード関数が無い為、JScriptの関数を使用します。 Function URI_Encode(TargetString) Dim objSC Dim js Dim strEncodeURI Set objSC = CreateObject("ScriptControl") objSC.Language = "JScript" Set js = objSC.CodeObject strEncodeURI = js.encodeURI(TargetString) URI_Encode = strEncodeURI Set objSC = Nothing End Function
このサンプルプログラムでは、「ADODB.Stream」オブジェクトを生成して、アップロードしたいファイルをそのオブジェクトに格納します。
これは、VBScriptだと普通にはbinaryデータが扱えず、テキスト形式以外のファイルも含めて、どんなファイルでも送れるようにするためです。
また、ファイル名はrequest headerにカスタムした値をセットして、そこで受け渡しするようにしています。
他に上手い方法は有るかもしれませんが、パッと思い付いたのがそれなので。
ファイル名の文字列は、VBScript内でJScriptを呼び出して、JScriptの関数を使用してURIエンコードをしています。
これはVBScriptだとちょうど良いエンコード用の関数が見当たらなかったからです。
このエンコードをしないと、ASP側のサンプルプログラムの項で解説したように日本語のファイル名がサーバー側で文字化けします。
最後に
果たして今回の「クラシックASPで実装したファイルアップロード用WebAPI」に関するサンプルプログラムが今の世の中でどれだけ需要があるのか、ここまで記事を書いて改めて疑問ですが、今回の記事がどこかの誰かの役に立つことがあれば幸いです。
今回も読んでいただきましてありがとうございました。
また次回もよろしくお願いします。
↓あまり需要は無い可能性が高いですが、クラシックASPでファイルをダウンロードするWebAPIのサンプルプログラムも記事にしました。興味がありましたらどうぞ。
↓レガシーなWebシステムでも最新のブラウザ「Edge」のIEモードで使えば動くんです。
是非以下の記事も読んでみてください。