【问题标题】:ServiceStack's HttpResult class does not properly format CSV filesServiceStack 的 HttpResult 类没有正确格式化 CSV 文件
【发布时间】:2020-01-08 10:58:54
【问题描述】:

我正在尝试使用 ServiceStack 中服务上的端点,使用 HttpResult 类来输出 CSV 文件。

CSV 字符串本身是通过 StringWriter 和 CsvHelper 构造的。

如果内容类型设置为“text/plain”,则在点击端点 URL 时,文本会正常显示在浏览器屏幕上。但是如果设置为“text/csv”,会生成一个CSV文件,但是里面的信息是不正确的。

例如:

预期输出:

Header 1, Header 2, Header 3

实际输出:

H,e,a,d,e,r, ,1,,, ,H,e,a,d,e,r, ,2,,, ,H,e,a,d,e,r, 3,"

有什么我可能遗漏的吗?

另外,顺便说一句,我如何设置文件本身的文件名?看来我必须使用 HttpHeaders.ContentDisposition,但是当我尝试设置它时,我遇到了一个错误,即有多个标题元素。

编辑:抱歉忘记包含代码 sn-p。

string response = string.Empty;

using (var writer = new StringWriter())
{
    using (var csv = new CsvWriter(writer))
    {
        csv.WriteHeader<TestClass>();
        foreach (var element in elements)
        {
            csv.WriteField(elements.header1);
            csv.WriteField(elements.header2);
            csv.WriteField(elements.header3);
            csv.NextRecord();
        }
    }

    //apparently double quotes can cause the rendered CSV to go wrong in some parts, so I added this as part of trying
    response = writer.ToString().Replace("\"", "");
}

return new HttpResult(response)
{
    StatusCode = HttpStatusCode.OK,
    ContentType = "test/csv"
};

还有关于TestClass的信息:

public class TestClass
{
    public string Header1 { get; set; }
    public string Header2 { get; set; }
    public string Header3 { get; set; }
}

【问题讨论】:

  • 请更新您的问题以包含Minimal Reproducible Example,如果他们看不到您实际在做什么,任何人都无法确定问题所在。
  • 对不起,我已经添加了代码 sn-ps。
  • 我已经更新了我的答案,展示了如何编写原始 CSV 字符串。

标签: c# servicestack csvhelper


【解决方案1】:

根据您的描述,您的HttpResult 文件响应可能会被内置的CSV Format 序列化。

如果您不使用它,可以使用以下方法将其删除:

Plugins.RemoveAll(x => x is CsvFormat);

否则,如果你正在使用它,你可以通过在你的服务实现中写入 CSV 文件来规避它的序列化,例如:

public class MyCsv : IReturn<string> {}

public async Task Any(MyCsv request)
{
    var file = base.VirtualFileSources.GetFile("path/to/my.csv");
    if (file == null)
        throw HttpError.NotFound("no csv here");

    Response.ContentType = MimeTypes.Csv;
    Response.AddHeader(HttpHeaders.ContentDisposition, 
        $"attachment; filename=\"{file.Name}\";");
    using (var stream = file.OpenRead())
    {
        await stream.CopyToAsync(Response.OutputStream);
        await Response.OutputStream.FlushAsync();
        Response.EndRequest(skipHeaders:true);
    }
}        

编辑,因为您返回的是原始 CSV string,您可以将其写入响应:

Response.ContentType = MimeTypes.Csv;
await Response.WriteAsync(response);
Response.EndRequest(skipHeaders:true);

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-12-10
    相关资源
    最近更新 更多