首页 > 代码库 > [WebApi] 捣鼓一个资源管理器--多文件上传

[WebApi] 捣鼓一个资源管理器--多文件上传

《打造一个网站或者其他网络应用的文件管理接口(WebApi)第二章“多文件上传”》

========================================================
作者:
qiujuer
博客:blog.csdn.net/qiujuer
网站:www.qiujuer.net
开源库:Genius-Android
转载请注明出处:http://blog.csdn.net/qiujuer/article/details/41675299
========================================================

History

[WebApi] 捣鼓一个资源管理器--文件下载


In This

既然访问文件接口有了,怎么能少的了文件的上传接口呢!

既然是文件上传接口那就肯定要来一个猛一点的接口--多文件上传


CodeTime

改动

进入正题前先来看看本次改动的文件有哪些:



可以看见一共有4个文件进行了改动,其中HomeResourceApi是添加了方法,Model/Resource是新增,View/Upload也是新增。


Model部分

为了返回数据简单方便,所以New 了一个类 Resource.cs

namespace WebResource.Models
{
    public class Resource
    {
        public string Id { get; set; }

        public string Type { get; set; }
    }
}
If Easy?

ResourceApi 部分

然后来看看咱们的ResourceApi类:

namespace WebResource.Controllers
{
    [RoutePrefix("Resource")]
    public class ResourceApiController : ApiController
    {
        private static readonly long MEMORY_SIZE = 64 * 1024 * 1024;
        private static readonly string ROOT_PATH = HttpContext.Current.Server.MapPath("~/App_Data/");

        [HttpGet]
        [Route("{Id}")]
        public async Task<HttpResponseMessage> Get(string Id)
        {
            // 进入时判断当前请求中是否含有 ETag 标识,如果有就返回使用浏览器缓存
            // Return 304
            var tag = Request.Headers.IfNoneMatch.FirstOrDefault();
            if (Request.Headers.IfModifiedSince.HasValue && tag != null && tag.Tag.Length > 0)
                return new HttpResponseMessage(HttpStatusCode.NotModified);

            // 进行模拟 App_Data/Image/{id}.png
            // 打开找到文件
            FileInfo info = new FileInfo(Path.Combine(ROOT_PATH, "Image", Id + ".png"));
            if (!info.Exists)
                return new HttpResponseMessage(HttpStatusCode.BadRequest);

            FileStream file = null;
            try
            {
                // 打开文件
                file = new FileStream(info.FullName, FileMode.Open, FileAccess.Read, FileShare.Read);
                HttpResponseMessage result = new HttpResponseMessage(HttpStatusCode.OK);
                // 在浏览器中显示 inline
                ContentDispositionHeaderValue disposition = new ContentDispositionHeaderValue("inline");
                // 写入文件基本信息
                disposition.FileName = file.Name;
                disposition.Name = file.Name;
                disposition.Size = file.Length;

                // 判断是否大于64Md,如果大于就采用分段流返回,否则直接返回
                if (file.Length < MEMORY_SIZE)
                {
                    //Copy To Memory And Close.
                    byte[] bytes = new byte[file.Length];
                    await file.ReadAsync(bytes, 0, (int)file.Length);
                    file.Close();
                    MemoryStream ms = new MemoryStream(bytes);

                    result.Content = new ByteArrayContent(ms.ToArray());
                }
                else
                {
                    result.Content = new StreamContent(file);
                }

                // 写入文件类型,这里是图片png
                result.Content.Headers.ContentType = new MediaTypeHeaderValue("image/png");
                result.Content.Headers.ContentDisposition = disposition;
                // 设置缓存信息,该部分可以没有,该部分主要是用于与开始部分结合以便浏览器使用304缓存
                // Set Cache
                result.Content.Headers.Expires = new DateTimeOffset(DateTime.Now).AddHours(1);
                // 这里应该写入文件的存储日期
                result.Content.Headers.LastModified = new DateTimeOffset(DateTime.Now);
                result.Headers.CacheControl = new CacheControlHeaderValue() { Public = true, MaxAge = TimeSpan.FromHours(1) };
                // 设置Etag,这里就简单采用 Id
                result.Headers.ETag = new EntityTagHeaderValue(string.Format("\"{0}\"", Id));

                // 返回请求
                return result;
            }
            catch
            {
                if (file != null)
                {
                    file.Close();
                }
            }

            return new HttpResponseMessage(HttpStatusCode.BadRequest);
        }


        [HttpPost]
        [Route("Upload")]
        [ResponseType(typeof(Resource))]
        public async Task<IHttpActionResult> Post()
        {
            List<Resource> resources = new List<Resource>();
            // multipart/form-data
            // 采用MultipartMemoryStreamProvider
            var provider = new MultipartMemoryStreamProvider();

            //读取文件数据
            await Request.Content.ReadAsMultipartAsync(provider);

            foreach (var item in provider.Contents)
            {
                // 判断是否是文件
                if (item.Headers.ContentDisposition.FileName != null)
                {
                    //获取到流
                    var ms = item.ReadAsStreamAsync().Result;
                    //进行流操作
                    using (var br = new BinaryReader(ms))
                    {
                        if (ms.Length <= 0)
                            break;
                        //读取文件内容到内存中
                        var data = http://www.mamicode.com/br.ReadBytes((int)ms.Length);>与上一章比较看来,只是增加了一个方法 Post ,而后将其重定向为Resource/Upload 

其中主要干了些什么我都在方法中注明了;应该是足够简单的。

现在运行一下,看看我们的Api是怎样的:


下面我们来调用它试试。

HomeController部分

修改HomeController 添加一个Upload 方法:

namespace WebResource.Controllers
{
    public class HomeController : Controller
    {
        public ActionResult Index()
        {
            ViewBag.Title = "Home Page";

            return View();
        }

        public ActionResult Upload()
        {
            return View();
        }
    }
}

Upload.cshtml部分
而后在方法上点击右键添加视图,然后进入View/Home/Upload.cshtml 视图中修改为:

@{
    ViewBag.Title = "Upload";
}

<h2>Upload</h2>

<div id="body">
    <h1>多文件上传模式</h1>
    <section class="main-content clear-fix">
        <form name="form1" method="post" enctype="multipart/form-data" action="/Resource/Upload">
            <fieldset>
                <legend>File Upload Example</legend>
                <div>
                    <label for="caption">File1</label>
                    <input name="file1" type="file" />
                </div>
                <div>
                    <label for="image1">File2</label>
                    <input name="file2" type="file" />
                </div>
                <div>
                    <input type="submit" value=http://www.mamicode.com/"Submit" />>在该视图中,我们建立了一个 Form 表单,然后指定为 Post 模式;同时指定

enctype="multipart/form-data" action="/Resource/Upload"


RunTime

写完了代码当然是调试运行喽!

运行 localhost:60586/Home/Upload
这里我们添加文件,还是使用上一章中的两种图片吧:


运行后:


当然,这里是因为我的浏览器是谷歌浏览器,所以返回的是 XML 数据,如果你的事IE浏览器那么应该返回的是Json 文件。

WebApi会根据请求返回不同的数据。


可以看到,现在 App_Data文件夹下,多了两个文件了;不过这两个文件是没有加上文件类型的;你可以手动给他加上个.png 然后打开看看是不是那两张图片。


END

OK,这一章就到此为止了!

资源文件

第一章资源文件(说好了这章中添加)

第二章资源文件

下一章

下一章将会把上传与下载查看两个方法相互结合,搭配起来;同时将会结合数据进行辅助存储文件信息。

同时,会讲如何避免文件重复上传的问题。

========================================================
作者:
qiujuer
博客:blog.csdn.net/qiujuer
网站:www.qiujuer.net
开源库:Genius-Android
转载请注明出处:http://blog.csdn.net/qiujuer/article/details/41675299
========================================================


[WebApi] 捣鼓一个资源管理器--多文件上传