.Net WebAPI 高速下载文件接口实现

2023-11-19

接触WebAPI一年多了,感觉是个承上启下,开创未来的技术。老一辈程序员写接口就像写方法一样,不需要了解太多网页的知识,却可以在浏览器中访问这些接口;由于是基于HTTP协议,因此不管是PC、手机还是嵌入式均可顺利访问。对于当下软件多终端的设计结构来说,这就像是量身订做的一样。

在开发的过程中遇到了一些问题,大部分都可通过百度找到解决方案,但是有一个问题却一直没有很好地解决,那就是文件下载速度的问题。

网上找到的WebAPI下载文件的代码大都是以下方式:

using System;
using System.Collections;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Net;
using System.Net.Http;
using System.Runtime.Remoting.Contexts;
using System.Text;
using System.Threading.Tasks;
using System.Web;
using System.Web.Http;
using System.Web.Http.Cors;
using System.Net.Http.Headers;

namespace Service.Controller
{
    public partial class APIController : ApiController
    {
        public HttpResponseMessage GetFileResponse(string FilePath, string FileName = null, string ContentType = "application/octet-stream")
        {
            FileStream fs;
            HttpResponseMessage result;

            fs = new FileStream(FilePath, FileMode.Open, FileAccess.Read, FileShare.Read);

            result = new HttpResponseMessage(System.Net.HttpStatusCode.OK) { Content = new StreamContent(fs) };
            result.Content.Headers.ContentType = new System.Net.Http.Headers.MediaTypeHeaderValue(ContentType);
            result.Content.Headers.ContentDisposition = new System.Net.Http.Headers.ContentDispositionHeaderValue("attachment");
            result.Content.Headers.ContentDisposition.FileName = (null != FileName ? FileName : Path.GetFileName(FilePath));

            return result; 
        }
    }
}

这种方式虽然可以实现文件下载,但是下载速度实在太慢(在局域网中下载速度只有50K),稍大一点的文件就有可能导致客户端请求超时。

改为以下方式可实现高速下载的目的。在百兆局域网内实际测试可满速下载。


using System;
using System.Collections;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Net;
using System.Net.Http;
using System.Runtime.Remoting.Contexts;
using System.Text;
using System.Threading.Tasks;
using System.Web;
using System.Web.Http;
using System.Web.Http.Cors;
using System.Net.Http.Headers;

namespace Service.Controller
{
    public partial class APIController : ApiController
    {

        #region 辅助函数
        public interface IWriteStreamToResponse<T>
        {
            T Suorce { get; set; }
            void WriteToStream(Stream outputStream, HttpContent content, TransportContext context);
        }

        public class StreamFromFileName : IWriteStreamToResponse<string>
        {
            private string _suorce;


            public string Suorce
            {
                get
                {
                    return _suorce;
                }
                set
                {
                    _suorce = value;
                }
            }

            public async void WriteToStream(Stream outputStream, HttpContent content, TransportContext context)
            {
                try
                {
                    var buffer = new byte[1024 * 1024 * 2];
                    using (var video = File.Open(_suorce, FileMode.Open, FileAccess.Read, FileShare.Read))
                    {
                        var length = (int)video.Length;
                        var bytesRead = 1;

                        while (length > 0 && bytesRead > 0)
                        {
                            bytesRead = video.Read(buffer, 0, Math.Min(length, buffer.Length));
                            await outputStream.WriteAsync(buffer, 0, bytesRead);
                            length -= bytesRead;
                        }
                    }
                }
                catch (Exception ex)
                {
                    return;
                }
                finally
                {
                    outputStream.Close();
                }
            }
        }

        public class StreamFromBytes : IWriteStreamToResponse<Stream>
        {
            private Stream _source;


            public Stream Suorce
            {
                get
                {
                    return _source;
                }
                set
                {
                    _source = value;
                }
            }

            public async void WriteToStream(Stream outputStream, HttpContent content, TransportContext context)
            {
                try
                {
                    var buffer = new byte[1024 * 1024 * 2];
                    using (var video = _source)
                    {
                        var length = (int)video.Length;
                        var bytesRead = 1;

                        while (length > 0 && bytesRead > 0)
                        {
                            bytesRead = video.Read(buffer, 0, Math.Min(length, buffer.Length));
                            await outputStream.WriteAsync(buffer, 0, bytesRead);
                            length -= bytesRead;
                        }
                    }
                }
                catch (Exception ex)
                {
                    return;
                }
                finally
                {
                    _source.Close();
                    outputStream.Close();
                }
            }
        }
        #endregion

        public HttpResponseMessage GetFileResponse(string FilePath, string FileName = null, string ContentType = "application/octet-stream")
        {
            HttpResponseMessage response;
            IWriteStreamToResponse<string> ResponseStreamWriter;
            Action<Stream, HttpContent, TransportContext> sendMethod;

            ResponseStreamWriter = new StreamFromFileName() { Suorce = FilePath };
            sendMethod = ResponseStreamWriter.WriteToStream;
            response = Request.CreateResponse();
            response.Content = new System.Net.Http.PushStreamContent(sendMethod);

            response.Content.Headers.ContentType = new System.Net.Http.Headers.MediaTypeHeaderValue(ContentType);
            response.Content.Headers.ContentDisposition = new System.Net.Http.Headers.ContentDispositionHeaderValue("attachment");
            response.Content.Headers.ContentDisposition.FileName = (null != FileName ? FileName : Path.GetFileName(FilePath));

            return response;
        }
    }
}



本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

.Net WebAPI 高速下载文件接口实现 的相关文章

随机推荐

  • 5G技术优势

    1G实现了移动通话 2G实现了短信 数字语音和手机上网 3G带来了基于图片的移动互联网 而4G则推动了移动视频的发展 5G网络则视为未来物联网 车联网等万物互联的基础 同时 5G普及将使得包括虚拟现实和增强现实这些技术成为主流 4G网络是专
  • 修改网页logo

    在用浏览器打开网站的时候 浏览器标签页上面有网站的图标 类似于logo小图标 如下图 步骤1 打开你的tomcat的安装目录 我的目录实在G盘 G apache tomcat 7 0 53 windows x64 apache tomcat
  • java进制转换方法

    一 十进制向二 八 十六进制的转换 方法一 Integer toBinaryString i 表示十进制转为二进制 Integer toOctalString i 表示十进制转为八进制 Integer toHexString i 表示十进制
  • 周庄不买门票攻略_周庄古镇旅游攻略

    周庄古镇旅游攻略 周庄古镇是世界文化遗产预选地 首批国家5A级旅游景区 位于苏州城东南 位于昆山 吴江 上海三地交界处 周庄古镇四面环水 因河成镇 依水成街 以街为市 井字型河道上完好保存着14座建于元 明 清各代的古石桥 800多户原住民
  • org/springframework/boot/maven/RepackageMojo has been compiled by a more recent version of the Java

    项目场景 项目中执行clean 再执行install时报错 错误如下 org springframework boot maven RepackageMojo has been compiled by a more recent versi
  • Python库之自然语言处理和文本挖掘

    来源地址 http www python88 com topic 37015 https mp weixin qq com s sPAomFg 5JZigFUG CtnaQ 自然语言处理和文本挖掘库主要用于以自然语言文本为对象的数据处理和建
  • linux基本命令练习

    1 列出 etc目录下的所有文件名称 2 创建文件file1 和file2 并复制到 home目录下 3 显示以ma开头的所有命令 ma 双击两次 TAB键 4显示所有文件名中有 bash的文件 用tab命令补全 5 显示当前所在的目录路径
  • android图像识别(百度普通物体识别)

    android图像识别 采用百度sdk 识别准确率基本上能用 主要缺陷是百度sdk免费额度有限 demo链接如下 仅供参考https download csdn net download android xc 12274161
  • Python进阶之CrawlSpider的应用及Scrapy配置项的引用

    1 CrawlSpider的应用 CrawlSpider可以根据规则自动分析链接的数据并按照正则的要求取出需要的数据 scrajpy startproject yg cd yg 注意 t crawl参数 scrapy genspider t
  • 解决SqlServer批量插入最多2100条数据的方法

    SqlServer批量插入数据时最多不能超过2100条 记录一下解决办法 Java代码 public void batchInsert List
  • 基于vue实现移动端点击上方导航,内容滑动切换,滑动内容导航自动切换。

    这是在日常开发过程中常见的选项卡 带滑动切换效果 小白一枚 不足之处还望体谅 包涵 这也是第一次尝试写博客 以后会继续分享一些工作中的问题与收获 实现效果 点击上方导航 当前导航添加样式 下方内容滑动切换 滑动下方内容上面导航切换 第一步
  • 论文笔记:Region Representation Learning via Mobility Flow

    2017 CIKM 1 摘要和介绍 使用出租车出行数据学习区域向量表征 同时考虑时间动态和多跳位置转换 gt 通过flow graph和spatial graph学习表征 出租车交通流可以作为区域相似度的一种 A区域和B区域之间流量大 gt
  • JS 变量提升和函数提升

    变量提升 这里介绍一个变量提升提升的经典案例 for var i 0 i lt 10 i setTimeout gt console log i 1000 这里打印是10个10 因为在执行第一个setTimeout时 Js不会等待1秒后再去
  • 怎么解决“无法打开包括文件:“graphics.h”: No such file or directory”的问题

    在接手同伴的中国象棋项目时 导入项目后 发现VS一直提示 无法打开包括文件 graphics h No such file or directory 在查阅资料后发现是缺少easyx文件 接下来 就介绍一下手动配置一下easyx文件 eas
  • 特殊类型动归--区间动归与环形动归

    区间动归 某类有序事件中前若干个事件的子答案 不能再支撑状态转移 我们需要去寻找 从某个元素起到另一个元素结束所包含所有的 连续 元素的子答案 作为状态 可以想象 在这个描述下 每个状态会对应于原题序列上的一个区间 区间具有良好的性质 短的
  • 深度学习(1):BP神经网络实现银行客户流失预测

    目的 针对银行客户行为和统计数据实现客户流失预测任务 一 数据准备 1 数据集 select data csv 作为训练样本 数据预处理方式 归一化 数值化 CreditScore 信用分数 EB 存贷款情况 EstimatedSalary
  • centos 建立回收站

    linux下的回收站在每一个当前用户目录 local share Trash中 也可以给linux添加一个回收站 mkdir tmp trash tmp 建立一个回收站目录 vi bin trash 编辑一个文件 mv tmp trash
  • python之浅拷贝、深拷贝

    什么是浅拷贝 深拷贝 理论来自python基础教程 在 Python 中 对象赋值实际上是对象的引用 当创建一个对象 然后把它赋给另一个变量的时候 Python 并没有拷贝这个对象 而只是拷贝了这个对象的引用 我们称之为浅拷贝 在 Pyth
  • 腾讯云 Finops Crane 开发者集训营 - 云原生如何助力企业搞定成本优化

    引言 随着docker的技术普及 越来越多的企业加入了云计算发展进程 云原生产业发展迅猛 云原生建设投入比例明显 面对大规模的集群投入 部署 维护等问题也逐渐产生 越来越多的企业对云原生不断提出更高要求 同时云原生技术简化运维的效能提 升开
  • .Net WebAPI 高速下载文件接口实现

    接触WebAPI一年多了 感觉是个承上启下 开创未来的技术 老一辈程序员写接口就像写方法一样 不需要了解太多网页的知识 却可以在浏览器中访问这些接口 由于是基于HTTP协议 因此不管是PC 手机还是嵌入式均可顺利访问 对于当下软件多终端的设