Возвращаемый файл в ASP.Net Core Web API
проблема
Я хочу вернуть файл в мой ASP.Net Web API Controller, но все мои подходы возвращают HttpResponseMessage
как JSON.
Код пока
public async Task<HttpResponseMessage> DownloadAsync(string id)
{
var response = new HttpResponseMessage(HttpStatusCode.OK);
response.Content = new StreamContent({{__insert_stream_here__}});
response.Content.Headers.ContentType = new MediaTypeHeaderValue("application/octet-stream");
return response;
}
Когда я вызываю эту конечную точку в моем браузере, Web API возвращает HttpResponseMessage
как JSON с заголовком содержимого HTTP, установленным в application/json
,
7 ответов
Если это ASP.net-Core, то вы смешиваете версии веб-API. Пусть действие возвращает производное IActionResult
потому что в вашем текущем коде фреймворк лечит HttpResponseMessage
как модель.
[Route("api/[controller]")]
public class DownloadController : Controller {
//GET api/download/12345abc
[HttpGet("{id}"]
public async Task<IActionResult> Download(string id) {
Stream stream = await {{__get_stream_based_on_id_here__}}
if(stream == null)
return NotFound();
return File(stream, "application/octet-stream"); // returns a FileStreamResult
}
}
Вы можете вернуть FileResult следующими методами:
1: вернуть FileStreamResult
[HttpGet("get-file-stream/{id}"]
public async Task<FileStreamResult> DownloadAsync(string id)
{
var fileName="myfileName.txt";
var mimeType="application/....";
var stream = await GetFileStreamById(id);
return new FileStreamResult(stream, mimeType)
{
FileDownloadName = fileName
};
}
2: вернуть FileContentResult
[HttpGet("get-file-content/{id}"]
public async Task<FileContentResult> DownloadAsync(string id)
{
var fileName="myfileName.txt";
var mimeType="application/....";
var fileBytes = await GetFileBytesById(id);
return new FileContentResult(fileBytes, mimeType)
{
FileDownloadName = fileName
};
}
Вот упрощенный пример потоковой передачи файла:
using System.IO;
using Microsoft.AspNetCore.Mvc;
[HttpGet("{id}")]
public async Task<FileStreamResult> Download(int id)
{
var path = "<Get the file path using the ID>";
var stream = File.OpenRead(path);
return new FileStreamResult(stream, "application/octet-stream");
}
Заметка:
Обязательно используйте FileStreamResult
из Microsoft.AspNetCore.Mvc
а не изSystem.Web.Mvc
.
Веб-API ASP.NET 5 и Angular 12
Вы можете вернуть объект FileContentResult (Blob) с сервера. Он не будет загружен автоматически. Вы можете программно создать тег привязки в своем интерфейсном приложении и установить для свойства href URL-адрес объекта, созданный из Blob, описанным ниже способом. Теперь нажатие на якорь загрузит файл. Вы можете установить имя файла, установив также атрибут «загрузка» для привязки.
downloadFile(path: string): Observable<any> {
return this._httpClient.post(`${environment.ApiRoot}/accountVerification/downloadFile`, { path: path }, {
observe: 'response',
responseType: 'blob'
});
}
saveFile(path: string, fileName: string): void {
this._accountApprovalsService.downloadFile(path).pipe(
take(1)
).subscribe((resp) => {
let downloadLink = document.createElement('a');
downloadLink.href = window.URL.createObjectURL(resp.body);
downloadLink.setAttribute('download', fileName);
document.body.appendChild(downloadLink);
downloadLink.click();
downloadLink.remove();
});
}
Бэкэнд
[HttpPost]
[Authorize(Roles = "SystemAdmin, SystemUser")]
public async Task<IActionResult> DownloadFile(FilePath model)
{
if (ModelState.IsValid)
{
try
{
var fileName = System.IO.Path.GetFileName(model.Path);
var content = await System.IO.File.ReadAllBytesAsync(model.Path);
new FileExtensionContentTypeProvider()
.TryGetContentType(fileName, out string contentType);
return File(content, contentType, fileName);
}
catch
{
return BadRequest();
}
}
return BadRequest();
}
FileStreamResult у меня работает. и File не является IActionResult. Я не знаю, как это может работать.
Ниже приведен базовый пример возврата файла (например, файла изображения) в .NET Core Web API:
<img src="@Url.Action("RenderImage", new { id = id})" alt="No Image found" />
Ниже приведен код для возврата файла из контроллера для просмотра. Ниже приведен метод действия, который вернет файл:
[Route("api/[controller]")]
public class DownloadController : Controller
{
//GET api/download/123
[HttpGet]
public async Task<IActionResult> RenderImage(string userId)
{
//get Image file using _fileservice from db
var result = await _fileService.getFile(userId);
if (result.byteStream == null)
return NotFound();
return File(result.byteStream, result.ContentType, result.FileName);
}
}
Примечание:
Наш файл должен быть сначала преобразован в byte[], а затем сохранен в базе данных как varbinary(max) для извлечения.
добавить builder.Services.AddSingleton(); в Program.cs
[HttpGet("{fileId}")]
public ActionResult GetFile(string fileId)
{
string pathToFile = "test.rar";
if (!System.IO.File.Exists(pathToFile))
{
return NotFound();
}
if(!_fileExtensionContentTypeProvider.TryGetContentType(pathToFile,
out var ContentType))
{
ContentType = "application/octet-stream";
}
var byets=System.IO.File.ReadAllBytes(pathToFile);
return File(byets, ContentType, Path.GetFileName(pathToFile));
}
}