问题

我想在我的ASP中返回一个文件。Net Web API控制器,但我所有的方法返回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。


当前回答

ASP。NET 5 WEB API和Angular 12

您可以从服务器返回一个FileContentResult对象(Blob)。它不会被自动下载。你可以通过编程的方式在前端应用程序中创建一个锚标记,并将href属性设置为通过下面的方法从Blob创建的对象URL。现在点击锚点将下载文件。你也可以通过将“download”属性设置为锚来设置文件名。

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

}

其他回答

下面是在.NET Core Web API中返回文件(例如图像文件)的基本示例:

<img src="@Url.Action("RenderImage", new { id = id})" alt="No Image found" />

下面是将文件从控制器返回到视图的代码。下面是Action方法,它将返回文件:

    [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),以便检索。

ASP。NET 5 WEB API和Angular 12

您可以从服务器返回一个FileContentResult对象(Blob)。它不会被自动下载。你可以通过编程的方式在前端应用程序中创建一个锚标记,并将href属性设置为通过下面的方法从Blob创建的对象URL。现在点击锚点将下载文件。你也可以通过将“download”属性设置为锚来设置文件名。

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为我工作。文件不是IActionResult。我不知道该怎么做。

你可以用这些方法返回FileResult:

1:返回FileStreamResult

    [HttpGet("get-file-stream/{id}"]
    public async Task<FileStreamResult> DownloadAsync(string id)
    {
        var fileName="myfileName.txt";
        var mimeType="application/...."; 
        Stream 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/...."; 
        byte[] 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");
}

注意:

请确保使用来自Microsoft.AspNetCore.Mvc而不是System.Web.Mvc的FileStreamResult。