Загрузка большого файла CSV в ASP.NET Проект MVC

#c# #http #csv #large-files

#c# #http #csv #большие файлы

Вопрос:

Мне нужно экспортировать действительно большой файл csv (~ 100 МБ). В Интернете я нашел похожий код и реализовал его для своего случая:

 public class CSVExporter
{
    public static void WriteToCSV(List<Person> personList)
    {
        string attachment = "attachment; filename=PersonList.csv";
        HttpContext.Current.Response.Clear();
        HttpContext.Current.Response.ClearHeaders();
        HttpContext.Current.Response.ClearContent();
        HttpContext.Current.Response.AddHeader("content-disposition", attachment);
        HttpContext.Current.Response.ContentType = "text/csv";
        HttpContext.Current.Response.AddHeader("Pragma", "public");
        WriteColumnName();
        foreach (Person person in personList)
        {
            WriteUserInfo(person);
        }
        HttpContext.Current.Response.End();
    }

    private static void WriteUserInfo(Person person)
    {
        StringBuilder stringBuilder = new StringBuilder();
        AddComma(person.Name, stringBuilder);
        AddComma(person.Family, stringBuilder);
        AddComma(person.Age.ToString(), stringBuilder);
        AddComma(string.Format("{0:C2}", person.Salary), stringBuilder);
        HttpContext.Current.Response.Write(stringBuilder.ToString());
        HttpContext.Current.Response.Write(Environment.NewLine);
    }

    private static void AddComma(string value, StringBuilder stringBuilder)
    {
        stringBuilder.Append(value.Replace(',', ' '));
        stringBuilder.Append(", ");
    }

    private static void WriteColumnName()
    {
        string columnNames = "Name, Family, Age, Salary";
        HttpContext.Current.Response.Write(columnNames);
        HttpContext.Current.Response.Write(Environment.NewLine);
    }
}
 

Проблема в том, что я хочу начать загрузку до того, как (!) будет создан весь CSV-файл. Почему он работает не так, как я предполагаю, и что я должен изменить?

Комментарии:

1. Два быстрых комментария: передайте IEnumerable<Person> и избегайте предварительного заполнения списка (для вывода 100 МБ, скорее всего, в нем много записей) и сбрасывайте вывод ответа каждые 1000 строк или около того.

2. @Morten Mertner, да, спасибо, я уже это делаю, это был найденный образец, на котором я основывал код

3. Мне любопытно, куда вы поместили это в свой фреймворк MVC? Вы только что вызвали метод WriteToCSV() из действия?

4. Если вы решили эту проблему, можете ли вы предоставить окончательный код?

Ответ №1:

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

 Response.Flush();
 

после добавления каждой записи в поток. Пожалуйста, обратитесь к этой статье для получения более подробной информации:

http://support.microsoft.com/kb/812406

Комментарии:

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