从Asp.Net Core WebAPI返回jpeg图像

85
使用 asp.net core web api,我希望我的控制器动作方法返回一个jpeg图像流
在我的当前实现中,浏览器仅显示json字符串。 我的期望是在浏览器中看到图片。
使用Chrome开发者工具进行调试时,我发现响应头中仍然返回了

Content-Type: application/json; charset=utf-8

的内容类型,尽管在我的代码中我手动设置了内容类型为"image/jpeg"。 寻找解决方案,我的Web API如下。
[HttpGet]
public async Task<HttpResponseMessage> Get()
{
    var image = System.IO.File.OpenRead("C:\\test\random_image.jpeg");
    var stream = new MemoryStream();

    image.CopyTo(stream);
    stream.Position = 0;            
    result.Content = new StreamContent(image);
    result.Content.Headers.ContentDisposition = new ContentDispositionHeaderValue("attachment");
    result.Content.Headers.ContentDisposition.FileName = "random_image.jpeg";
    result.Content.Headers.ContentType = new MediaTypeHeaderValue("image/jpeg");
    result.Content.Headers.ContentLength = stream.Length;

    return result;
}

在这里输入图片描述

4个回答

143

清晰的解决方案是使用FilestreamResult!!

[HttpGet]
public IActionResult Get()
{
    var image = System.IO.File.OpenRead("C:\\test\\random_image.jpeg");
    return File(image, "image/jpeg");
}

说明:

在ASP.NET Core中,您必须在控制器内使用内置的File()方法。这将允许您手动设置内容类型。

不要像在ASP.NET Web API 2中那样创建和返回HttpResponseMessage,它什么都不做,甚至不会抛出错误!!


4
Visual Studio提示该方法缺少await使用,因此将同步运行。是否可以缓存文件,以便不必每次都读取?为什么不使用重载的File方法接受文件路径而不是读取文件?如果要读取文件,为什么不使用using语句? - developer82
2
将代码行写成: return await Task.Run(() => File(image, "image/jpeg"));为我解决了错误,并且也起作用。 - jman
4
将方法从“async Task<IActionResult>”改写为“IActionResult”,以更加简洁的方式解决问题(Visual Studio会正确指示该方法具有异步行为);)... - DotBert
2
不要忘记处理OpenRead对象,但PhysicalFile是更好的解决方案。 - gbjbaanb
1
修改了代码,使得在 VS 中不再显示异步警告 @DotBert - hannes neukermans
显示剩余2条评论

18

PhysicalFile可帮助以简单的语法从Asp.Net Core WebAPI返回文件。

    [HttpGet]
    public IActionResult Get(int imageId)
    {            
       return PhysicalFile(@"C:\test.jpg", "image/jpeg");
    }

2
我想知道这个程序是否是异步的?我不想遇到死锁或无法访问文件的情况。 - Mustafa Salih ASLIM
1
@ASLIM 方法PhysicalFile()返回一个PhysicalFileResult类型的实例,该实例支持execute-async。因此,如果我理解正确,ASP.NET基础架构将选择该异步方法,该方法将调用PhysicalFileResultExecutor.ExecuteAsync()->response.SendFileAsync()。所以我想异步部分是透明地处理的。 - XDS

0
在我的情况下,我使用了相对路径到图像,所以下面是我的有效解决方案。
[HttpGet]
public async Task<IActionResult> Get()
{
    var url = "/content/image.png";
    var path = GetPhysicalPathFromURelativeUrl(url);
    return PhysicalFile(image, "image/png");
}
public string GetPhysicalPathFromRelativeUrl(string url)
{            
    var path = Path.Combine(_host.Value.WebRootPath, url.TrimStart('/').Replace("/", "\\"));
    return path;
}

我认为这段代码是无效的。"image"变量没有被声明(第6行)。你是不是想用"path"代替它? - Christophe

-15
[HttpGet("Image/{id}")]
    public IActionResult Image(int id)
    {
        if(id == null){ return NotFound(); }
        else{

            byte[] imagen = "@C:\\test\random_image.jpeg";
            return File(imagen, "image/jpeg");
        }
    }

我不确定为什么他们会对这个进行负投票,因为我看到的只是一段可运行的代码。 - khaled Dehia
这个回答被踩是因为没有解释。仅仅给出代码的回答并不是好的回答。 - undefined

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接