Asp.net Web API - Как установить имя файла для настраиваемого формата CSV Media Type Formatter
Я успешно реализовал формат Csv Media Type Formatter в моем проекте ASP.Net Web API. Я могу получить результаты в формате Csv. Однако результирующее имя файла является "частями" без расширения.
В идеале, я хочу иметь возможность установить это имя файла в контроллере, но возможность добавления расширения по всему миру будет минимальным.
Ниже приведены примеры, которые я нашел
Переопределить OnGetResponseHeaders - я не вижу это как вариант в текущей версии.
http://forums.asp.net/t/1782973.aspx/1?Setting+response+and+content+headers+esp+ContentDisposition+inside+a+MediaTypeFormatter
В соответствии с этой статьей это должно работать
public override IEnumerable<KeyValuePair<string, string>> OnGetResponseHeaders(Type objectType, string mediaType, HttpResponseMessage responseMessage)
{
return new[] { new KeyValuePair<string, string>("Content-Disposition", "attachment; filename=testing.csv") };
}
Однако Visual Studio говорит: "Нет подходящего метода для переопределения" и не будет компилироваться, когда я добавлю это в свой пользовательский Csv Formatter.
Возврат HttpMessageResponse от контроллера - Как установить загрузку имени файла в веб-API ASP.NET
Однако, похоже, это просто толкает существующие файлы сервера, что приведет к сериализации Csv из состава. Ниже приведена попытка сделать такой подход:
public HttpResponseMessage Get(string id)
{
var response = new HttpResponseMessage();
if (id == "test")
{
var data = GetTestData();
response.StatusCode = HttpStatusCode.OK;
response.Content = new StreamContent(data);
response.Content.Headers.ContentDisposition = new ContentDispositionHeaderValue("attachment");
response.Content.Headers.ContentDisposition.FileName = "testorama.csv";
return response;
}
return null;
}
Проблема в том, что новый StreamContent() ожидает поток - есть ли способ получить текущий поток, созданный Custom Csv Formatter?
В нижней строке, как я могу установить имя файла для набора результатов, который сначала сериализуется в формате Csv?
Решение
Спасибо Клаудио - это заставило меня двигаться в правильном направлении. Пара изменится с того, что вы разместили:
-
Я извлекал из BufferedMediaTypeFormatter для своего пользовательского Csv
Formatter и использовать SetDefaultContentHeaders мне пришлось вместо этого
вытекает из MediaTypeFormatter.
-
SetDefaultContentHeaders принимает параметр mediaType с типом MediaTypeHeaderValue, а не строка.
Вот окончательный код:
public override void SetDefaultContentHeaders(Type type, HttpContentHeaders headers, MediaTypeHeaderValue mediaType)
{
base.SetDefaultContentHeaders(type, headers, mediaType);
headers.Add("Content-Disposition", "attachment; filename=testorama.csv");
}
Ответы
Ответ 1
Отмените метод SetDefaultContentHeaders
на свой MediaTypeFormatter
public override void SetDefaultContentHeaders(
Type type, HttpContentHeaders headers, string mediaType)
{
base.SetDefaultContentHeaders(type, headers, mediaType);
headers.Add("Content-Disposition", "attachment; filename=yourname.csv");
}
Ответ 2
Чтобы создать собственное имя на основе данных (по крайней мере, в Web API 2), вы захотите переопределить GetPerRequestFormatterInstance. Оттуда вы можете получить доступ к HttpRequestMessage.
private string FileName { get; set; }
public override void SetDefaultContentHeaders(Type type, HttpContentHeaders headers, MediaTypeHeaderValue mediaType)
{
base.SetDefaultContentHeaders(type, headers, mediaType);
if (!string.IsNullOrEmpty(FileName))
headers.Add("Content-Disposition", string.Format("attachment; filename={0}", FileName));
}
public override MediaTypeFormatter GetPerRequestFormatterInstance(Type type, HttpRequestMessage request, MediaTypeHeaderValue mediaType)
{
// We aren't setting the name, so just return the current instance.
if (!request.Properties.ContainsKey("filename")) return this;
var formatter = new CsvFormatter();
var fileName = request.Properties["filename"] as string;
formatter.FileName = string.Format("{0}.csv", fileName);
return formatter;
}
Затем в действии вашего контроллера вы можете установить имя файла следующим образом:
if (!Request.Properties.ContainsKey("filename"))
Request.Properties.Add("filename", "MyFile.{ext}");
Я использую {ext} в случае добавления дополнительных форматировщиков, которым требуется имя файла. Теоретически, только расширение должно измениться для поддержки других форматов.