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
错误很奇怪,但是如果您查看真实代码,您可能会发现无法正确使用 IDisposable
和 using
块的地方。这通常是导致资源仍在使用或无法读取或写入的原因。
【参考方案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
一起使用。这将解决您的问题。
当您使用Image
、Graphics
和Stream
s 时,请确保正确使用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(stream);报参数无效