为了使 Request.InputStream 保持活动状态而保留 BinaryReader 对象未释放?

发布于 2024-10-15 15:11:25 字数 1773 浏览 4 评论 0原文

我有几种方法可以使用 Request.InputStream 处理图像的保存。我有两个共享 HttpContext 的扩展。在我的一种方法中,我使用 BinaryReader 读取内容并进行处理。然而,自然地,在处置 BinaryReader 时,它会关闭 Request 上的 InputStream 属性。我的第二种方法使用相同的输入流来创建缩略图。

基本上,我需要一种方法在第一个方法中处理读取器后保持 Request.InputStream 属性处于活动状态。这可能吗?这是我的两种方法。首先调用SaveImageStream(),然后调用GenerateThumbnail()。

public static void SaveImageStream(this HttpContextBase ctx, string filename)
{
    var config = ObjectFactory.GetInstance<IConfig>();

    using (var reader = new BinaryReader(ctx.Request.InputStream))
    {
        var bandImagesPath = config.GetSetting<string>("BandImagePath");
        var path = Path.Combine(ctx.Server.MapPath(bandImagesPath), filename);

        byte[] file = reader.ReadBytes((int)ctx.Request.InputStream.Length);

        using (var outputStream = System.IO.File.Create(path, 2048))
        {
            const int chunkSize = 2 * 1024; // 2KB
            byte[] buffer = new byte[chunkSize];
            int bytesRead;
            ctx.Request.InputStream.Position = 0;
            while ((bytesRead = ctx.Request.InputStream.Read(buffer, 0, buffer.Length)) > 0)
            {
                outputStream.Write(buffer, 0, bytesRead);
            }
        }
    }
}

public static void GenerateThumbnail(this HttpContextBase ctx, string filename)
{
    var config = ObjectFactory.GetInstance<IConfig>();

    int size = config.GetSetting<int>("ThumbSize");
    var thumbPath = Path.Combine(ctx.Server.MapPath(config.GetSetting<string>("ThumbPath")), filename);

    var image = System.Drawing.Image.FromStream(ctx.Request.InputStream);
    var thumb = image.GetThumbnailImage(size, size, null, IntPtr.Zero);

    thumb.Save(thumbPath, System.Drawing.Imaging.ImageFormat.Png);
}

I have a couple methods to handle the saving of an image using Request.InputStream. I have two extensions that share the HttpContext. In one of my methods, I'm using a BinaryReader to read in the contents and do the processing. However, naturally, when disposing the BinaryReader, it closes off the InputStream property on Request. My SECOND method uses the same input stream to create a thumbnail.

Bascially, I need a way to keep the Request.InputStream property alive after disposing the reader in the first method. Is this possible? Here are my two methods. SaveImageStream() is called first, then GenerateThumbnail().

public static void SaveImageStream(this HttpContextBase ctx, string filename)
{
    var config = ObjectFactory.GetInstance<IConfig>();

    using (var reader = new BinaryReader(ctx.Request.InputStream))
    {
        var bandImagesPath = config.GetSetting<string>("BandImagePath");
        var path = Path.Combine(ctx.Server.MapPath(bandImagesPath), filename);

        byte[] file = reader.ReadBytes((int)ctx.Request.InputStream.Length);

        using (var outputStream = System.IO.File.Create(path, 2048))
        {
            const int chunkSize = 2 * 1024; // 2KB
            byte[] buffer = new byte[chunkSize];
            int bytesRead;
            ctx.Request.InputStream.Position = 0;
            while ((bytesRead = ctx.Request.InputStream.Read(buffer, 0, buffer.Length)) > 0)
            {
                outputStream.Write(buffer, 0, bytesRead);
            }
        }
    }
}

public static void GenerateThumbnail(this HttpContextBase ctx, string filename)
{
    var config = ObjectFactory.GetInstance<IConfig>();

    int size = config.GetSetting<int>("ThumbSize");
    var thumbPath = Path.Combine(ctx.Server.MapPath(config.GetSetting<string>("ThumbPath")), filename);

    var image = System.Drawing.Image.FromStream(ctx.Request.InputStream);
    var thumb = image.GetThumbnailImage(size, size, null, IntPtr.Zero);

    thumb.Save(thumbPath, System.Drawing.Imaging.ImageFormat.Png);
}

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

最佳男配角 2024-10-22 15:11:25

您可以使用“装饰器”模式来包装InputStream。查看本文末尾的示例:

http://ydie22.blogspot.com/2008/02/about-idisposable-close-streams-and.html

You could use the "decorator" pattern to wrap the InputStream. Have a look at the end of this post for an example:

http://ydie22.blogspot.com/2008/02/about-idisposable-close-streams-and.html

他是夢罘是命 2024-10-22 15:11:25

通过从一种方法调用另一种方法,您可以在 using 语句中执行所有操作。我还想知道这一行:

byte[] file = reader.ReadBytes((int)ctx.Request.InputStream.Length);

您没有在任何地方使用 file 变量,该变量将整个请求流驻留在内存中。如果您不小心,这将成为拒绝服务攻击的途径。但是解决方案...

将缩略图方法更改为如下所示:

public static void SaveImageStream(this HttpContextBase ctx, string filename)
{
    var config = ObjectFactory.GetInstance<IConfig>();

    using (var reader = new BinaryReader(ctx.Request.InputStream))
    {
        var bandImagesPath = config.GetSetting<string>("BandImagePath");
        var path = Path.Combine(ctx.Server.MapPath(bandImagesPath), filename);

        using (var outputStream = System.IO.File.Create(path, 2048))
        {
            const int chunkSize = 2 * 1024; // 2KB
            byte[] buffer = new byte[chunkSize];
            int bytesRead;
            ctx.Request.InputStream.Position = 0;
            while ((bytesRead = ctx.Request.InputStream.Read(buffer, 0, buffer.Length)) > 0)
            {
                outputStream.Write(buffer, 0, bytesRead);
            }
        }

        ctx.Request.InputStream.Position = 0;
        ctx.GenerateThumbnail(filename);
    }
}

或者,您可以在该 file 属性周围使用 MemoryStream,并将其发送到 GenerateThumbnail 扩展方法。

By calling one method from another, you can do everything within the using statement. I'm also wondering about this line:

byte[] file = reader.ReadBytes((int)ctx.Request.InputStream.Length);

You aren't using the file variable anywhere, which has the entire request stream resident in memory. If you aren't careful this would be an avenue for a Denial of Service attack. But on to the solution...

Change the thumbnail method to look like this:

public static void SaveImageStream(this HttpContextBase ctx, string filename)
{
    var config = ObjectFactory.GetInstance<IConfig>();

    using (var reader = new BinaryReader(ctx.Request.InputStream))
    {
        var bandImagesPath = config.GetSetting<string>("BandImagePath");
        var path = Path.Combine(ctx.Server.MapPath(bandImagesPath), filename);

        using (var outputStream = System.IO.File.Create(path, 2048))
        {
            const int chunkSize = 2 * 1024; // 2KB
            byte[] buffer = new byte[chunkSize];
            int bytesRead;
            ctx.Request.InputStream.Position = 0;
            while ((bytesRead = ctx.Request.InputStream.Read(buffer, 0, buffer.Length)) > 0)
            {
                outputStream.Write(buffer, 0, bytesRead);
            }
        }

        ctx.Request.InputStream.Position = 0;
        ctx.GenerateThumbnail(filename);
    }
}

Alternatively, you can use a MemoryStream around that file attribute, and send that to the GenerateThumbnail extension method.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文