这就是我通常的做法。我有一个扩展 FileResult 类的 CSVResult 类,如下所示:
public class CSVResult : FileResult
{
private IQueryable _data;
private string[] _headers;
public CSVResult(string fileName, IQueryable data)
: base("text/csv")
{
this.FileDownloadName = fileName;
_data = data;
}
public CSVResult(string fileName, IQueryable data, string[] headers)
: this(fileName, data)
{
_headers = headers;
}
// Returns a string array containing the headers (column names)
private string[] GetHeaders()
{
var headers = (from p in _data.ElementType.GetProperties()
select p.Name).ToArray();
return headers;
}
// Writes the CSV file to the http response
protected override void WriteFile(HttpResponseBase response)
{
Stream outputStream = response.OutputStream;
using (MemoryStream memoryStream = new MemoryStream())
{
WriteObject(memoryStream);
outputStream.Write(memoryStream.GetBuffer(), 0, (int)memoryStream.Length);
}
}
// Writes the CSV data into a stream
private void WriteObject(Stream stream)
{
StreamWriter writer = new StreamWriter(stream, System.Text.Encoding.Default);
if (_headers == null)
{
_headers = GetHeaders();
}
// First line for column names
foreach (var h in _headers)
{
writer.Write(string.Format("\"{0}\",", h));
}
writer.WriteLine();
foreach (var row in _data)
{
foreach (var p in row.GetType().GetProperties())
{
var value = p.GetValue(row, null);
string strValue = value == null ? string.Empty : value.ToString();
writer.Write(string.Format("\"{0}\",", strValue));
}
writer.WriteLine();
}
writer.Flush();
}
}
然后,您可以像这样在 Controller 中使用它:
public ActionResult ExportToCSV()
{
var data = customers.AsQueryable();
var fileName = "customers.csv";
return new CSVResult(fileName, data);
}
当您不提供列名时,CSVResult 类使用属性名作为列名。但是,您也可以像这样提供列名:
public ActionResult ExportToCSV()
{
var data = customers.AsQueryable();
var fileName = "customers.csv";
string[] headers = new string[] { "Customer ID", "Customer Name", "Account Price" };
return new CSVResult(fileName, data, headers);
}