5

我想使用 Web API 5.0 返回从我的数据库生成的 csv 它工作正常,除了返回的 csv 被截断。

我认为问题出在 MemoryBuffer 管理上,但我找不到它在哪里。

我的代码(已解决):

        IEnumerable<MasterObsTrip> masterTripList = _obsvMasterRepo.GetObsTrips(vesselName, dateYear, port, obsvCode, obsvTripCode, obsvProgCode, lastModifiedDateYear, lastModifiedBy, statusCode);
        IList<MasterObsTripModel> masterTripModelList = new List<MasterObsTripModel>();
        foreach (MasterObsTrip trip in masterTripList)
            masterTripModelList.Add(new MasterObsTripModel(trip));

        var stream = new MemoryStream();
        var writer = new StreamWriter(stream);

        CsvFileDescription outputFileDescription = new CsvFileDescription
        {
            SeparatorChar = ',', // comma delimited
            FirstLineHasColumnNames = true, // no column names in first record
            FileCultureName = "nl-NL" // use formats used in The Netherlands
        };
        CsvContext cc = new CsvContext();
        cc.Write(masterTripModelList,writer,outputFileDescription);
        writer.Flush();
        stream.Position = 0;
        HttpResponseMessage response = new HttpResponseMessage(HttpStatusCode.OK);
        response.Content = new StreamContent(stream);
        response.Content.Headers.ContentType = new MediaTypeHeaderValue("application/octet-stream");
        response.Content.Headers.ContentDisposition = new ContentDispositionHeaderValue("attachment");
        response.Content.Headers.ContentDisposition.FileName = "ObserverTripList.csv";
        stream.Flush();
        return response;

谢谢

4

1 回答 1

6

在重置 stream.Position = 0 之前,我会尝试执行 writer.Flush()

此外,如果您经常需要 CSV 内容,我还建议您自己创建一个 CsvContent 类。

public class CsvContent<T> : HttpContent
    {
        private readonly MemoryStream _stream = new MemoryStream();
        public CsvContent(CsvFileDescription outputFileDescription, string filename, IEnumerable<T> data)
        {
            var cc = new CsvContext();
            var writer = new StreamWriter(_stream);
            cc.Write(data, writer, outputFileDescription);
            writer.Flush();
            _stream.Position = 0;

            Headers.ContentType = new MediaTypeHeaderValue("application/octet-stream");
            Headers.ContentDisposition = new ContentDispositionHeaderValue("attachment");
            Headers.ContentDisposition.FileName = filename;

        }
        protected override Task SerializeToStreamAsync(Stream stream, TransportContext context)
        {
            return _stream.CopyToAsync(stream);
        }

        protected override bool TryComputeLength(out long length)
        {
            length = _stream.Length;
            return true;
        }
    }

然后你的控制器动作减少到......

IEnumerable<MasterObsTrip> masterTripList = _obsvMasterRepo.GetObsTrips(vesselName, dateYear, port, obsvCode, obsvTripCode, obsvProgCode, lastModifiedDateYear, lastModifiedBy, statusCode);
        IList<MasterObsTripModel> masterTripModelList = new List<MasterObsTripModel>();
        foreach (MasterObsTrip trip in masterTripList)
            masterTripModelList.Add(new MasterObsTripModel(trip));

        CsvFileDescription outputFileDescription = new CsvFileDescription
        {
            SeparatorChar = ',', // comma delimited
            FirstLineHasColumnNames = true, // no column names in first record
            FileCultureName = "nl-NL" // use formats used in The Netherlands
        };
        HttpResponseMessage response = new HttpResponseMessage(HttpStatusCode.OK) {
           Content = new CsvContent<MasterObsTripModel> (outputFileDescription, 
                                                      "ObserverTripList.csv", 
                                                       masterTripModelList);
        }
        return response;

这可以通过在 CsvContent 类中包含 CsvFileDescription 的创建来进一步简化。

于 2013-11-14T02:44:40.980 回答