2010-12-31 13 views
24

Estoy intentando escribir en un archivo de texto en la memoria y luego descargar el archivo sin guardar el archivo en el disco duro. Estoy usando el StringWriter para escribir el contenido:Crear archivo de texto y descarga

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

¿Cómo luego descargar este archivo?

EDIT: Fue combinación de respuestas que me dio mi solución. Aquí está:

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(); 
+0

http://www.xefteri.com/articles/show.cfm?id=8 – fejesjoco

Respuesta

13

En lugar de almacenar los datos en la memoria y luego enviarlo a la secuencia de respuesta, se puede escribir directamente a la secuencia de respuesta:

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

el ejemplo utiliza la codificación UTF-8, que se debe cambiar si está usando alguna otra codificación.

+0

Hola Guffa - ¿cómo puedo obtener la descarga de respuesta para descargar? – higgsy

+0

@higgsy: agrega instrucciones para la disposición del contenido y el tipo de contenido en el encabezado, para que el navegador sepa de qué se trata. Klaus Byskow Hoffman tiene algunos ejemplos en su respuesta, pero no tiene que usar un manejador HTTP para devolver la respuesta, también funciona con una página normal. También debe especificar la codificación en el tipo de contenido, por ejemplo 'text/plain; charset = utf-8'. – Guffa

5

Básicamente se crea un HttpHandler implementando la interfaz IHttpHandler. En el método ProcessRequest básicamente escribes tu texto en context.Response. También es necesario agregar un encabezado Content-Disposition http:

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

Asimismo, recuerda a establecer el ContentType:

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

Sólo una pequeña adición a las otras respuestas. Al final de una descarga ejecuto:

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

supe que de lo contrario, la descarga a veces no se completa correctamente.

This Google Groups posting también observa que Response.End arroja un ThreadAbortException que puede evitar utilizando el método CompleteRequest.

+1

en realidad cuando utilicé las líneas que ha agregado, el archivo generado contenía el texto que escribí en la secuencia más el código html procesado, así que tuve que volver al código y poner la línea "Response.End" y funcionó ¡bien! – Glolita

+1

Normalmente, solo proporciono descargas a través de manejadores ASHX separados, no en páginas ASPX. –

16

Esta resuelto para mí:

 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();  
0

tuve muchos problemas con esto. Finnaly encontró una solución que parece funcionar siempre.

En la mayoría de los casos el usuario va a hacer clic en un botón para la descarga. En este punto, es mejor redirigir la página al mismo lugar. agregue un parámetro en la url que pueda captar y leer.

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

<asp:Button ID="btn" runat="server" Text="print something" OnClick="btn_Click" /> 


    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"); 
    } 
0

Extensión de respuesta @Vinicious.

que tenían datos que podrían contener comas. La solución común es escapar de ese dato al encerrarlo entre comillas, al tiempo que se asegura de que también se salgan las comillas que también podrían ser parte de los datos.

Un roce me vino en contra y una advertencia al escribir CSV, Excel no le va a gustar que si se pone sus espacios finales comas.discovered solution to my problem from superuser answer

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; 
    } 
} 

A continuación causará un problema para excel. En Excel, la primera cita se convertirá en parte de los datos y, en consecuencia, se separará en la coma incrustada. Espacios malos

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))); 
Cuestiones relacionadas