如何将HttpPostedFileBase转换为图像?

52

我正在使用ASP.NET MVC,有一个上传文件的操作,文件已经成功上传。但我想获取图像的宽度和高度。我认为我需要首先将HttpPostedFileBase转换为Image,然后再进行下一步。如何操作?

如果有更好的方法获取图像的宽度和高度,请告诉我。

2个回答

109

我使用 Image.FromStream 方法,如下所示:

Image.FromStream(httpPostedFileBase.InputStream, true, true)

请注意,返回的ImageIDisposable

为使此功能正常工作,您需要引用System.Drawing.dll,而Image位于System.Drawing命名空间中。

调整图像大小

我不确定您要做什么,但如果您正在制作缩略图或类似的东西,则可能会对执行以下操作感兴趣...

try {
    var bitmap = new Bitmap(newWidth,newHeight);
    using (Graphics g = Graphics.FromImage(bitmap)) {
        g.SmoothingMode = SmoothingMode.HighQuality;
        g.PixelOffsetMode = PixelOffsetMode.HighQuality;
        g.CompositingQuality = CompositingQuality.HighQuality;
        g.InterpolationMode = InterpolationMode.HighQualityBicubic;
        g.DrawImage(oldImage,
            new Rectangle(0,0,newWidth,newHeight),
            clipRectangle, GraphicsUnit.Pixel);
    }//done with drawing on "g"
    return bitmap;//transfer IDisposable ownership
} catch { //error before IDisposable ownership transfer
    if (bitmap != null) bitmap.Dispose();
    throw;
}

clipRectangle 是原始图像的矩形,您希望将其缩放到新位图中(您需要手动处理纵横比)。catch块是构造函数内典型的 IDisposable 用法;在返回之前,您保留新 IDisposable 对象的所有权(您可能需要使用代码注释对此进行记录)。

保存为Jpeg

不幸的是,默认的“另存为jpeg”编码器没有公开任何质量控制,并选择了极低的默认质量。

您也可以手动选择编码器,然后可以传递任意参数:

ImageCodecInfo jpgInfo = ImageCodecInfo.GetImageEncoders()
    .Where(codecInfo => codecInfo.MimeType == "image/jpeg").First();
using (EncoderParameters encParams = new EncoderParameters(1))
{
    encParams.Param[0] = new EncoderParameter(Encoder.Quality, (long)quality);
    //quality should be in the range [0..100]
    image.Save(outputStream, jpgInfo, encParams);
}

1
因为 finally 块总是会执行 - 但新创建的图像只需要在出现错误时被处理。如果没有出现错误,则新图像已正确构建并由调用函数拥有 - 现在他们有责任处理它。 - Eamon Nerbonne
当我使用Image image = Image.FromStream(item.InputStream, true, true);代码时,我会得到“参数无效”异常。请告诉我,如何解决这个问题? - Elvin Mammadov
@ElvinArzumanoğlu:如果你无法轻松解决问题,那么你应该提出一个新的问题,因为在你自己的问题中,你可以添加所有相关的细节。但是作为一般提示;尝试将流保存到磁盘并从文件流本地重现异常-如果你能够做到这一点,你就有了一个相当小的测试用例,这些总是更容易处理。 - Eamon Nerbonne
@Eamon,我因为发问被封锁了,所以我现在不能问任何问题:(。一开始我的情况是,我有一个用于上传图片的dropzone js库(http://www.dropzonejs.com/),我可以同时上传多张图片,我将这些图片添加到我的httpPfile中,在这个dropzone上传操作中添加到Lis<>中,然后我在保存按钮中获取这些上传文件,但是在foreach循环中写入之前的代码时,我得到了参数无效的异常,然后我认为这个错误意味着我只能在post操作中第一次写入这个,然后我试着将httpPoBase转换为图片,dropezone动作和转换工作都很好。 - Elvin Mammadov
我不太明白你说的是什么,但是httpPostedFileBase.InputStream只在文件上传的请求中有效 - 在该请求中,您需要将数据保存到某个地方,并且您可能还想立即进行图像处理。 - Eamon Nerbonne
显示剩余6条评论

7
如果您确定源代码是图像且不需要编辑,您可以按照此处所述轻松完成操作。
[HttpPost]
public void Index(HttpPostedFileBase file)
{
    if (file.ContentLength > 0)
    {
        var filename = Path.GetFileName(file.FileName);

        System.Drawing.Image sourceimage =
            System.Drawing.Image.FromStream(file.InputStream);
    }
}

为了保护文件是图像,将 JavaScript 验证添加到视图中,通过在输入标记中添加 MIME 类型的 accept 属性来实现。
<input type="file" accept="image/*">

以及jQuery验证脚本

$.validator.addMethod('accept', function () { return true; });

整个解决方案可以在这里找到。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接