ОБНОВЛЕНИЕ: Как я уже упоминал, я изменил свой метод действий, но безуспешно. Посмотреть скриншоты
Результат один и тот же:
Кратко о моей проблеме: все в dot net core 2.0. У меня есть WebAPI (отдельный проект) и его контроллер (разговор с SQL Server). Мое клиентское приложение - это веб-приложение ASP.NET Core MVC, метод действия его контроллера БУДЕТ возвращать файл. В моем случае поток байтов. Когда я открываю файл, который я загрузил из браузера, в котором запущено мое клиентское приложение, файл похож на некоторый HttpResponseMessage, завернутый в формат стиля JSON.
Контроллер API
[Route("api/[controller]")]
public class GasDownloadController : Controller
{
private readonly IGasesRepository _repository;
public GasDownloadController(IGasesRepository repository)
{
_repository = repository;
}
[HttpGet]
public HttpResponseMessage Export([FromQuery] Gas gas)
{
var item = _repository.GetGasesService(gas);
byte[] outputBuffer = null;
using (MemoryStream tempStream = new MemoryStream())
{
using (StreamWriter writer = new StreamWriter(tempStream))
{
FileWriter.WriteDataTable(item, writer, true);
}
outputBuffer = tempStream.ToArray();
}
HttpResponseMessage result = new HttpResponseMessage(HttpStatusCode.OK);
result.Content = new ByteArrayContent(outputBuffer);
result.Content.Headers.ContentType = new MediaTypeHeaderValue("text/csv");
result.Content.Headers.ContentDisposition = new ContentDispositionHeaderValue("attachment") { FileName = $"ENVSdata.csv" };
return result;
}
}
Вспомогательный класс
public class FileWriter
{
public static void WriteDataTable(DataTable sourceTable, TextWriter writer, bool includeHeaders)
{
if (includeHeaders)
{
writer.WriteLine("sep=,");
IEnumerable<string> headerValues = sourceTable.Columns
.OfType<DataColumn>()
.Select(column => QuoteValue(column.ColumnName));
writer.WriteLine(String.Join(",", headerValues));
}
IEnumerable<String> items = null;
foreach (DataRow row in sourceTable.Rows)
{
items = row.ItemArray.Select(o => QuoteValue(o?.ToString() ?? String.Empty));
writer.WriteLine(String.Join(",", items));
}
writer.Flush();
}
private static string QuoteValue(string value)
{
return String.Concat("\"",
value.Replace("\"", "\"\""), "\"");
}
}
Контроллер MVC
public class DownloadsController : Controller
{
private IGasesRepository _repository;
public DownloadsController(IGasesRepository repository)
{
_repository = repository;
}
[HttpGet]
public ActionResult Index()
{
return View();
}
[HttpPost]
public async Task<FileResult> GetFile(Gas inputGas)
{
var model = await _repository.GasDownloads(inputGas);
return File(model, "text/csv", "data.csv");
}
}
Репозиторий
public class GasesRepository : IGasesRepository
{
public IEnumerable<Gas> Gases { get; set; }
public byte[] CsvBytes { get; set; }
private string BaseGasApiUrl = "http://localhost:XXXX";
private string BaseDwnlApiUrl = "http://localhost:XXXX";
public async Task<IEnumerable<Gas>> GasService(Gas gasCompound)
{
//code omitted for brewity
}
public async Task<byte[]> GasDownloads(Gas gasCompound)
{
UriBuilder builder = new UriBuilder(BaseDwnlApiUrl);
builder.Query =
$"XXXXX";
using (var client = new HttpClient())
{
client.BaseAddress = new Uri(BaseDwnlApiUrl);
client.DefaultRequestHeaders.Accept.Clear();
try
{
HttpResponseMessage responseMessage = await client.GetAsync(builder.Uri);
if (responseMessage.IsSuccessStatusCode)
{
var apiResult = responseMessage.Content.ReadAsByteArrayAsync().Result;
CsvBytes = apiResult;
}
else
return null;
}
catch (HttpRequestException downloadRequestException)
{
throw new HttpRequestException(downloadRequestException.Message);
}
catch (ArgumentNullException argsNullException)
{
throw new ArgumentNullException(argsNullException.Message);
}
}
return CsvBytes;
}
}
РЕЗУЛЬТАТ
Итак, когда я открываю файл (например, Excel), загруженный моим браузером, это файл CSV, но вместо столбцов и строк и данных в нем это всего лишь
{
"version": {
"major": 1,
"minor": 1,
"build": -1,
"revision": -1,
"majorRevision": -1,
"minorRevision": -1
},
"content": {
"headers": [
{
"key": "Content-Type",
"value": [
"text\/csv"
]
},
{
"key": "Content-Disposition",
"value": [
"attachment; filename=data.csv"
]
}
]
},
"statusCode": 200,
"reasonPhrase": "OK",
"headers": [
],
"requestMessage": null,
"isSuccessStatusCode": true
}
Что я уже пробовал:
Если я отлаживаю, я вижу, что получаю допустимый/действительный массив байтов, но каким-то образом происходит какое-то волшебство, или он настолько очевиден и велик, что я не вижу леса за деревьями?
Я попытался изменить метод Action контроллера MVC, чтобы он возвращал множество возможных типов вещей (IActionResult, IHttpResponse, FileContentResult и т. д.).
У меня был тот же проект в MVC 5, и без проблем я получил действительный CSV-файл с моими строками и столбцами данных.
Любая помощь будет принята с благодарностью!
GasDownloadController.Export
, а неDownloadsController.GetFile
. - person Kirk Larkin   schedule 03.10.2017