我的网站需要一个包含多个上传内容的网络表单,并通过电子邮件发送给某人。
为了解决这个问题,我们创建了一个临时文件流,它基本上将上传复制到文件系统,并在处理时删除文件。
TemporaryFileStream继承Stream对象以欺骗dotnet,认为它实际上是一个流,这样我们就可以使用var attachment = new Attachment(fileStream, file.FileName, file.ContentType);
来发送电子邮件。
我遇到的问题是,当文件大于10 MB或文件总数大于10 MB时,我收到System.IO错误,说您无法访问已关闭的文件。
我不明白为什么只有在大小超过10 MB时才会发生这种情况,因为HttpPostedFileBase正确发送,所以不是上传,在临时文件流上实际调用`Read()'方法时会发生错误。
这是启动临时文件流的方式:
/// <summary>
/// A temporary fileStream that is removed when disposed
/// </summary>
/// <param name="file">The HttpPosted file to write to the temp directory</param>
public TemporaryFileStream(HttpPostedFileBase file)
{
file.InputStream.Flush();
file.InputStream.Position = 0;
_tempPath = Path.Combine(Path.GetTempPath(), String.Join(".", Path.GetRandomFileName(), file.FileName));
_innerStream = File.Create(_tempPath);
file.InputStream.CopyTo(_innerStream);
_innerStream.Flush(true);
_innerStream.Position = 0;
_innerStream.Unlock(0,_innerStream.Length);
}
http输入流立即复制到临时文件夹,稍后再读。
发送邮件后,代码不会使用dispose()
包装来调用using()
方法。
public new void Dispose()
{
if (!_baseDisposed)
{
_baseDisposed = true;
Close();
base.Dispose();
}
if (!_innerDisposed)
{
_innerDisposed = true;
_innerStream.Flush();
_innerStream.Close();
_innerStream.Dispose();
}
if (File.Exists(_tempPath))
File.Delete(_tempPath);
}
这是调用Close()
的唯一地方,但在发送邮件后会调用它。
我很确定它不是httpRuntime.maxRequestLength设置,因为我们将其设置为:“512000”。
我甚至没有成功尝试以下内容:
httpRuntime maxRequestLength="512000" executionTimeout="3600"
appRequestQueueLimit="100" requestLengthDiskThreshold="10024000"
enableKernelOutputCache="false" relaxedUrlToFileSystemMapping="true" />
为什么我的文件流可以在我的控件之外关闭?或者SendMail(...).ConfigureAsync(true)
的异步上下文可能与此有关吗?
亲切的问候, 马文布劳威尔。
答案 0 :(得分:0)
我已经解决了这个问题。
结果是base.Dispose();
和
的组合
httpRuntime maxRequestLength="512000" executionTimeout="3600"
appRequestQueueLimit="100" requestLengthDiskThreshold="10024000"
enableKernelOutputCache="false" relaxedUrlToFileSystemMapping="true" />
显然base.Dispose();
尝试关闭未打开的流,并且requestLengthDiskThreshold等在读取时关闭了文件流。