サムネイルを作成して表示する
今回のサンプルプログラムでは、Buttonコントロールを使用して、<input>要素を含んだデフォルトのフォームを送信します。この<input>要素は、ポストされたファイルを保持します。この記事の最後に、サンプルプログラムの完全なコードを示します(リスト2)。完全なコードでは、次の4つのステップを実行しています。
- ポストされたファイルのパスからファイル名を抽出する
- アップロードされたファイルをあらかじめ決められたサーバーパスに保存する
- 画像のサムネイルコピーを保存する
<img>要素のsrc属性をサムネイルの場所に設定する
ユーザーがファイルを送信すると、File1.PostedFile.FileNameにクライアントのローカルパス(ユーザーのマシン上でのファイルの場所)が格納されます。ここからパスなしのファイル名だけを抽出する必要がありますが、これにはSystem.IO.PathクラスのGetFileNameメソッドを使用できます。
前述のSaveUploadedFileメソッドは、PostedFile.SaveAsメソッドを使用して、このファイルを保存します。PostedFile.SaveAsメソッドがMapPathメソッドを使用していることに注目してください。MapPathメソッドは、サーバーサイドの相対パスを物理パスにマッピングします。そして、その物理パスにファイル名を付加し、アップロードされたファイルを保存する場所の完全なパス名を作成します(ファイルをデータベースに保存することも、ファイルの内容をWebページに表示することもできます)。
次のステップでは、サムネイル画像を作成します。SaveThumbnailメソッドによって、画像のサムネイルコピーを作成します。
Private Sub SaveThumbnail(ByVal filename As String)
Dim image As Image = image.FromStream( _
File1.PostedFile.InputStream)
Dim thumbnail As Image = image.GetThumbnailImage( _
100, 100, AddressOf Callback, IntPtr.Zero)
thumbnail.Save(MapPath(GetThumbnailPath(filename)))
End Sub
Private Function GetThumbnailPath( _
ByVal filename As String) As String
Return "~/Images/" + _
String.Format(thumbnailMask, filename)
End Function
SaveThumbnailメソッドは、HttpPostedFileのInputStreamプロパティをImage.FromStreamメソッドに渡すことによって、HttpPostedFileの入力ストリームからメモリ内インスタンスSystem.Drawing.Imageを作成します。次に、ImageのGetThumbnailImageメソッドを呼び出して、画像のサムネイルコピーを作成します。GetThumbnailImageには変わった引数がいくつかありますが、その理由は主に、このメソッドの実装がアンマネージドコードを呼び出すからです。最初の2つの引数は、サムネイル画像の幅と高さです。3番目の引数は使用されないコールバックデリゲートで、使用されなくても渡す必要があります。4番目も使用されない引数で、ネイティブコード呼び出しに対応するための名残です。この最後の引数は、IntPtr.Zeroでなければなりません(以上から分かるように、本当ならばもう少し使いやすいサムネイルラッパーを作成した方がよいでしょう)。このメソッドは最終的に、元の画像と同じ場所にサムネイルを保存します。このとき、サムネイルのファイル名には「thumbnail_」というプレフィックスが付加されます。
最後に、SetPreviewImageメソッドが、サムネイルの仮想パスを使用して、サムネイルを<img>要素のsrcプロパティに割り当てます。
Private Sub SetPreviewImage(ByVal filename As String) PreviewImage.Src = GetThumbnailPath(filename) End Sub
ファイルのアップロードというトピックは少し古くなっていますが、今でも役に立つ話だと思います。サムネイルを作成して表示することは、ユーザーに多数の画像のプレビューを見せてその中からフルサイズの画像を選択させるときに便利な手法です。GetThumbnailImageメソッドはアンマネージド(ネイティブ)コードを呼び出すため、使われない「ジャンクな」引数がいくつかあり、やや扱いにくいものですが、この記事を読めば要点は分かるでしょう。
Imports System.Web
Imports System.IO
Imports System.Drawing
Imports System.Drawing.Drawing2D
Imports System.Drawing.Image
Imports System.Drawing.Imaging
Partial Class _Default
Inherits System.Web.UI.Page
Private Const imagePath As String = "~/Images/"
Private filename As String = ""
Private Const thumbnailMask As String = "thumbnail_{0}"
Protected Sub Button1_Click(ByVal sender As Object, _
ByVal e As System.EventArgs) Handles Button1.Click
ProcessPostedFile()
End Sub
Private Sub ProcessPostedFile()
filename = Path.GetFileName(File1.PostedFile.FileName)
SaveUploadedFile(filename)
SaveThumbnail(filename)
SetPreviewImage(filename)
End Sub
Private Sub SaveUploadedFile(ByVal filename As String)
File1.PostedFile.SaveAs(MapPath(imagePath) + filename)
End Sub
Private Function Callback() As Boolean
Return False
End Function
Private Sub SaveThumbnail(ByVal filename As String)
Dim image As Image = _
image.FromStream(File1.PostedFile.InputStream)
Dim thumbnail As Image = image.GetThumbnailImage( _
100, 100, AddressOf Callback, IntPtr.Zero)
thumbnail.Save(MapPath(GetThumbnailPath(filename)))
End Sub
Private Function GetThumbnailPath(ByVal filename As String) As String
Return "~/Images/" + String.Format(thumbnailMask, filename)
End Function
End Class
