【问题标题】:How to use streams, to generate csv file, using CsvHelper in .NET Core 3.1?如何使用流,生成 csv 文件,在 .NET Core 3.1 中使用 CsvHelper?
【发布时间】:2020-08-10 07:08:19
【问题描述】:

我正在开发一个 api,它必须在某个端点上返回 csv 文件。这是我负责生成 csv 的控制器:

    [ApiController]
    [Route("api/[controller]")]
    [Authorize]
    public sealed class ReportController : BaseController
    {
        public ReportController(ICommandBus commandBus,
            IQueryBus queryBus)
                : base(commandBus, queryBus)
        {
        }

        [HttpGet]
        public async Task<IActionResult> GetReportAsync([FromQuery] GenerateReportRequest request)
        {
            try
            {
                var report = await QueryBus
                    .SendAsync<GenerateReportQuery, Report>(new GenerateReportQuery
                    {
                        Filters = request.Filters,
                        ResponseFileFormat = request.ResponseFileFormat,
                        WithPodOnly = request.WithPodOnly
                    });

                return File(report.Content,
                    report.Type,
                    report.Name);
            }
            catch (Exception e)
            {
                // ToDo: Handle exception in proper way
                return StatusCode(StatusCodes.Status500InternalServerError,
                    e.Message);
            }
        }
    }

当请求到达我的 api 时,会调用某些处理程序,并在 CsvGenerationStrategy 类中开始生成 csv,该类在下面附加:

    public class CsvGenerationStrategy : IReportGenerationStrategy
    {
        public async Task<Report> GenerateReportAsync(ICollection<ShipmentEntity> shipmentEntities)
        {
            var shipment = shipmentEntities
                .Select(s => (Shipment) s)
                .ToList();

            await using var memoryStream = new MemoryStream();
            await using var streamWriter = new StreamWriter(memoryStream);
            await using var csvWriter = new CsvWriter(streamWriter, CultureInfo.InvariantCulture);
            
            csvWriter.Configuration.Delimiter = ";";
            
            await csvWriter.WriteRecordsAsync(shipment);
            var content = memoryStream.ToArray();

            var report = new Report
            {
                Content = content,
                Type = ReportConstants.CsvFileType,
                Name = ReportConstants.CsvReportFileName
            };

            return report;
        }

        private class Shipment
        {
            [Name(ReportConstants.IssueColumnName)]
            public string Issue { get; set; }
            [Name(ReportConstants.MaterialReleaseReceiptColumnName)]
            public string MaterialReleaseReceipt { get; set; }
            [Name(ReportConstants.FreightBillIssueColumnName)]
            public string FreightBillIssue { get; set; }
            [Name(ReportConstants.InvoiceNumberColumnName)]
            public string InvoiceNumber { get; set; }
            [Name(ReportConstants.TaxCodeColumnName)]
            public string TaxCode { get; set; }
            [Name(ReportConstants.ContractorIdColumnName)]
            public string ContractorId { get; set; }
            [Name(ReportConstants.AddressIdColumnName)]
            public string AddressId { get; set; }
            [Name(ReportConstants.ContractorNameColumnName)]
            public string ContractorName { get; set; }
            [Name(ReportConstants.ShipmentCountryColumnName)]
            public string ShipmentCountry { get; set; }

            public static explicit operator Shipment(ShipmentEntity entity) =>
                entity != null
                    ? new Shipment
                        {
                            Issue = entity.Issue,
                            MaterialReleaseReceipt = entity.MaterialReleaseReceipt,
                            FreightBillIssue = entity.FreightBillIssue,
                            InvoiceNumber = entity.InvoiceNumber,
                            TaxCode = entity.TaxCode,
                            ContractorId = entity.ContractorId,
                            AddressId = entity.AddressId,
                            ContractorName = entity.ContractorName,
                            ShipmentCountry = entity.ShipmentCountry
                        }
                    : null;
        }
    }

代码看起来很正常,但是类的行为很奇怪。在大多数情况下,生成运行正常,但我很少注意到一种情况,即 MemoryStream 对象不包含数据,即使发货收集是正确的。我相信,这种行为不依赖于作为参数传递的数据。可能我在流中做错了什么。如何正确使用它们?如何使用 CsvHelper 库正确生成 csv 文件?

【问题讨论】:

    标签: c# csv .net-core csvhelper


    【解决方案1】:

    我找到了解决方案。 StreamWriter 必须在写入记录后被刷新,所以现在函数如下所示:

            public async Task<Report> GenerateReportAsync(ICollection<ShipmentEntity> shipmentEntities)
            {
                var shipment = shipmentEntities
                    .Select(s => (Shipment) s)
                    .ToList();
    
                await using var memoryStream = new MemoryStream();
                await using var streamWriter = new StreamWriter(memoryStream);
                await using var csvWriter = new CsvWriter(streamWriter, CultureInfo.InvariantCulture);
                
                csvWriter.Configuration.Delimiter = ";";
                
                await csvWriter.WriteRecordsAsync(shipment);
                await streamWriter.FlushAsync();
    
                var report = new Report
                {
                    Content = memoryStream.ToArray(),
                    Type = ReportConstants.CsvFileType,
                    Name = ReportConstants.CsvReportFileName
                };
    
                return report;
            }
    

    而且它工作正常:)

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2020-05-06
      • 2018-09-24
      • 2021-10-02
      • 1970-01-01
      • 1970-01-01
      • 2020-04-03
      相关资源
      最近更新 更多