大于10MB的C#.Net FileStream会被意外关闭

时间:2015-11-09 12:20:44

标签: c# file-upload

我的网站需要一个包含多个上传内容的网络表单,并通过电子邮件发送给某人。 为了解决这个问题,我们创建了一个临时文件流,它基本上将上传复制到文件系统,并在处理时删除文件。 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)的异步上下文可能与此有关吗?

亲切的问候, 马文布劳威尔。

1 个答案:

答案 0 :(得分:0)

我已经解决了这个问题。 结果是base.Dispose();
的组合 httpRuntime maxRequestLength="512000" executionTimeout="3600" appRequestQueueLimit="100" requestLengthDiskThreshold="10024000" enableKernelOutputCache="false" relaxedUrlToFileSystemMapping="true" /> 显然base.Dispose();尝试关闭未打开的流,并且requestLengthDiskThreshold等在读取时关闭了文件流。