C#实现以文件流的形式返回本地文件或远程文件路径

 更新时间:2025年08月21日 15:49:43   作者:VipSoft  
FileStream和FileInfo只能处理本地文件路径,无法直接处理HTTP URL,所以下面小编就来和大家详细介绍一下C#如何实现以文件流的形式返回本地文件或远程文件路径吧

FileStreamFileInfo只能处理本地文件路径,无法直接处理HTTP URL。以下是几种实现远程PDF返回给前端的解决方案:

方案1:使用HttpClient下载远程文件(推荐)

[HttpGet]
public async Task<HttpResponseMessage> GetReportFile()
{  
    try
    {
        string orderNo = HttpContext.Current.Request.QueryString["orderNo"];
        string filePath = "D:\\1.pdf";
        
        if(!string.IsNullOrEmpty(orderNo))
        {            
            filePath = "http://www.a.com/1.pdf";
            
            // 使用HttpClient下载远程文件
            using (var httpClient = new HttpClient())
            {
                // 设置超时时间
                httpClient.Timeout = TimeSpan.FromSeconds(30);
                
                // 下载文件内容
                var response = await httpClient.GetAsync(filePath);
                response.EnsureSuccessStatusCode();
                
                var content = await response.Content.ReadAsByteArrayAsync();
                
                // 创建返回结果
                var result = new HttpResponseMessage(HttpStatusCode.OK);
                result.Content = new ByteArrayContent(content);
                result.Content.Headers.ContentType = new MediaTypeHeaderValue("application/pdf");
                result.Content.Headers.ContentDisposition = new ContentDispositionHeaderValue("inline")
                {
                    FileName = "document.pdf"
                };
                
                return result;
            }
        }
        else
        {
            // 处理本地文件
            FileInfo foundFileInfo = new FileInfo(filePath);
            FileStream fs = new FileStream(filePath, FileMode.Open, FileAccess.Read, FileShare.ReadWrite);
            
            var result = new HttpResponseMessage(HttpStatusCode.OK);
            result.Content = new StreamContent(fs);
            result.Content.Headers.ContentType = new MediaTypeHeaderValue("application/pdf");
            result.Content.Headers.ContentDisposition = new ContentDispositionHeaderValue("inline")
            {
                FileName = foundFileInfo.Name
            };
            
            return result;
        }
    }
    catch (Exception ex)
    {
        logger.Error(ex, ex.Message);
        return new HttpResponseMessage(HttpStatusCode.BadRequest);
    }
}

方案2:流式传输(节省内存)【推荐】

[HttpGet]
public async Task<HttpResponseMessage> GetReportFile()
{  
    try
    {
        string orderNo = HttpContext.Current.Request.QueryString["orderNo"];
        string filePath = "D:\\1.pdf";
        
        if(!string.IsNullOrEmpty(orderNo))
        {            
            filePath = "http://www.a.com/1.pdf";
            
            using (var httpClient = new HttpClient())
            {
                httpClient.Timeout = TimeSpan.FromSeconds(30);
                
                // 流式下载
                var response = await httpClient.GetAsync(filePath, HttpCompletionOption.ResponseHeadersRead);
                response.EnsureSuccessStatusCode();
                
                var stream = await response.Content.ReadAsStreamAsync();
                
                var result = new HttpResponseMessage(HttpStatusCode.OK);
                result.Content = new StreamContent(stream);
                result.Content.Headers.ContentType = new MediaTypeHeaderValue("application/pdf");
                result.Content.Headers.ContentDisposition = new ContentDispositionHeaderValue("inline")
                {
                    FileName = "document.pdf"
                };
                
                return result;
            }
        }
        else
        {
            // 本地文件处理...
        }
    }
    catch (Exception ex)
    {
        logger.Error(ex, ex.Message);
        return new HttpResponseMessage(HttpStatusCode.BadRequest);
    }
}

方案3:添加缓存和错误处理

[HttpGet]
public async Task<HttpResponseMessage> GetReportFile()
{  
    try
    {
        string orderNo = HttpContext.Current.Request.QueryString["orderNo"];
        string filePath = "D:\\1.pdf";
        
        if(!string.IsNullOrEmpty(orderNo))
        {            
            filePath = "http://www.a.com/1.pdf";
            
            using (var httpClient = new HttpClient())
            {
                // 添加User-Agent头,有些服务器需要
                httpClient.DefaultRequestHeaders.Add("User-Agent", "Mozilla/5.0");
                httpClient.Timeout = TimeSpan.FromSeconds(30);
                
                // 先获取头部信息检查文件是否存在
                var headResponse = await httpClient.SendAsync(new HttpRequestMessage(HttpMethod.Head, filePath));
                
                if (!headResponse.IsSuccessStatusCode)
                {
                    return new HttpResponseMessage(HttpStatusCode.NotFound)
                    {
                        Content = new StringContent("远程文件未找到")
                    };
                }
                
                // 获取文件名(从Content-Disposition或URL中提取)
                string fileName = "document.pdf";
                if (headResponse.Content.Headers.ContentDisposition != null)
                {
                    fileName = headResponse.Content.Headers.ContentDisposition.FileName ?? fileName;
                }
                
                // 下载文件
                var getResponse = await httpClient.GetAsync(filePath, HttpCompletionOption.ResponseHeadersRead);
                getResponse.EnsureSuccessStatusCode();
                
                var result = new HttpResponseMessage(HttpStatusCode.OK);
                result.Content = new StreamContent(await getResponse.Content.ReadAsStreamAsync());
                result.Content.Headers.ContentType = new MediaTypeHeaderValue("application/pdf");
                result.Content.Headers.ContentDisposition = new ContentDispositionHeaderValue("inline")
                {
                    FileName = fileName
                };
                
                // 添加缓存头(可选)
                result.Headers.CacheControl = new CacheControlHeaderValue()
                {
                    MaxAge = TimeSpan.FromHours(1)
                };
                
                return result;
            }
        }
        else
        {
            // 本地文件处理...
        }
    }
    catch (HttpRequestException httpEx)
    {
        logger.Error(httpEx, "网络请求错误");
        return new HttpResponseMessage(HttpStatusCode.BadGateway);
    }
    catch (TaskCanceledException timeoutEx)
    {
        logger.Error(timeoutEx, "请求超时");
        return new HttpResponseMessage(HttpStatusCode.RequestTimeout);
    }
    catch (Exception ex)
    {
        logger.Error(ex, ex.Message);
        return new HttpResponseMessage(HttpStatusCode.InternalServerError);
    }
}

重要注意事项

  • 异步方法:将方法改为async Task<HttpResponseMessage>以支持异步操作
  • 资源释放:确保正确释放HttpClient和流资源
  • 超时处理:为远程请求设置合理的超时时间
  • 错误处理:添加针对网络请求的特定错误处理
  • 内存考虑:对于大文件,使用流式传输避免内存溢出

推荐使用方案2的流式传输,因为它内存效率更高,特别适合处理大文件。

到此这篇关于C#实现以文件流的形式返回本地文件或远程文件路径的文章就介绍到这了,更多相关C#文件流返回文件路径内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

相关文章

  • C#中File静态类对文件的读取写入

    C#中File静态类对文件的读取写入

    这篇文章介绍了C#中File静态类对文件的读取写入,文中通过示例代码介绍的非常详细。对大家的学习或工作具有一定的参考借鉴价值,需要的朋友可以参考下
    2022-05-05
  • C# 使用HttpClient上传文件并附带其他参数的步骤

    C# 使用HttpClient上传文件并附带其他参数的步骤

    这篇文章主要介绍了C# 使用HttpClient上传文件并附带其他参数的步骤,帮助大家更好的理解和使用c#,感兴趣的朋友可以了解下
    2020-12-12
  • C#使用log4net的3种调用方法

    C#使用log4net的3种调用方法

    log4net是一个用于记录日志的开源框架,它是C#中最常用的日志记录工具之一,本文给大家介绍了C#使用log4net的3种调用方法,通过图文和代码给大家讲解的非常详细,需要的朋友可以参考下
    2024-03-03
  • C#词法分析器之词法分析的使用详解

    C#词法分析器之词法分析的使用详解

    本篇文章介绍了,C#词法分析器之词法分析的使用详解。需要的朋友参考下
    2013-05-05
  • C#(WinForm) ComboBox和ListBox添加项及设置默认选择项

    C#(WinForm) ComboBox和ListBox添加项及设置默认选择项

    这篇文章主要介绍了C#(WinForm) ComboBox和ListBox添加项及设置默认选择项的的相关资料,需要的朋友可以参考下
    2014-07-07
  • C# WPF 自定义按钮的方法

    C# WPF 自定义按钮的方法

    这篇文章主要介绍了C# WPF 自定义按钮的方法,帮助大家更好的理解和学习使用c#,感兴趣的朋友可以了解下
    2021-03-03
  • C# wpf利用附加属性实现界面上定义装饰器

    C# wpf利用附加属性实现界面上定义装饰器

    装饰器是wpf中可以浮在控件上面的一种组件,我们通常可以用来实现一些诸如控件拖动点、提示框、自定义鼠标等界面功能。本文主要是利用附加属性实现界面上定义装饰器,需要的可以参考下
    2022-12-12
  • c# 获取字符串的字节数的方法

    c# 获取字符串的字节数的方法

    本篇文章主要是对c#中获取字符串的字节数的方法进行了介绍,需要的朋友可以过来参考下,希望对大家有所帮助
    2014-01-01
  • Unity打包代码到DLL的实现

    Unity打包代码到DLL的实现

    本文主要介绍了Unity打包代码到DLL的实现,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2023-03-03
  • 浅析wpf中datagrid显示列的问题

    浅析wpf中datagrid显示列的问题

    这篇文章主要为大家详细介绍了wpf中datagrid显示列问题的相关知识,文中的示例代码讲解详细,具有一定的借鉴价值,有需要的小伙伴可以学习一下
    2024-04-04

最新评论