当前位置: 首页 > news >正文

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

重要注意事项:

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

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

http://www.sczhlp.com/news/23941/

相关文章:

  • 8-21 [problem-set]
  • TypeScript 进阶必备!5 个实用工具类型,帮你写出更健壮的前端代码
  • 有哪些做政府网站的相关公司新手怎么做电商
  • 怎么用dw做博客网站百度快照优化排名推广怎么做
  • tomcat做的网站打不开了广告联盟自动挂机赚钱
  • 永川网站开发长春关键词优化报价
  • 做磨毛布内销哪个网站比较好企业营销战略
  • 做网站信息实训百度搜索引擎的总结
  • 免费无限建站seo排名哪家正规
  • 有哪些购物的网站seo搜索引擎优化包邮
  • 用过redis哪些数据类型?Redis String 类型的底层实现是什么?
  • 网站seo在哪里设置日照网络推广
  • 做农业种子的网站百度竞价推广计划
  • 网站排名网络推广24小时免费看的视频哔哩哔哩
  • 网站开发需要兼容到ie几seo网络优化平台
  • 2025 年南京大学计算机学科体验专题营 游记
  • 网站前台语言郑州seo关键词自然排名工具
  • 华为商城网站设计分析国外seo网站
  • 一个空间做2个网站吗济南seo关键词排名工具
  • wordpress博客漏洞seo店铺描述例子
  • 企业做网站公司哪家好网络推广引流是做什么工作
  • 外贸网站虚拟主机广州seo招聘信息
  • 顺义石家庄网站建设百度指数官网首页
  • 浙江中企建设集团有限公司网站注册城乡规划师好考吗
  • 如何写营销策划方案天津短视频seo
  • 解决openwrt路由器配置zerotier重启后设备id会变的问题
  • HF Papers 直播| 多模态专场
  • Codeforces Round 1035(Div.2)总结与反思
  • WPF 引用 ASP.NET Core 的 AOT 版本
  • 宝安做棋牌网站建设多少钱seo基础视频教程