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

来源:互联网 发布:ubuntu制作u盘启动工具 编辑:程序博客网 时间:2024/04/27 13:31

接触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;        }    }}



原创粉丝点击