从使用DMZ API的公共Asp Core API获取文件

时间:2019-08-25 09:07:17

标签: c# .net api web core

我有两个API:DMZ和Public(公共使用dmz) 1. DMZ:

    public FileStreamResult GetContent(int id)
    {
        var content = from m in db.messagestoimages
                      where m.Message == id
                      select m;

        if (content == null || content.Count() == 0)
        {
            return null;
        }
        string fileName = content.First().ImageURL;

        string fullPath = AppDomain.CurrentDomain.BaseDirectory  + fileName;
        if (File.Exists(fullPath))
        {
            var fileStream = new FileStream(fullPath, FileMode.Open, FileAccess.ReadWrite, FileShare.ReadWrite);
            var result = new FileStreamResult(fileStream, "image/jpeg");
            return result;
        }

        return null;
    }

2:公共API

   [HttpGet("{id}")]
    public FileStreamResult Get(string id)
    {
        try
        {
            {
                using (var client = new HttpClient())
                {
                    try
                    {
                        string host = configuration.GetSection("MySettings").GetSection("OctopusURL").Value;

                        client.BaseAddress = new Uri(host);

                        var response = client.GetAsync("api/Content/" + id);
                        var stream = response.Result.Content.ReadAsStreamAsync().Result;
                        return new FileStreamResult(stream, "image/jpeg")
                        {
                            FileDownloadName = "test.jpeg"
                        };
                    }
                    catch (Exception ex)
                    {
                        return null;
                    }
                }
            }

        }
        catch (Exception ex)
        {
            return null; // 500 is generic server error
        }
    }

我的问题是,当我从公共API获取文件时,这是错误的,我无法打开文件,Windows表示不支持格式。我得到的文件大小小于原始文件,这可能意味着文件已部分传输或出现错误。

enter image description here

1 个答案:

答案 0 :(得分:2)

直接将FileStream返回到HTTP响应可能会导致客户端下载文件不完整。

这是因为服务器和客户端之间的流不稳定。传输可能会暂停,可能会受到影响,可能会取消。但是从服务器和磁盘读取过程需要稳定的连接和稳定的速度。

您可以使用MemoryStream复制文件并将其返回到HTTP响应流。但是MemoryStream使用了很多内存,这可能会导致整个服务器停止工作。

BufferedStream返回文件是一种更好的方法。快速,稳定并且产生更少的东西。

但是从.NET Core中的服务器返回本地文件的最佳方法是使用:

Controller.PhysicalFileResult PhysicalFile(string physicalPath, string contentType, bool enableRangeProcessing);

修改您的DMZ API以使用PhysicalFile返回文件以获得最佳性能和稳定性。像这样:

    public IActionResult GetContent(int id)
    {
        var content = from m in db.messagestoimages
                      where m.Message == id
                      select m;

        if (content == null || content.Count() == 0)
        {
            return NotFound();
        }
        string fileName = content.First().ImageURL;

        string fullPath = AppDomain.CurrentDomain.BaseDirectory  + fileName;
        if (File.Exists(fullPath))
        {
            return PhysicalFile(fullPath, "image/jpeg", true);
        }

        return NotFound();
    }

对于您的公共API,我已经使用以下代码进行了测试:

using System;
using System.IO;
using System.Net.Http;

namespace Temp
{
    class Program
    {
        static void Main(string[] args)
        {
            using (var client = new HttpClient())
            {
                client.BaseAddress = new Uri("https://www.google.com");
                var response = client.GetAsync("/images/branding/googlelogo/2x/googlelogo_color_272x92dp.png");
                var stream = response.Result.Content.ReadAsStreamAsync().Result;
                using (var mstream = new MemoryStream())
                {
                    stream.CopyTo(mstream);
                    File.WriteAllBytes("a.png", mstream.ToArray());
                }
            }
        }
    }
}

可以正常工作并成功下载了文件,该文件也可以成功打开。

我想这不是公共API的问题。