WebAPI上传大文件

今天在研究WebAPI的上传与下载,作为Rest的框架,更多是面向资源,就其本身来说,是不会涉及也不应该涉及到大文件的处理,具体多大呢,也就是ASP.NET的限值2G。

ASP.NET的pipeline对于上传文件一般的处理流程是接收到文件,放到内存中,我们也一般只处理后续的流程,例如存入硬盘等等。

目前想象的一个场景是上传一个大文件,后续处理可能有多种。如果并发数过多,肯定会造成内存溢出,所以参考资料与琢磨,搞定了这个问题。

但是场景本身是有一定问题的,这纯属个人爱好在玩,真实场景来说文件不宜过大,不是专门处理大文件的服务器与协议,无非就是用流的方式,但是大文件传输使用流采用可靠协议是最好的,可靠不是指TCP的可靠,而是指在如果断开后,后续的处理,例如断点。

如果是HTTP的断点,那就只有自己写了。

一、配置文件修改

不多说,这个必须的。

1   <system.web>
2     <compilation debug="true" targetFramework="4.5" />
3     <httpRuntime targetFramework="4.5" maxRequestLength="2147483647"/>
4   </system.web>

    <security>
      <requestFiltering >
        <requestLimits maxAllowedContentLength="2147483647" ></requestLimits>
      </requestFiltering>
    </security>

二、扩展主机缓存Policy

这是微软预留的接口,作为扩展,让用户自己关闭主机是否缓冲,也就是正常流程中将上传文件的内容存入内存的动作

public class NoBufferPolicySelector : WebHostBufferPolicySelector
{
   public override bool UseBufferedInputStream(object hostContext)
   {
      var context = hostContext as HttpContextBase;

      if (context != null)
      {
          if (context.Request.HttpMethod == HttpMethod.Post.ToString() && context.Request.ContentLength >200000)
              return false;
      }

      return true;
   }

还有个动作就是要去注册它

 1         public static void Register(HttpConfiguration config)
 2         {
 3             // Web API 配置和服务
 4
 5             // Web API 路由
 6             config.MapHttpAttributeRoutes();
 7
 8             config.Routes.MapHttpRoute(
 9                 name: "DefaultApi",
10                 routeTemplate: "api/{controller}/{id}",
11                 defaults: new { id = RouteParameter.Optional }
12             );
13
14
15             GlobalConfiguration.Configuration.Services.Replace(typeof(IHostBufferPolicySelector), new NoBufferPolicySelector());
16
17
18         }

三、想怎么玩儿怎么玩儿

上传的代码,大家都懂的

 [RoutePrefix("test")]
    public class UploadController : ApiController
    {
        [Route("upload")]
        [HttpPost]
        public Task<IEnumerable<FileDesc>> Post()
        {
            var folderName = "uploads";
            var PATH = HttpContext.Current.Server.MapPath("~/" + folderName);
            var rootUrl = Request.RequestUri.AbsoluteUri.Replace(Request.RequestUri.AbsolutePath, String.Empty);
            if (Request.Content.IsMimeMultipartContent())
            {
                var streamProvider = new CustomMultipartFormDataStreamProvider(PATH);
                var task = Request.Content.ReadAsMultipartAsync(streamProvider).ContinueWith<IEnumerable<FileDesc>>(t =>
                {

                    if (t.IsFaulted || t.IsCanceled)
                    {
                        throw new HttpResponseException(HttpStatusCode.InternalServerError);
                    }

                    var fileInfo = streamProvider.FileData.Select(i =>
                    {
                        var info = new FileInfo(i.LocalFileName);
                        return new FileDesc(info.Name, rootUrl + "/" + folderName + "/" + info.Name, info.Length / 1024);
                    });
                    return fileInfo;
                });

                return task;
            }
            else
            {
                throw new HttpResponseException(Request.CreateResponse(HttpStatusCode.NotAcceptable, "This request is not properly formatted"));
            }
        }
    }

    public class CustomMultipartFormDataStreamProvider : MultipartFormDataStreamProvider
    {
        public CustomMultipartFormDataStreamProvider(string path)
            : base(path)
        { }

        public override string GetLocalFileName(System.Net.Http.Headers.HttpContentHeaders headers)
        {
            var name = !string.IsNullOrWhiteSpace(headers.ContentDisposition.FileName) ? headers.ContentDisposition.FileName : "NoName";
            return name.Replace("\"", string.Empty);
        }
    }

MultipartFormDataStreamProvider

还有各种Provider,这样我们就可以有很多种处理方式,去掉WebAPI自带的Buffer,我们自己来处理。

MultipartFormDataRemoteStreamProvider 例如这个Provider,是抽象类,需要自己继承,设想如果我们要把这个上传的文件传到另外的地方去,例如Azure上,我们是不是可以直接架设管道,用流的方式。

下次介绍Provider。

最后还是上图吧,without picture I say ge hair?

准备工作,要上传的文件,才装了系统,就用这个吧

700多MB够了吧,还要怎样?

准备客户端,用网页比较方便,直接看进度

<h2>API Upload</h2>
<form name="apiForm" method="post" enctype="multipart/form-data" action="http://localhost:15068/test/upload">
<div>
<label for="apifiles">Select a File</label>
<input name="apifiles" type="file" />
</div>
<div>
<input type="submit" value="Upload" />
</div>
</form>

那就开始吧

至于内存的占用,既然是流,就不用多说了。不会有很大起伏的,就不贴图了,已经占了很大版面了。

PS:在学习的过程中,还遇到另外一种解决方案,是否还记得ASP.NET中接收上传文件的SaveAS方法,是的,用这个方法的主人也是可以接收文件的,它会干一个有趣的事情,不用内存作为Buffer,而是用硬盘,并且IIS在关闭或者隔一段时间后会干掉这个硬盘Buffer,后续的流程还是一样。对了,这是在IIS上测试的,本地宿主没试过。

时间: 2024-10-16 15:53:01

WebAPI上传大文件的相关文章

Asp.Net上传大文件带进度条swfupload

Asp.Net基于swfupload上传大文件带进度条百分比显示,漂亮大气上档次,大文件无压力,先看效果 一.上传效果图 1.上传前界面:图片不喜欢可以自己换 2.上传中界面:百分比显示 3.上传后返回文件地址,我测试呢所以乱写的 二.核心代码 upload.htm代码 <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml

uploadify上传大文件

引言 之前使用Uploadify做了一个上传图片并预览的功能,今天在项目中,要使用该插件上传大文件.之前弄过上传图片的demo,就使用该demo进行测试.可以查看我的这篇文章: [Asp.net]Uploadify所有配置说明,常见bug问题分析 . 大文件上传 第一步:修改uploadify参数 1 'fileSizeLimit': '0',//单个文件大小,0为无限制,可接受KB,MB,GB等单位的字符串值 2 'fileTypeDesc': '文件',//文件描述Image Files 3

WCF利用Stream上传大文件

WCF利用Stream上传大文件 转自别人的文章,学习这个例子,基本上wcf也算入门了,接口用法.系统配置都有了 本文展示了在asp.net中利用wcf的stream方式传输大文件,解决了大文件上传问题.主要是存档方便以后遇到该问题是来查阅.贴出部分代码,如果有疑惑或需要完整代码的请留言 WebForm1.aspx.cs protected void Button1_Click(object sender, EventArgs e) {             FileData file = n

运用php上传大文件配置方法

网站建设:运用php上传大文件配置方法如下: 翻开php.ini, 1.第一找出 file uploads区域,有影响文件上传的以下几个参数: file_uploads = on ;能否准许经过http上传文件的开关.默许为on即是开 upload_tmp_dir ;文件上传至服务器上存储临时文件的地方,假设没指定就会用系统默许的临时文件夹 upload_max_filesize = 8m ;望文生意,即准许上传文件大小的最大值.默许为2m 2.在resource limits区域,还有参数 ;

IIS上传大文件

IIS7.0上传文件限制的解决方法 在 Windows7(iis7.5).Win2008(iis 7.0)和Win2003(iis 6.0) 中,默认设置是特别严格和安全的,这样可以最大限度地减少因以前太宽松的超时和限制而造成的攻击.指定 ASP 请求的实体主体中允许大小为 200,000 (IIS6为204,800) 个字节,在 iis 6.0 之前的版本中,例如:Windows XP(IIS 5.1),没有限制. 这就造成了文件上传不能超过200k,而事实上是提交数据不能超过200k,你可以

PHP上传遇到的问题-php 上传大文件主要涉及配置upload_max_filesize和post_max_size两个选项

今天在做上传的时候出现一个非常怪的问题,有时候表单提交可以获取到值,有时候就获取不到了,连普通的字段都获取不到了,苦思冥想还没解决,最后问了师傅,师傅看了说挺奇怪的,然后问我upload_max_filesize的值改了吗,我说改了啊,师傅也解决不了了.过了一会师傅问post_max_size改了吗,我说那个和上传没关系吧,师傅没理我,我还是照着自己的想法继续测试,弄了半天还是不行,最后试了师傅提的意见,成功了,原来上传是和post_max_size有关系的. 总结:php.ini配置文件中的默

php 上传大文件主要涉及配置upload_max_filesize和post_max_size两个选项

php 上传大文件主要涉及配置 upload_max_filesize 和post_max_size两个选项 今天在做上传的时候出现一个非常怪的问题,有时候表单提交可以获取到值,有时候就获取不到了,连普通的字段都获取不到了,苦思冥想还没解决,最后问了师傅, 师傅看了说挺奇怪的,然后问我 upload_max_filesize的值改了吗,我说改了啊,师傅也解决不了了.过了一会师傅问 post_max_size改了吗,我说那个和上传没关系吧, 师傅没理我,我还是照着自己的想法继续测试,弄了半天还是不

PHP+IIS上传大文件

最近刚接触IIS服务器,在使用php上传大文件的时候,遇到了一些问题.通过查阅网上资料进行了总结,希望对各位有帮助. 第一步,检查PHP的配置. 打开php.ini配置文件 1.file_uploads 设为On,允许通过HTTP上传文件 2.upload_tmp_dir 文件上传至服务器时用于临时存储的目录,如果没指定,系统会使用默认的临时文件夹(我的机器是/tmp). 3.upload_max_filesize 允许上传文件大小的最大值,默认为2M. 4.post_max_size Php可

上传大文件&amp;验证码

c#如何上传大文件? 想要想上传大文件,必须在web.config文件中进行配置. 在<system.web>节点中添加如下代码即可: <httpRuntime maxRequestLength="2097151"/> 这个代码就是表示设置最大请求值,上传文件也就相当于请求.maxRequestLength单位为KB,最大值为:209715 如果不设置,默认为4096 KB (4 MB). 也就是说上传的文件最大可以上传2G以内的文件. 一般没有配置的话,默认只