Using CSVHelper to output stream to browser

不问归期 提交于 2019-12-17 23:09:27

问题


I'm trying to use CSVHelper to generate a CSV file and send it back to a browser, so the user can select a save location and filename and save the data.

The website is MVC based. Here' the jQuery button code I'm using to make the call (data is some serialised Json representation of a DTO list):

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

Here's the controller code:

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

Which seems to achieve precisely nothing - invoking the method steps into the correct bit of code but the response is empty, let alone offering the user a file dialog to save the data. I've stepped through this code, and it brings back data from the service, writes it, and throws no errors. So what am I doing wrong?

EDIT: Returning this ...

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

... gives me a response, consisting of the csv-formatted data that I'm expecting. But the browser still doesn't seem to know what to do with it - no download option is offered to the user.


回答1:


Try below code:

    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

Below is how to pass a complex type model to an action method which is using GET HTTP method. I don't prefer this approach, it just gives you an idea there is an approach to achieve this.

Model

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

Action:

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

View:

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



回答2:


Try in the controller:

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



回答3:


Could also user dynamic keyword for converting any data

Code from @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();
    }
}


来源:https://stackoverflow.com/questions/21093150/using-csvhelper-to-output-stream-to-browser

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!