2014-01-13 2 views
24

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

Веб-сайт основан на базе MVC. Вот кнопка JQuery код, я использую, чтобы сделать вызов (данные некоторые сериализованная Json представление списка DTO):

$.ajax({ 
     type: "POST", 
     url: unity.baseUrl + "common/ExportPayments", 
     data: data 
    }); 

Вот код контроллера:

[HttpPost] 
    public FileStreamResult ExportPayments() 
    { 
     MemoryStream ms = new MemoryStream(); 
     StreamWriter sw = new StreamWriter(ms); 
     CsvWriter writer = new CsvWriter(sw); 

     List<Payment_dto> pd = _commonService.GetPayments(); 

     foreach (var record in pd) 
     { 
      writer.WriteRecord(record); 
     } 
     sw.Flush(); 

     return new FileStreamResult(ms, "text/csv"); 
    } 

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

EDIT: Возвращение этого ...

return File(ms.GetBuffer(), "text/csv", "export.csv"); 

... дает мне ответ, состоящий из данных CSV-формате, что я ожидал. Но браузер по-прежнему не знает, что с ним делать - пользователю не предлагается вариант загрузки.

+0

Попробуйте установить скрипач http://fiddler2.com/. Вы сможете точно увидеть, что возвращается браузеру, когда этот метод выполняется. – mituw16

+0

Ничего не происходит. Однако я обнаружил, что он связан с типом действия - метод в настоящее время установлен на POST, потому что я хотел отправить ему некоторые сложные данные. Если я изменю его на GET, он работает так, как ожидалось. Я не понимаю, почему POST ведет себя по-другому, но он все равно должен отправить ответ? –

ответ

25

Попытка ниже код:

public FileStreamResult ExportPayments() 
    { 
     var result = WriteCsvToMemory(_commonService.GetPayments()()); 
     var memoryStream = new MemoryStream(result); 
     return new FileStreamResult(memoryStream, "text/csv") { FileDownloadName = "export.csv" }; 
    } 


    public byte[] WriteCsvToMemory(IEnumerable<Payment_dto> records) 
    { 
     using (var memoryStream = new MemoryStream()) 
     using (var streamWriter = new StreamWriter(memoryStream)) 
     using (var csvWriter = new CsvWriter(streamWriter)) 
     { 
      csvWriter.WriteRecords(records); 
      streamWriter.Flush(); 
      return memoryStream.ToArray(); 
     } 
    } 

Update

Ниже, как пройти сложный тип модели для метода действия, который использует GET HTTP метод. Я не предпочитаю такой подход, он просто дает вам представление, что есть подход к достижению этого.

Модель

public class Data 
    { 
     public int Id { get; set; } 
     public string Value { get; set; } 

     public static string Serialize(Data data) 
     { 
      var serializer = new JavaScriptSerializer(); 
      return serializer.Serialize(data); 
     } 
     public static Data Deserialize(string data) 
     { 
      var serializer = new JavaScriptSerializer(); 
      return serializer.Deserialize<Data>(data); 
     } 
    } 

Действие:

[HttpGet] 
    public FileStreamResult ExportPayments(string model) 
    { 
     //Deserialize model here 
     var result = WriteCsvToMemory(GetPayments()); 
     var memoryStream = new MemoryStream(result); 
     return new FileStreamResult(memoryStream, "text/csv") { FileDownloadName = "export.csv" }; 
    } 

Вид:

@{ 
    var data = new Data() 
    { 
        Id = 1, 
        Value = "This is test" 
    }; 
} 
@Html.ActionLink("Export", "ExportPayments", new { model = Data.Serialize(data) }) 
+0

Это дает мне нужные данные в ответе и заставляет браузер попробовать и загрузить файл (по желанию), если он сделан в результате действия GET. Но если это действие POST, браузер ничего не делает с ответом. –

+1

привет @MattThrower, я не уверен, почему вы хотите использовать метод POST. Используйте GET, чтобы stil мог передать параметр сложного типа. – Lin

+0

ОК, ну, я получил ваш код, работая, передавая тонну простых параметров типа и запрашивая базу данных. Так что спасибо за это - но мне любопытно узнать, как вы передадите сложный тип, зависящий от querystring - как JSON? –

0

Попытка в контроллере:

HttpContext.Response.AddHeader("content-disposition", "attachment; filename=payments.csv"); 
+0

Спасибо за попытку помочь, но все равно ничего –

0

Может также пользователь динамическое ключевое слово для преобразования каких-либо данных

код из @Lin

public FileStreamResult ExportPayments() 
{ 
    var result = WriteCsvToMemory(_commonService.GetPayments()()); 
    var memoryStream = new MemoryStream(result); 
    return new FileStreamResult(memoryStream, "text/csv") { FileDownloadName = "export.csv" }; 
} 


public byte[] WriteCsvToMemory(dynamic records) 
{ 
    using (var memoryStream = new MemoryStream()) 
    using (var streamWriter = new StreamWriter(memoryStream)) 
    using (var csvWriter = new CsvWriter(streamWriter)) 
    { 
     csvWriter.WriteRecords(records); 
     streamWriter.Flush(); 
     return memoryStream.ToArray(); 
    } 
} 
Смежные вопросы