[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个文件进行了改动,其中Home与ResourceApi是添加了方法,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 = br.ReadBytes((int)ms.Length);
                        //Create
                        //当前时间作为ID
                        Resource resource = new Resource() { Id = DateTime.Now.ToString("yyyyMMddHHmmssffff", DateTimeFormatInfo.InvariantInfo) };

                        //Info
                        FileInfo info = new FileInfo(item.Headers.ContentDisposition.FileName.Replace("\"", ""));
                        //文件类型
                        resource.Type = info.Extension.Substring(1).ToLower();

                        //Write
                        try
                        {
                            //文件存储地址
                            string dirPath = Path.Combine(ROOT_PATH);
                            if (!Directory.Exists(dirPath))
                            {
                                Directory.CreateDirectory(dirPath);
                            }

                            File.WriteAllBytes(Path.Combine(dirPath, resource.Id), data);
                            resources.Add(resource);
                        }
                        catch { }
                    }
                }
            }

            //返回
            if (resources.Count == 0)
                return BadRequest();
            else if (resources.Count == 1)
                return Ok(resources.FirstOrDefault());
            else
                return Ok(resources);
        }
    }
}

与上一章比较看来,只是增加了一个方法 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="Submit" />
                </div>
            </fieldset>
        </form>
    </section>
</div>

在该视图中,我们建立了一个 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

========================================================

时间: 2024-09-30 01:53:11

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

[WebApi] 捣鼓一个资源管理器--多文件上传+数据库辅助

<打造一个网站或者其他网络应用的文件管理接口(WebApi)第三章"多文件上传+数据库辅助存储"> ======================================================== 作者:qiujuer 博客:blog.csdn.net/qiujuer 网站:www.qiujuer.net 开源库:Genius-Android 转载请注明出处: http://blog.csdn.net/qiujuer/article/details/4172

[WebApi] 捣鼓一个资源管理器--数据库辅助服务器文件访问

<打造一个网站或者其他网络应用的文件管理接口(WebApi)第四章"数据库辅助服务器文件访问"> ======================================================== 作者:qiujuer 博客:blog.csdn.net/qiujuer 网站:www.qiujuer.net 开源库:Genius-Android 转载请注明出处: http://blog.csdn.net/qiujuer/article/details/41721

[WebApi] 捣鼓一个资源管理器--服务器端分割压缩图片

<打造一个网站或者其他网络应用的文件管理接口(WebApi)第五章"服务器端分割压缩图片"> ======================================================== 作者:qiujuer 博客:blog.csdn.net/qiujuer 网站:www.qiujuer.net 开源库:Genius-Android 转载请注明出处:http://blog.csdn.net/qiujuer/article/details/41826865

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

<打造一个网站或者其他网络应用的文件管理接口(WebApi)第一章--之-- "文件下载" > ======================================================== 作者:qiujuer 博客:blog.csdn.net/qiujuer 网站:www.qiujuer.net 开源库:Genius-Android 转载请注明出处:blog.csdn.net/qiujuer/article/details/41621781 =====

深入分析JavaWeb 47 -- Struts2拦截器与文件上传下载

一.struts2中的拦截器(框架功能核心) 1.过滤器VS拦截器 过滤器VS拦截器功能是一回事.过滤器是Servlet规范中的技术,可以对请求和响应进行过滤. 拦截器是Struts2框架中的技术,实现AOP(面向切面)的编程思想,是可插拔的, 可以对访问某个 Action 方法之前或之后实施拦截. 拦截器栈(Interceptor Stack): 将拦截器按一定的顺序联结成一条链. 在访问被拦截的方法时, Struts2拦截器链中的拦截器就会按其之前定义的顺序被依次调用 Struts2执行原理

深入分析JavaWeb Item47 -- Struts2拦截器与文件上传下载

一.struts2中的拦截器(框架功能核心) 1.过滤器VS拦截器 过滤器VS拦截器功能是一回事. 过滤器是Servlet规范中的技术,能够对请求和响应进行过滤. 拦截器是Struts2框架中的技术.实现AOP(面向切面)的编程思想.是可插拔的, 能够对訪问某个 Action 方法之前或之后实施拦截. 拦截器栈(Interceptor Stack): 将拦截器按一定的顺序联结成一条链. 在訪问被拦截的方法时, Struts2拦截器链中的拦截器就会按其之前定义的顺序被依次调用 Struts2运行原

拦截器与文件上传

拦截器与文件上传 三种上传方案: 1.上传到tomcat服务器(不能及时刷新) 2.上传到指定文件目录,添加服务器与真实目录的映射关系,从而解耦上传文件与tomcat的关系 文件服务器(目前公司用的最常用的方法) 3.在数据库表中建立二进制字段,将图片存储到数据库(处理上百万的数据不方便) 完成图片上传: 写两个方法:1.上传图片2.跳转文件上传页面. 1 private File file; 2 private String fileContentType; 3 private String

WebApi发送HTML表单数据:文件上传与多部分MIME

5.3 Sending HTML Form Data5.3 发送HTML表单数据(2) 本文引自:http://www.cnblogs.com/r01cn/archive/2012/12/20/2826230.html By Mike Wasson|June 21, 2012作者:Mike Wasson | 日期:2012-6-21 Part 2: File Upload and Multipart MIME第2部分:文件上传与多部分MIME This tutorial shows how to

(转)WebApi发送HTML表单数据:文件上传与多部分MIME

5.3 Sending HTML Form Data5.3 发送HTML表单数据(2) 本文引自:http://www.cnblogs.com/r01cn/archive/2012/12/20/2826230.html By Mike Wasson|June 21, 2012作者:Mike Wasson | 日期:2012-6-21 Part 2: File Upload and Multipart MIME第2部分:文件上传与多部分MIME This tutorial shows how to