4

PNG をメモリ ストリームに保存しようとすると、エラーが発生します。ASP.NET 開発サーバーではすべてが機能しますが、IIS7 でサイトを実行するとエラーが発生します。また、jpg形式で保存しようとすると、すべてが正しくなります。IIS では、.NET Trusted Level を Full に設定しています。しかし、それでもうまくいきません。あなたの助けが必要です。

private static Stream DrawBarChart(IEnumerable<Tuple<string, ulong, double>> data){
using (MemoryStream stream = new MemoryStream())
{
    var canvasWidth = PageSize.A4.Width;
    var canvasHeight = PageSize.A4.Height;

    using (
        System.Drawing.Image bitmap = new Bitmap((int) canvasWidth,
                                                 (int) canvasHeight))
    {
        using (var graphics = Graphics.FromImage(bitmap))
        {
            var penBlack1 = new Pen(Brushes.Black, 1);

            graphics.DrawLine(penBlack1, 0, 0, canvasWidth, 0);
            graphics.DrawLine(penBlack1, 0, 0, 0, canvasHeight);

            graphics.Save();
        }
        bitmap.Save(stream, ImageFormat.Png);

    stream.Flush();
    stream.Position = 0;

    return stream;
    }
}

}

4

1 に答える 1

3

コードには、誤動作の原因となる完全に独立した問題が少なくとも 2 つあります。

問題 #1: GDI+ エラー

これは、エコシステムのいたるところで発生し続ける、繰り返し発生する問題です。私はそれを持っていました、私はそれを修正することができましたが、今では正確にどのように思い出せません. 問題を再現しようとしましたが、エラーを受け取ることができませんでした。

このスレッドを確認することをお勧めします : http://forums.asp.net/t/624305.aspx/1

  • 他の描画を続行する前に、すべての Bitmap インスタンスを破棄したことを確認する
  • (興味深いもの): GC.Collect()の実行 (おそらく各ビットマップのレンダリング後)

これは、私があなたに答えを出そうとした主な理由ではありません. あなたは、私がこのような状況に陥らないようにするために私が普段行っているすべてのこと (セキュリティ、信頼など) を既に行っているようです (あなたは行ったと言っています)。さらに、必要以上に自分の後片付けをします(私の回答を読んでいるときにわかるように、少し多すぎます)。

あなたのコードには、おそらく気付いていない 2 つ目の問題があることがわかりました。私自身の VS 環境でその問題を解決するだけで、(IIS 7 と Express と ASP 開発サーバーの両方で) ビットマップのレンダリングに成功しました。

アプリケーションのコードを少し再編成することで、問題 1 を解決できる可能性が高くなります。だから:問題#2について私が言わなければならないことをチェックしてください.

問題 #2: ストリームを同時に破棄して返すことはできません

次のように、作成して破棄したばかりのストリームを行って返すことはできません。

public static Stream SomeMethod() {
  using (MemoryStream stream = new MemoryStream()) {
    // write something to the stream
    return stream;
  }
}

そのコードが ASP.NET 開発サーバーで実際にどのように機能するのか、私にはよくわかりません。ここで指摘しようとしている問題は、コードが常に ObjectDisposedException をスローすることです (コードをサービスとして実行しているか、インタラクティブなユーザー空間で実行しているかに関係なく)。

閉じたストリームにアクセスできません

誰がストリームを閉じますか? usingステートメントの終了。

問題#2の可能な解決策

この特定の問題 (予想よりも多くのメモリを消費する可能性がある) の簡単な解決策は、メソッドがストリームではなく byte[] を返すようにすることです。

public static byte[] SomeMethod() {
  using (MemoryStream stream = new MemoryStream()) {

    // ... create bitmap and render things ...

    // write something to the stream
    bitmap.Save(stream, ImageFormat.Png);

    return stream.ToArray();
  }
}

アプリケーションのニーズについて自分で推測できるようにすることで、この他のソリューションの方がさらに優れていると思います。

これらの生成されたチャート イメージを< img >タグに戻して Web ブラウザーに戻したい場合、たとえば ASP.NET ジェネリック ハンドラーを使用してこれを実現している場合は、次の OutputStream を渡すことができます。次のように、結果の byte[] (または Stream) を取得する代わりに、現在の WebResponse を描画メソッド渡します

HTML の場合:

<img src="path/Foo.ashx" alt="chart" ... etc ... />

アプリを起動中:

public class Foo : IHttpHandler {
  public void ProcessRequest(HttpContext context) {

   context.Response.ContentType = "application/octet-stream";
   Stream alreadyExistingStream = context.Response.OutputStream;

   Etc.SomeMethod(stream);       
  }
}

public class Etc {

public static void SomeMethod(Stream stream) {
  // There used to be a using here that would create a stream
    // simply because the parameter name **stream** is the same as the former local var's name
    // the instructions that do the drawing of things 
    // + saving of the resulting Bitmap **to** the stream
    // keep on compiling without any problems

    // draw things to a bitmap
    // write the bitmap to the stream
    bitmap.Save(stream, ImageFormat.Png);

    // returning stuff is not needed anymore
  // This used to be the time and place where the stream would be disposed
  // and it's resources given back to the community
}

}
于 2013-02-23T18:16:40.980 に答える