如何将内存流下载到文件?
我正在使用下面的示例代码来编写和下载内存流到C#中的文件。
MemoryStream memoryStream = new MemoryStream(); TextWriter textWriter = new StreamWriter(memoryStream); textWriter.WriteLine("Something"); byte[] bytesInStream = new byte[memoryStream.Length]; memoryStream.Write(bytesInStream, 0, bytesInStream.Length); memoryStream.Close(); Response.Clear(); Response.ContentType = "application/force-download"; Response.AddHeader("content-disposition", "attachment; filename=name_you_file.xls"); Response.BinaryWrite(bytesInStream); Response.End();
我收到以下错误:
指定的参数超出了有效值的范围。
参数名称:offset
可能是什么原因?
在代码中将数据复制到数组的位置,TextWriter可能没有刷新数据。 当您使用Flush()或Close()时会发生这种情况。
看看这是否有效:
MemoryStream memoryStream = new MemoryStream(); TextWriter textWriter = new StreamWriter(memoryStream); textWriter.WriteLine("Something"); textWriter.Flush(); // added this line byte[] bytesInStream = memoryStream.ToArray(); // simpler way of converting to array memoryStream.Close(); Response.Clear(); Response.ContentType = "application/force-download"; Response.AddHeader("content-disposition", "attachment; filename=name_you_file.xls"); Response.BinaryWrite(bytesInStream); Response.End();
你在逻辑上做错了。 首先,您将一些文本写入MemoryStream
,然后将空数组写入同一个流。 我假设您正在尝试将流的内容复制到bytesInStream
数组中。 您可以通过调用memoryStream.ToArray()
来创建此数组。
或者,您可以通过使用MemoryStream.CopyTo
将流直接写入响应输出流来避免arrays复制。 用这个替换你的BinaryWrite
调用:
memoryStream.Position = 0; memoryStream.CopyTo(Response.OutputStream);
注意:由于CopyTo
将从当前位置复制,因此在开始时显式定位流。
好的,因为显然只是为了提供一个工作示例而被投票,让我详细说明:
首先,你不这样做
textWriter.Flush()
并期望将textwriter的内容刷新到内存流。
那你不做
memoryStream.Position = 0
并期望内存流从位置0“写入”。
然后你做
memoryStream.Write(bytesInStream, 0, bytesInStream.Length);
但你的意思是
memoryStream.Read(bytesInStream, 0, CInt(memoryStream.Length))
您还错过了长度为Long,而read使用了整数,因此您可以在那里获得exception。
所以这是你的代码最低限度适应“工作”(我把它复制到vb项目)
Imports System.Web Imports System.Web.Services Public Class TextHandler Implements System.Web.IHttpHandler Sub ProcessRequest(ByVal context As HttpContext) Implements IHttpHandler.ProcessRequest 'context.Response.ContentType = "text/plain" 'context.Response.Write("Hello World!") Dim memoryStream As New System.IO.MemoryStream() Dim textWriter As System.IO.TextWriter = New System.IO.StreamWriter(memoryStream) textWriter.WriteLine("Something") textWriter.Flush() memoryStream.Position = 0 Dim bytesInStream As Byte() = New Byte(memoryStream.Length - 1) {} 'memoryStream.Write(bytesInStream, 0, bytesInStream.Length) memoryStream.Read(bytesInStream, 0, CInt(memoryStream.Length)) memoryStream.Close() context.Response.Clear() context.Response.ContentType = "application/force-download" context.Response.AddHeader("content-disposition", "attachment; filename=name_you_file.txt") context.Response.BinaryWrite(bytesInStream) context.Response.End() End Sub ReadOnly Property IsReusable() As Boolean Implements IHttpHandler.IsReusable Get Return False End Get End Property End Class
然后你用
Content-Type: application/force-download
意思是
“我,网络服务器,我会欺骗你(浏览器)关于这个文件是什么,所以你不会把它当作PDF / Word文档/ MP3 /其他什么,并提示用户将神秘文件保存到磁盘代替”。 当客户端没有“保存到磁盘”时,这是一个肮脏的黑客攻击。
…
最后,你没有正确编码文件名,所以如果一个文件名使用非ASCII字符,它会乱码文件名,如果你碰巧是中文或俄文并且完全在ASCII字符集之外操作,这非常有趣。
原版的
这是我的一个ajax处理程序的快速摘录。 这是VB.NET,在转换时,要注意长度为-1的东西。
Sub ProcessRequest(ByVal context As HttpContext) Implements IHttpHandler.ProcessRequest Dim strFileName As String = "Umzugsmitteilung.doc" Dim strUID As String = context.Request.QueryString("ump_uid") context.Response.Clear() 'If String.IsNullOrEmpty(strUID) Or fileData Is Nothing Then ' context.Response.Write("") ' context.Response.End() 'End If context.Response.ClearContent() 'context.Response.AddHeader("Content-Disposition", "attachment; filename=" + strFileName) context.Response.AddHeader("Content-Disposition", GetContentDisposition(strFileName)) 'context.Response.ContentType = "application/msword" context.Response.ContentType = "application/octet-stream" GetUmzugsMitteilung(strUID) context.Response.End() End Sub ' ProcessRequest Public Shared Sub SaveWordDocumentToOutputStream(strUID As String, doc As Aspose.Words.Document) Using ms As System.IO.MemoryStream = New System.IO.MemoryStream() CreateWordDocumentFromTemplate(strUID, doc, ms) ms.Position = 0 Dim bytes As Byte() = New Byte(ms.Length - 1) {} ms.Read(bytes, 0, CInt(ms.Length)) System.Web.HttpContext.Current.Response.OutputStream.Write(bytes, 0, ms.Length) ms.Close() End Using ' ms End Sub ' SaveWordDocumentToOutputStream Public Shared Function StripInvalidPathChars(str As String) As String If str Is Nothing Then Return Nothing End If Dim strReturnValue As String = "" Dim strInvalidPathChars As New String(System.IO.Path.GetInvalidPathChars()) Dim bIsValid As Boolean = True For Each cThisChar As Char In str bIsValid = True For Each cInvalid As Char In strInvalidPathChars If cThisChar = cInvalid Then bIsValid = False Exit For End If Next cInvalid If bIsValid Then strReturnValue += cThisChar End If Next cThisChar Return strReturnValue End Function ' StripInvalidPathChars Public Shared Function GetContentDisposition(ByVal strFileName As String) As String ' https://stackoverflow.com/questions/93551/how-to-encode-the-filename-parameter-of-content-disposition-header-in-http Dim contentDisposition As String strFileName = StripInvalidPathChars(strFileName) If System.Web.HttpContext.Current IsNot Nothing AndAlso System.Web.HttpContext.Current.Request.Browser IsNot Nothing Then If (System.Web.HttpContext.Current.Request.Browser.Browser = "IE" And (System.Web.HttpContext.Current.Request.Browser.Version = "7.0" Or System.Web.HttpContext.Current.Request.Browser.Version = "8.0")) Then contentDisposition = "attachment; filename=" + Uri.EscapeDataString(strFileName).Replace("'", Uri.HexEscape("'"c)) ElseIf (System.Web.HttpContext.Current.Request.Browser.Browser = "Safari") Then contentDisposition = "attachment; filename=" + strFileName Else contentDisposition = "attachment; filename*=UTF-8''" + Uri.EscapeDataString(strFileName) End If Else contentDisposition = "attachment; filename*=UTF-8''" + Uri.EscapeDataString(strFileName) End If Return contentDisposition End Function ' GetContentDisposition
您正在使用很长的方法将字符串转换为字节。
你确定,你需要任何流吗? 为什么不使用编码?
Response.BinaryWrite(Encoding.UTF8.GetBytes("Something"))
上述就是C#学习教程:如何将内存流下载到文件?分享的全部内容,如果对大家有所用处且需要了解更多关于C#学习教程,希望大家多多关注—计算机技术网(www.ctvol.com)!
本文来自网络收集,不代表计算机技术网立场,如涉及侵权请联系管理员删除。
ctvol管理联系方式QQ:251552304
本文章地址:https://www.ctvol.com/cdevelopment/1014090.html