Image.FromStream(PostedFile.InputStream) 失败。 (参数无效。)(AsyncFileUpload))

Posted

技术标签:

【中文标题】Image.FromStream(PostedFile.InputStream) 失败。 (参数无效。)(AsyncFileUpload))【英文标题】:Image.FromStream(PostedFile.InputStream) Fails. (Parameter is not valid.) (AsyncFileUpload)) 【发布时间】:2010-12-09 13:02:30 【问题描述】:

我正在使用 AsyncFileUpload (AJAX Toolkit) 来上传图片。 我有一个处理图像大小调整的按钮。 这已经有一段时间了,但现在不行了......

protected void BtnUploadImage_Click(object sender, EventArgs e)

    var imageFileNameRegEx = new Regex(@"(.*?)\.(jpg|jpeg|png|gif)$", 
        RegexOptions.IgnoreCase);
    if (!AsyncFileUpload1.HasFile || 
        !imageFileNameRegEx.IsMatch(AsyncFileUpload1.FileName))
    
        AsyncFileUpload1.FailedValidation = true;
        ErrorLabel.Visible = true;
        return;
    
    ErrorLabel.Visible = false;

    var file = AsyncFileUpload1.PostedFile.InputStream;

    var img = Image.FromStream(file, false, false);

...

我觉得奇怪的另一件事是:如果我尝试使用小于 80kb 的图像,它可以工作..!

我们已尝试重新启动服务器,但没有任何变化。 相同的代码在我的机器上运行良好。 (之前听说过??:))

我也尝试将文件保存在服务器上,然后通过 Image.FromFile() 获取文件,但随后出现“无法访问已关闭的文件”。

如何解决这个问题?

【问题讨论】:

您的 sn-p 中缺少代码。 @Joseph,我认为只是在函数处添加结束大括号是错误的,不能就此止步,img 变量没有使用。 不认为其余的相关,Image.FromStream() 无论如何都不执行之后会发生什么。 根据您的观点,Graphics/Bitmap 等时的发现。当您尝试编写时,反过来也会出现同样的问题一个图形到一个 Response.Out 流。 Cannot access a closed file 错误很奇怪,但是如果您查看真实代码,您可能会发现无法正确使用 IDisposableusing 块的地方。这通常是导致资源仍在使用或无法读取或写入的原因。 【参考方案1】:

我会确保流位于开头:

var file = AsyncFileUpload1.FileContent;
file.Seek(0, SeekOrigin.Begin);

var img = Image.FromFile(file);

要检查的第二件事:the requestLengthDiskThreshold 设置。除非指定,否则此设置的默认值为...是的,80 KB。

注意: imo 是使用 Image 直接读取文件流还是使用中间 MemoryStream 应该没有总体区别(除了在后一种情况下您实际加载整个文件进入内存两次)。无论哪种方式,都将从中读取原始文件流,因此流位置、CAS 权限、文件权限等仍然适用。

注意 2: 是的,一定要确保正确处理这些资源 :)

【讨论】:

谢谢,这就像一个魅力。我查看了 HttRuntime 设置,但不知何故完全忽略了 requestLengthDiskThreshold 设置。 :(你又一次拯救了一天:D @PeterLillevold 如何在不使用 ajax 工具包的情况下实现这一目标 @HeemanshuBhalla 实现了什么?您必须在这里更具体,我的回答不仅适用于ATK。你问的是一般的图片上传吗?如果是这样,请在此处查找 SO 上的现有 QA,或提出新问题。【参考方案2】:

这是正确的,它不会起作用。问题是您正在跨越托管/非托管边界,我最近遇到了同样的情况。其他问题是流不直接存在并且 Image.FromStream 不知道如何处理它。

解决方案非常简单:将 PostedFile 中的所有内容读入 MemoryStream(只需使用 new MemoryStream())并将 MemoryStream 与 Image.FromStream 一起使用。这将解决您的问题。

当您使用ImageGraphicsStreams 时,请确保正确使用using。它们都实现了 IDisposable 并且在 ASP.NET 环境中,不正确使用 using 块,从长远来看,可能并且将导致内存使用量增加和其他讨厌的副作用(并且 ASP.NET 应用程序运行时间很长! )。

解决方案应如下所示:

using(Stream memstr = new MemoryStream())

    // copy to a memory stream
    Stream uploadStream = AsyncFileUpload1.PostedFile.InputStream;
    byte[] all = new byte[uploadStream.Length];
    uploadStream.Read(all, 0, uploadStream.Length);
    memstr.Write(all, 0, uploadStream.Length);
    memstr.Seek(0, SeekOrigin.Begin);
    using(Graphics g = Graphics.FromStream(memstr))
    
         // do your img manipulation, or Save it.
    

更新:跨管理边界问题只发生在相反的情况下(使用响应流),似乎,不是上传流,但我不完全确定。

【讨论】:

您能否提供一个如何将所有字节读入内存流的示例? 注意:不能保证Read 有效。如果不是,则返回值包含实际读取的字节数。您可以通过始终检查 Read() 的返回值来使您的代码更加健壮,或者循环直到读取所有字节。 试过这个:string imageID;使用 (var mStream = new MemoryStream()) var uploadStream = AsyncFileUpload1.PostedFile.InputStream; var all = new byte[uploadStream.Length]; uploadStream.Read(all, 0, (int) uploadStream.Length); mStream.Write(all, 0, (int) uploadStream.Length); mStream.Seek(0, SeekOrigin.Begin);使用 (var img = Image.FromStream(mStream)) imageID = ImageCreation.SaveImage(img, true); 但我得到 "Parameter is not valid.",仍然在 Image.FromStream 上。 (现在甚至在本地机器上) 那么恐怕你必须进行一些调试。放置一个断点并逐行遍历代码。我怀疑由于某种原因流不完整,但我似乎无法创建相同的情况...... MemoryStream 作为中间流总是对我有用。 好的,我试试。顺便说一句:“全部”中的各个字节为“0”。这有什么线索吗?

以上是关于Image.FromStream(PostedFile.InputStream) 失败。 (参数无效。)(AsyncFileUpload))的主要内容,如果未能解决你的问题,请参考以下文章

Image.FromStream 参数无效

Image.FromStream(stream);报参数无效

Image.FromStream(ms) 提示参数无效

Image.FromStream参数无效

一直报Image img = Image.FromStream;参数无效,这要怎么改

winform中: datagridview发生以下异常: system.ArgumentException:参数无效