Повернути файл у веб-API ASP.Net Core


131

Проблема

Я хочу повернути файл у свій 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;
}

Коли я називаю цю кінцеву точку у своєму браузері, веб-API повертає HttpResponseMessageJSON як заголовок вмісту HTTP application/json.

Відповіді:


228

Якщо це 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(); // returns a NotFoundResult with Status404NotFound response.

        return File(stream, "application/octet-stream"); // returns a FileStreamResult
    }    
}

12
У моєму випадку мені потрібно було створити Excel в пам'яті та повернути його для завантаження, тому мені потрібно було також визначити ім’я файлу з розширенням: return File(stream, "application/octet-stream", "filename.xlsx"); Таким чином, при завантаженні користувач може відкрити його безпосередньо.
KMJungersen

Я розумію, що в NotFound()кінцевому рахунку робить, але чи є він у .NET Core чи це щось місцеве для вашого проекту?
ΩmegaMan

2
@ ΩmegaMan - це допоміжний метод ControllerBaseі є частиною самої основи docs.microsoft.com/en-us/dotnet/api/…
Nkosi

3
Гаразд, знайшов свою проблему, хоча мій контролер працював у .NET Core 2.2, він не був похідний від базового класу Controller, тому не мав доступу до ControllerBase.NotFound()методу. Колись вийшло, все працювало. lol / thx
ΩmegaMan

1
Чи споживає цей метод системну пам'ять у випадку, якщо ви завантажуєте великі файли з сервера? Моя перша здогадка - ні, враховуючи той факт, що ми не створюємо новий MemoryStream (). Буду вдячний за відповідь. thx
Ehsan Najafi

16

Ви можете повернути 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
        };
    }

2
Якщо в межах ControllerBaseє багато перевантажених версій ControllerBase.Fileпомічника, який повертає будь-яку з них.
Nkosi

2
Ваша відповідь все ще справедлива. Тому не відчувайте себе розгубленим. Я тільки вказував на деякі ресурси, якими ви можете скористатися, щоб підтримати свою відповідь.
Nkosi

1
Так, це правда.
Hamed Naeemaei

10

Ось спрощений приклад передачі файлу:

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.

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.