如何在ASP.NET 3.5中将流保存到文件的最佳方法?

3

我有一个流对象,其中包含我正在工作的项目中作为嵌入式资源的XSD文件的内容,如下所示:

using ( Stream xsdStream = assembly.GetManifestResourceStream( xsdFile ) )
{
  // Save the contents of the xsdStream here...
}

在这个使用块中,我想在网页上提示用户使用“保存文件”对话框,让他们选择保存流中包含的XSD文件。

如何最好地实现这一点?我完全迷失了,似乎无法通过谷歌搜索到相关答案。

谢谢!

4个回答

2
如果您不使用AJAX,可以使用Response.WriteFile。否则,我会使用MemoryStream。就像我这里做的一样。抱歉它是用VB.NET编写的,我还没有转码。请注意,这也允许您通过Web服务器下载文件,即使您的文件在没有公共访问权限的应用程序服务器上也可以。
Imports System.Data
Imports System.Data.SqlClient
Imports System.Data.Sql
Imports System.Net
Imports System.IO

Partial Class DownloadFile
Inherits System.Web.UI.Page

Protected Sub page_load(ByVal sender As Object, ByVal e As EventArgs) Handles Me.Load
Dim url As String = Request.QueryString("DownloadUrl")
If url Is Nothing Or url.Length = 0 Then Exit Sub

'Initialize the input stream
Dim req As HttpWebRequest = WebRequest.Create(url)
Dim resp As HttpWebResponse = req.GetResponse()
Dim bufferSize As Integer = 1 

'Initialize the output stream
Response.Clear()
Response.AppendHeader("Content-Disposition:", "attachment; filename=download.zip")
Response.AppendHeader("Content-Length", resp.ContentLength.ToString)
Response.ContentType = "application/download"

'Populate the output stream
Dim ByteBuffer As Byte() = New Byte(bufferSize) {}
Dim ms As MemoryStream = New MemoryStream(ByteBuffer, True)
Dim rs As Stream = req.GetResponse.GetResponseStream()
Dim bytes() As Byte = New Byte(bufferSize) {}
While rs.Read(ByteBuffer, 0, ByteBuffer.Length) > 0
Response.BinaryWrite(ms.ToArray())
Response.Flush()
End While

'Cleanup
Response.End()
ms.Close()
ms.Dispose()
rs.Dispose()
ByteBuffer = Nothing
End Sub
End Class

1

你需要设置 content-disposition:

Response.AddHeader "Content-Disposition","attachment; filename=" & xsdFile

您还需要将Content-Type设置为text/plain,将Content-Length设置为文件大小。然后您可以编写文件的内容。

虽然这个答案提供了有价值的信息,如果Rob想要自己实现流媒体,那么这是有用的,但它并没有回答如何首先流式传输文件的问题。如果Rob想走这条路,我认为tsilb的答案更好。不过,我仍然认为我的方法更容易... ;) - JohannesH

1
private void DownloadEmbeddedResource( 
  string resourceName, Assembly resourceAssembly, string downloadFileName )
{
  using ( Stream stream = resourceAssembly.GetManifestResourceStream( resourceName ) )
  {
    if ( stream != null )
    {
      Response.Clear();
      string headerValue = string.Format( "attachment; filename={0}", downloadFileName );
      Response.AppendHeader( "Content-Disposition:", headerValue );
      Response.AppendHeader( "Content-Length", stream.Length.ToString() );
      Response.ContentType = "text/xml";

      var byteBuffer = new Byte[1];

      using ( var memoryStream = new MemoryStream( byteBuffer, true ) )
      {
        while ( stream.Read( byteBuffer, 0, byteBuffer.Length ) > 0 )
        {
          Response.BinaryWrite( memoryStream.ToArray() );
          Response.Flush();
        }
      }

      Response.End();
    }
  }
}

我最终使用了上面的方法。感谢tsilb帮助我解决语法问题。JohannesH,如果资源不是来自另一个程序集,我会使用您的建议(抱歉,我应该在原始问题中澄清这一点)。

上面的代码可以工作,但我遇到了一个相当奇怪的问题...在方法完成并下载完成后,页面仍然似乎没有恢复过来,鼠标仍处于沙漏模式,就好像它仍然认为正在进行工作。有什么办法可以解决这个问题吗?

再次感谢您的所有帮助!


0

听起来你应该看一下WebResource.axd处理程序。

微软在这个主题上有一篇优秀的文章

编辑:

似乎tsilb比我回答快了一两分钟。然而,AssemblyResourceLoader(又名WebResource.axd)已经实现了这个功能,并且做得很好,不要忘记这只小狗支持输出缓存。所以去使用它吧,省去自己的麻烦。 ;)


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