Создать текстовый файл и скачать

23

Я пытаюсь записать в текстовый файл в памяти, а затем загрузить этот файл без сохранения файла на жесткий диск. Я использую StringWriter для записи содержимого:

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

Как загрузить этот файл?

EDIT: Это была комбинация ответов, которые дали мне мое решение. Вот он:

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();
Теги:
file
download

7 ответов

13
Лучший ответ

Вместо того, чтобы хранить данные в памяти и затем отправлять их в поток ответов, вы можете записать их непосредственно в поток ответов:

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

В примере используется кодировка UTF-8, вы должны изменить это, если используете другую кодировку.

  • 0
    Привет, Гаффа. Как я могу получить поток ответов для загрузки?
  • 0
    @higgsy: Вы добавляете инструкции по расположению и типу содержимого в заголовке, чтобы браузер знал, что это такое. У Клауса Бискова Хоффмана есть несколько примеров в его ответе, но вам не нужно использовать обработчик HTTP для возврата ответа, он также работает с обычной страницей. Вы должны также указать кодировку в типе контента, например text/plain; charset=utf-8 .
16

Это решило для меня:

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

В основном вы создаете HttpHandler, реализуя интерфейс IHttpHandler. В методе ProcessRequest вы в основном просто пишете текст в context.Response. Вам также нужно добавить заголовок Content-Disposition http:

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

Также не забудьте установить ContentType:

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

Просто небольшое дополнение к другим ответам. В самом конце загрузки я выполняю:

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

Я узнал, что в противном случае загрузка иногда не завершается успешно.

В этой публикации Google Groups также отмечается, что Response.End выбрасывает ThreadAbortException, которого можно избежать, используя метод CompleteRequest.

  • 1
    на самом деле, когда я использовал добавленные вами строки, сгенерированный файл содержал текст, который я написал в потоке, плюс код html сотен, поэтому мне пришлось вернуться в код и просто поместить строку «Response.End», и она работала просто хорошо!
  • 1
    Обычно я предоставляю загрузки только через отдельные обработчики ASHX, а не на страницах ASPX.
0

Расширение @Vinicious ответа.

У меня были данные, содержащие запятые. Общее решение заключается в том, чтобы избежать этой части данных, заключая ее в кавычки, при этом также избегая кавычек, которые также могут быть частью данных.

Один руб, против которого я выступил, и предупреждение при написании 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)));
0

У меня было много проблем с этим. Finnaly нашел решение, которое, кажется, работает каждый раз.

В большинстве случаев пользователь нажимает кнопку для загрузки. На этом этапе лучше перенаправить страницу обратно в одно и то же место. добавьте параметр в URL-адрес, который вы можете захватить и прочитать.

example (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

Это очень просто, и ответ можно увидеть в этой статье Microsoft KB: Как записать двоичные файлы в браузер с помощью ASP.NET и С#/a >

  • 0
    Это на самом деле не отвечает на вопрос ... Хиггси указал, что файл не должен быть записан на жесткий диск.
  • 2
    Привет, точно, файл не должен быть записан на жесткий диск.

Ещё вопросы

Сообщество Overcoder
Наверх
Меню