创建文本文件并下载

我正在尝试写入内存中的文本文件,然后下载该文件而不将文件保存到硬盘。 我正在使用StringWriter来编写内容:

 StringWriter oStringWriter = new StringWriter(); oStringWriter.Write("This is the content"); 

我如何下载此文件?

编辑:这是答案的组合,给了我我的解决方案。 这里是:

 StringWriter oStringWriter = new StringWriter(); oStringWriter.WriteLine("Line 1"); Response.ContentType = "text/plain"; Response.AddHeader("content-disposition", "attachment;filename=" + string.Format("members-{0}.csv",string.Format("{0:ddMMyyyy}",DateTime.Today))); Response.Clear(); using (StreamWriter writer = new StreamWriter(Response.OutputStream, Encoding.UTF8)) { writer.Write(oStringWriter.ToString()); } Response.End(); 

您可以直接将数据写入响应流,而不是将数据存储在内存中然后将其发送到响应流:

 using (StreamWriter writer = new StreamWriter(Response.OutputStream, Encoding.UTF8)) { writer.Write("This is the content"); } 

该示例使用UTF-8编码,如果您使用其他编码,则应更改该编码。

这解决了我:

  MemoryStream ms = new MemoryStream(); TextWriter tw = new StreamWriter(ms); tw.WriteLine("Line 1"); tw.WriteLine("Line 2"); tw.WriteLine("Line 3"); tw.Flush(); byte[] bytes = ms.ToArray(); ms.Close(); Response.Clear(); Response.ContentType = "application/force-download"; Response.AddHeader("content-disposition", "attachment; filename=file.txt"); Response.BinaryWrite(bytes); Response.End(); 

基本上,您通过实现IHttpHandler接口来创建HttpHandler。 在ProcessRequest方法中,您基本上只需将文本写入context.Response 。 您还需要添加Content-Disposition http标头:

 context.Response.AddHeader("Content-Disposition", "attachment; filename=YourFileName.txt"); 

还记得设置ContentType

 context.Response.ContentType = "text/plain"; 

只是对其他答案的一小部分补充。 在下载的最后,我执行:

 context.Response.Flush(); context.ApplicationInstance.CompleteRequest(); 

我了解到,否则,下载有时无法成功完成。

此Google网上论坛post还指出, Response.End会抛出一个ThreadAbortException ,您可以使用CompleteRequest方法避免这种情况。

这很简单,答案可以在这篇Microsoft知识库文章中看到: 如何使用ASP.NET和C#将二进制文件写入浏览器

我有很多问题。 Finnaly找到了一个似乎每次都有效的解决方案。

在大多数情况下,用户将单击下载按钮。 此时,最好将页面重定向回同一位置。 在您可以抓取和读取的url中添加一个参数。

示例(www.somewhere.com/mypage.aspx?print=stuff)

   protected void Page_Load(object sender, EventArgs e) { if (Request["print"] == "stuff") { Print("my test content"); } } /* or pass byte[] content*/ private void Print(string content ){ Response.ContentType = "text/plain"; Response.AddHeader("content-disposition", "attachment;filename=myFile.txt"); // Response.BinaryWrite(content); Response.Write(content); Response.Flush(); Response.End(); } protected void btn_Click(object sender, EventArgs e) { // postbacks give you troubles if using async. // Will give an error when Response.End() is called. Response.Redirect(Request.Url + "?print=queue"); } 

延伸@Vinicious回答。

我有可能包含逗号的数据。 常见的解决方案是通过将其括在引号中来逃避该数据,同时确保也可以转义也可能是数据一部分的引号。

我写的一个rub和写入CSV的警告,如果你在逗号上留下空格,excel将不会喜欢你。 从超级用户的回答中发现我的问题的解决方案

 protected void btnDownload_Click(object sender, EventArgs e) { MemoryStream ms = new MemoryStream(); TextWriter tw = new StreamWriter(ms, System.Text.Encoding.UTF8); var structures = KAWSLib.BusinessLayer.Structure.GetStructuresInService(); // *** comma delimited tw.Write("Latitude, Longitude, CountySerial, StructureType, Orientation, District, RoutePre, RouteNo, LocationDesc"); foreach (var s in structures) { tw.Write(Environment.NewLine + string.Format("{0:#.000000},{1:#.000000},{2},{3},{4},{5},{6},{7},{8}", s.LATITUDE, s.LONGITUDE, s.CO_SER, EscapeIfNeeded(s.SuperTypeLookup.SHORTDESC), EscapeIfNeeded(s.OrientationLookup.SHORTDESC), s.DISTRICT, s.ROUTE_PREFIX, s.RouteValue, EscapeIfNeeded(s.LOC_DESC))); } tw.Flush(); byte[] bytes = ms.ToArray(); ms.Close(); Response.Clear(); Response.ContentType = "application/force-download"; Response.AddHeader("content-disposition", "attachment; filename=" + string.Format("kaws-structures-{0:yyyy.MM.dd}.csv", DateTime.Today)); Response.BinaryWrite(bytes); Response.End(); } string EscapeIfNeeded(string s) { if (s.Contains(",")) { return "\"" + s.Replace("\"", "\"\"") + "\""; } else { return s; } } 

以下将导致excel问题。 在excel中,第一个引用将成为数据的一部分,因此在嵌入式逗号中分开。 空间不好。

  tw.Write(Environment.NewLine + string.Format("{0:#.000000}, {1:#.000000}, {2}, {3}, {4}, {5}, {6}, {7}, {8}", s.LATITUDE, s.LONGITUDE, s.CO_SER, EscapeIfNeeded(s.SuperTypeLookup.SHORTDESC), EscapeIfNeeded(s.OrientationLookup.SHORTDESC), s.DISTRICT, s.ROUTE_PREFIX, s.RouteValue, EscapeIfNeeded(s.LOC_DESC)));