3

ご挨拶!

画像を返す Web フォーム プロトタイプ (ImageLaoder.aspx) を作成しているため、他の Web フォーム/Web ページの簡単な例のように使用できます。

<img src="http://www.mydomain.com/ImageLoader.aspx?i=http://images.mydomain.com/img/a.jpg" />

これまでのところ、JPG は問題なくロードされますが、GIF はオリジナルに比べて「粗く」見え、BMP と PNG は次の例外が発生します。

System.Runtime.InteropServices.ExternalException: GDI+ で一般的なエラーが発生しました

これまでの私のコードは次のようになります。

protected void Page_Load(object sender, EventArgs e)
{
    string l_filePath = Request.QueryString["i"];

    System.Drawing.Image l_image = GetImage(l_filePath);
    if (l_image != null)
    {
        System.Drawing.Imaging.ImageFormat l_imageFormat = DetermineImageFormat(l_filePath);
        WriteImageAsReponse(l_image, l_imageFormat);
    }
}

private System.Drawing.Image GetImage(string filePath)
{
    WebClient l_WebClient = new WebClient();
    byte[] l_imageBytes = l_WebClient.DownloadData(filePath);

    System.Drawing.Image l_image = null;
    using (MemoryStream l_MemStream = new MemoryStream(l_imageBytes, 0, l_imageBytes.Length))
    {
        l_MemStream.Write(l_imageBytes, 0, l_imageBytes.Length);
        l_image = System.Drawing.Image.FromStream(l_MemStream, true);
        l_MemStream.Close();
    }

    return l_image;
}

private System.Drawing.Imaging.ImageFormat DetermineImageFormat(string filePath)
{
    if (filePath.EndsWith(".jpg", StringComparison.OrdinalIgnoreCase))
        return System.Drawing.Imaging.ImageFormat.Jpeg;
    else if (filePath.EndsWith(".gif", StringComparison.OrdinalIgnoreCase))
        return System.Drawing.Imaging.ImageFormat.Gif;
    else if (filePath.EndsWith(".png", StringComparison.OrdinalIgnoreCase))
        return System.Drawing.Imaging.ImageFormat.Png;
    else
        return System.Drawing.Imaging.ImageFormat.Bmp;
}

private void WriteImageAsReponse(System.Drawing.Image image, System.Drawing.Imaging.ImageFormat imageFormat)
{
    if (image == null)
        return;

    System.Drawing.Bitmap l_outputBitMap = new Bitmap(image);

    if (imageFormat == System.Drawing.Imaging.ImageFormat.Jpeg)
        Response.ContentType = "image/jpg";
    else if (imageFormat == System.Drawing.Imaging.ImageFormat.Gif)
        Response.ContentType = "image/gif";
    else if (imageFormat == System.Drawing.Imaging.ImageFormat.Png)
        Response.ContentType = "image/png";
    else
        Response.ContentType = "image/bmp";

    l_outputBitMap.Save(Response.OutputStream, imageFormat);
}

GIF が粗く、PNG と BMP が例外を引き起こす理由はありますか?

4

1 に答える 1

19

GetImage メソッドに関するいくつかのポイント:

  • Image.FromStream を使用する場合、ストリームを閉じる (または破棄する) べきではありません
  • ストリームで (using ステートメントを使用して) Dispose を呼び出している場合は、Close を呼び出す必要はありません。
  • あなたはストリームに書き込んでいますが、「巻き戻し」はしていないので、 l_image は私が見る限り実際にはデータを取得しません (Image.FromStream が位置自体をリセットしない限り)。(gif/jpg デコーダーはストリームを巻き戻しますが、bmp/png は巻き戻さないため、エラーが発生する可能性があります。)
  • バイト配列を取る MemoryStream コンストラクターを使用しないのはなぜですか?

つまり、GetImage メソッドを次のように置き換えることができると思います。

private Image GetImage(string filePath)
{
    WebClient l_WebClient = new WebClient();
    byte[] l_imageBytes = l_WebClient.DownloadData(filePath);
    MemoryStream l_stream = new MemoryStream(l_imageBytes);
    return Image.FromStream(l_stream);
}

さて、もっと重要なことは、なぜ画像をロードしているのかということです。ファイル自体を応答として提供して、既に行っているようにコンテンツ タイプを設定しないのはなぜですか。つまり、すべてのコードは次のようになります。

protected void Page_Load(object sender, EventArgs e)
{
    string filePath = Request.QueryString["i"];
    string extension = l_filePath.Substring(l_filePath.LastIndexOf('.') + 1);
    Response.ContentType = "image/" + extension;
    byte[] data = new WebClient.DownloadData(filePath);
    Response.OutputStream.Write(data, 0, data.Length);
    Response.End();
}

もう少しエラー処理 (「これは合理的な拡張機能ですか?」など) があればいいのですが、それ以外は問題ないと思います。イメージを自分で実際にロードする唯一の利点は、それがウイルスなどではなく、実際にイメージであることを検証できることです。

編集: 興味がないだけですが、画像リクエストをサーバーに送信する正当な理由はありますか? Web ページの作成者はなぜ次のように書くのでしょうか。

<img src="http://www.mydomain.com/ImageLoader.aspx?i=http://images.mydomain.com/img/a.jpg" />

それ以外の

<img src="http://images.mydomain.com/img/a.jpg" />

便利な理由いくつかありますが、多くの場合、無駄です。

于 2009-01-31T17:38:35.717 に答える