Класс HttpResult в ServiceStack неправильно форматирует файлы CSV - PullRequest
0 голосов
/ 08 января 2020

Я пытаюсь вывести файл CSV, используя конечную точку службы в ServiceStack, используя класс HttpResult.

Сама строка CSV создается с помощью StringWriter и CsvHelper.

Если тип контента установлен на «текст / обычный», текст отображается на экране браузера нормально при нажатии 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, но когда я попытался установить его, я получил ошибку в связи с наличием нескольких элементов заголовка.

EDIT: Извините, я забыл включить фрагмент кода.

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

1 Ответ

1 голос
/ 08 января 2020

Из вашего описания ваш HttpResult файл ответа может быть сериализован встроенным CSV форматом .

Если вы не используете его, вы можете удалить его с помощью:

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

Изменить, так как вы возвращаете raw CSV string вы можете записать его в ответ с помощью:

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