前端通信:ajax设计方案(三)--- 集成ajax上传技术

931 阅读20分钟
原文链接: www.cnblogs.com
前端通信:ajax设计方案(三)--- 集成ajax上传技术 - 仲强 - 博客园

半个诗人

前端通信:ajax设计方案(三)--- 集成ajax上传技术

在此之前让我感慨一下现在的前端开发的氛围。我遇到好多人,给我的观念都是,这个东西这个框架有了,那个东西那个框架做了,前端嘛,学几个框架,这个拼凑一下那个拼凑一下就好了。其实我想问,东西都框架做了,那你会什么?会吹牛逼?会撕逼?

我在简历上写专注原声js,曾经被几个人笑过。我一直搞不懂,框架会过时,基础永远不会过时。离了框架,我可以活,我也会自己写框架,我也在前端模块化的路上自己摸索着,我也在前端如何更简单,更快速开发的路上摸索着。难道有框架做了,我就坐吃山空等死吗?

前端太浮躁,我也无所谓成为别人眼中的奇葩。我去做前端,我去做分离,我去写后端,每天总会花一些时间在我喜欢的东西上。我知道我很傻逼,有的玩不玩,还去看代码。那我没办法,我做奇葩很长时间了,因为我有自己的梦想,我有自己的追求。

请不要在我面前说,你这个东西人家都做了。做了怎么了?人家做了,是你的吗?人家做的时候前面不也有千千万万个死的淘汰的东西吗?难道就因为人家做了我就不干了?请不要目光短浅。鄙人也不隐藏我为什么做前端,现在列举我做前端的理由,你和我一样吗?

    1. 对接UI,需要涉猎页面设计,布局和美化。学会去审美,学会站在用户角度去看自己的东西。当然我不否认,UI妹子也多
    2. 对接js,对前端核心技术的考验。对于页面功能实现、新旧技术兼容和舍弃、如何写出高效可维护代码的思考
    3. 对接架构,前端性能优化,程序健壮性和容错性,各种框架资源整合使用,从DNS解析到页面渲染到你眼前的各种过程的跨域学习
    4. 对接后端,新老技术的变化,永远不是前端,后端一样需要去配合着去改变。所以懂后端,设计后端,写后端,永远都需要你去懂得
    5. 对接服务器,反向代理,负载均衡,请求分发容错整合等等难道不需要懂吗?难道只敲个js就够了?
    6. 前端的未来,任何项目的使用和展示,都离不开前端。因为前端第一接触是用户,是发展的最核心的资源。前端是站在整个战线第一线的。
    7. 最重要的。前端刚起步,不是很成熟,可以接触所有的原声和底层,优化,开发,调试,甚至改变世界,都是有可能的。后端太成熟,接触太多都是框架,突出重围,需要更深的积累和叛逆。
    8. 最重要的,前端相对来说,薪水前期还是很好的。毕竟还要生活,诗和远方都不及面包重要,活着,一切才有可能。

 

  之前发布了ajax的通用解决方案,核心的ajax发布请求,以及集成了轮询。这次去外国网站逛逛,然后发现了ajax level2的上传文件,所以就有了把ajax的上传文件集成进去的想法,ajax方案的level2的改进就不介绍了,不清楚的可到前几篇博客去看看。我们直接切入主题。

 

概念介绍:

  1. js的FormData:js中在新的版本中已经支持了FormData对象,可以初始化一个空的form,或者初始化已经存在的form,浏览器测试代码。

  

 

  2. 浏览器的支持:浏览器已支持input=file的时候查看文件,具体包括文件的大小(size)和类型(type),浏览器测试如下

 

  3. xmlhttprequest:支持发送(send方法)新的数据类型,包括DOMStringDocumentFormDataBlobFileArrayBuffer。具体参见ajax设计方案的规范

 

工具准备:

  1. 前端代码

  2. nginx服务器(分离)

  3. IIS服务器(部署后台)

  4. 后台代码(webAPI)

 

什么不多说,先贴代码:

前端代码:

?
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52     /*     *   ajax上传文件     *       url                 文件上传地址     *       fileSelector        input=file 选择器(支持多文件上传,只要后台接口支持)     *       size                文件限制大小     *       fileType            文件限制类型 mime类型     *       success             上传成功处理     *       error               上传失败处理     *       timeout             超时处理     *     *   return: status:  0      请选择文件     *                    1      超出文件限制大小     *                    2      非允许文件格式     * */     upload:function(url,fileSelector,size,fileType,success,error,timeout){         var formdata = new FormData(),fileNode = document.querySelector(fileSelector),fileCount = fileNode.files.length,data={},result ={};         //以下为上传文件限制检查         if ( fileCount > 0 ){             tool.each(Array.prototype.slice.call(fileNode.files),function (value){                 //检查文件大小                 if (value.size > size){                     result["status" ] = 1;                     result["errMsg" ] = "超出文件限制大小";                 }else{                     //检查文件格式.因为支持formdata,自然支持数组的indexof(h5)                     if (fileType.indexOf(value.type)=== -1 ){                         result[ "status"] = 2;                         result[ "errMsg"] = "非允许文件格式";                     }else {                         formdata.append(value.name,value);                     };                 };             });         }else{             result["status"] = 0;             result["errMsg" ] = "请选择文件";         };           if (result.status !== undefined)  return result;   //如果有错误信息直接抛出去,结束运行           var ajaxParam ={             type:"post" ,             url:url,             data:formdata,             isFormData:true ,             success:success,             error:error,             timeout:timeout         };         ajax.common(ajaxParam);     }, };

后端接口代码(C#的webAPI),代码比较简陋,能完成测试就好

    [Route("upload3")]
        public async Task<HttpResponseMessage> PostFormData()
        {
            // Check if the request contains multipart/form-data.
            // 检查该请求是否含有multipart/form-data
            if (!Request.Content.IsMimeMultipartContent())
            {
                throw new HttpResponseException(HttpStatusCode.UnsupportedMediaType);
            }

            string root = HttpContext.Current.Server.MapPath("~/uploadfile");
            var provider = new ReNameMultipartFormDataStreamProvider(root);

            try
            {
                // Read the form data.
                // 读取表单数据
                var task = await Request.Content.ReadAsMultipartAsync(provider).ContinueWith(t =>
                {
                    if (t.IsFaulted || t.IsCanceled)
                    {
                        Request.CreateErrorResponse(HttpStatusCode.InternalServerError, t.Exception);
                    }
                    string fileName = string.Empty;
                    foreach (MultipartFileData file in provider.FileData)
                    {
                        fileName = file.LocalFileName;
                    }
                    //返回上传后的文件全路径
                    return new HttpResponseMessage() { Content = new StringContent(fileName) };
                });
                return Request.CreateResponse(HttpStatusCode.OK);
            }
            catch (System.Exception e)
            {
                return Request.CreateErrorResponse(HttpStatusCode.InternalServerError, e);
            }
        }

        ///
        /// 重命名上传的文件
        ///
        public class ReNameMultipartFormDataStreamProvider : MultipartFormDataStreamProvider
        {
            public ReNameMultipartFormDataStreamProvider(string root)
                : base(root)
            { }
            public override string GetLocalFileName(System.Net.Http.Headers.HttpContentHeaders headers)
            {
                //截取文件扩展名
                string exp = Path.GetExtension(headers.ContentDisposition.FileName.TrimStart('"').TrimEnd('"'));
                string name = base.GetLocalFileName(headers);
                return name + exp;
            }
        }

 

浏览器测试结果(几乎所有主流浏览器都支持,除了IE10以下)

测试代码如下:

?
1 2 3 4 5 6 7 8 9 var temp = ajax.upload("/api/ajaxUpload/upload3/" , "#file1", 1024 * 1024 * 1, ["image/png" ,"image/bmp"], function (data) {     if (data == "true" ) {         alert("上传成功!" );     }     if (data == "error" ) {         alert(data);     } }); console.log(temp);

格式限制测试结果如下

1. 选取超过限制大小的文件

2. 选取非允许格式的文件

3. 未选择上传文件

 

 

文件上传成功测试

IE10、11

safari

火狐

谷歌

opera

edge

360浏览器

 

 

 下面扯一下遇到的问题

  问题一  IE8-9兼容问题

在兼容性网站(http://caniuse.com/)查询兼容性,ajax leve2支持IE10+版本,所以如果在IE8-9上使用纯前端代码进行上传文件的话,只有传统的form标签

html代码如下:

?
1 2 3 4 5 6 <form id="formUpload" action="/api/ajaxUpload/upload2/" method="post" enctype="multipart/form-data" target="framFile">     <input name="isIE8" type="text" value="1" readonly style= "display: none"/>     <input id="iefile" type="file" name="age"/>     <input type="submit" value="submit"> </form> <iframe id="framFile" name="framFile" src="postMsg.html"></iframe>

缺点:

1. 每次form提交的时候都会刷新页面,如果想做异步无刷新,用iframe做提交页面

2. IE8-9无法在前端对文件进行大小和类型检查(使用IE的文件组件不安全,因为可以修改系统上所有文件,容易被攻击,而且浏览器都是默认关闭的)

3. 上传文件接口不能有返回值,否则在IE8下会将接口返回值作为文件下载下来,且无法取得返回值(用了N种方法),但是在其他浏览器中ajax的成功事件会去做判断,测试图片如下 

一些建议:如果真的要做IE8-9,现在普遍的方案是将flash插件和ajax Level2的上传进行组合,支持H5的用ajax上传,不支持初始化flash上传插件。

PS:对于那些偏执的,一定要在IE8-9用纯前端代码支持上传的,还有一种折中的方案,和这种思想类似,但是我做了优化,思路如下:

需要2个接口:上传文件接口,IE8-9下上传结果查询接口

a. 首先使用form的无刷新上传(ifarme)

b. 后台接收到formdata数据判断是否是IE8-9的上传,是的话将该用户上传文件是否成功的状态改变(不管存库或者其他地方),否则直接返回上传结果

c. 前端在form的submit之后,发起得到一次结果的轮询,如果得到结果,则直接结束轮询,结果查询接口也将该用户的上传文件状态清空

 

  问题二  一般ajax请求和formdata请求,后台取值问题。

传统http请求,可以直接在接口参数中取得数据,但是使用formdata进行ajax请求的话,后台接口需要从formdata对象中取数据,包括文件啥的。因为这个我写后台接口的时候就懵逼了好长一段时间,然后左查查右查查,终于明白取值方式也不一样了。

 

  问题三  关于formdata上传文件,具体能上传多大文件的限制问题

上传文件的限制取决于web容器可接受上传文件的大小,tomcat、IIS等web容器都有自己的设置方法,具体可搜索引擎,你懂的

 

  问题四  前端对大文件的传输解决方案,具体可参考该文章

在新的版本中,就是支持H5的版本中,有了File对象可以切割文件,因为在取到input=file中取到的文件都是File类型,File对象有个方法slice,可以切割文件,然后分配一个xhr上传。主要是后台的切割文件重组问题不是很清楚,所以我暂时也没有集成大文件上传方法。

 

 代码已集成github:github.com/GerryIsWarr…     点颗星星是我最大的鼓励,有什么问题可以博客、邮箱、github上留言

 

这一次上传版本,代码做过变动,变动如下:

  1. 增加FormData数据传输方法(postFormData),如果判断到浏览器不支持FormData,则自动使用默认原始的数据传输
  2. 新增各种类型判断方法,判断类型
  3. 更新each方法,判断如果传入参数obj为数组而且浏览器支持h5的新特性直接用数组的forEach方法

 

我的全栈书签,这次更新整理了国内顶级互联网和著名的一些互联网公司的招聘网站,希望大家找到好工作,^_^

github地址:github.com/GerryIsWarr…

 

posted on 2017-01-11 18:14 仲强 阅读(717) 评论(11) 编辑 收藏

评论

#1楼 2017-01-11 20:50 batsing  

Jquery. form. js 早已做好了这一切 支持(0)反对(0) http://pic.cnblogs.com/face/681503/20141018114352.png   

#2楼[楼主] 2017-01-11 21:26 仲强  

@ batsing
技术理念不一样,Jquery. form是做了,但那是它的不是你的,离开这个东西,你还能做吗? 支持(0)反对(0) http://pic.cnblogs.com/face/801930/20161012082514.png   

#3楼[楼主] 2017-01-11 21:28 仲强  

@ batsing
现在前端普遍浮躁,那我问你,之前出了好多模块化的东西,那以后就没有再出的必要了吗?知其然,知其所以然,才是真谛。 支持(0)反对(0) http://pic.cnblogs.com/face/801930/20161012082514.png   

#4楼 2017-01-12 08:26 阿伯有蚕豆  

期待把后端也换成js(node做server),然后做成一个功能块github发布出来,会贡献很大。。。 支持(0)反对(0) http://pic.cnblogs.com/face/644947/20150529235845.png   

#5楼[楼主] 2017-01-12 09:16 仲强  

@ 阿伯有蚕豆
现在node做服务器大多是做入口的第一层,因为完全异步的I/O模型,异步I/O模型极大提高web服务的并发性。而且node相对很年轻,不是很成熟,所以暂时不会替换后端的,以后我也不知道。我感觉现在学很多东西,包括一些框架啊,都是作者的一种编程思路的展示,会用当然很重要,但是学一些精华和思想是很重要的。 支持(0) 反对(0) http://pic.cnblogs.com/face/801930/20161012082514.png   

#6楼 2017-01-12 14:23 batsing  

@ 仲强
这无所谓离开离不开。
没遇到那个jquery.form.js 插件前,我也是用自己写的,但是各种不成熟,来回折腾。说得难听点是 正事不干,瞎搞。
有这时间,还不如把那些用得不顺手的东西改造封装一下,弄成好用的。 支持(0) 反对(0) http://pic.cnblogs.com/face/681503/20141018114352.png   

#7楼 2017-01-12 15:59 求学求教求讲解  

博主你也不能一票否决别人,有的人做前端只是为了生活应付工作,有的人是热爱前端并且以学习新知识为乐趣的,人生短短几十年,何必去在意别人怎么做,专注自己所做的事才是真正的热爱这个职业。 支持(0)反对(0)   

#8楼 2017-01-12 17:01 小不了  

哟,仲强兄终于更新了!求转载啊求转载!

我记得一个大牛也说过,现在的开发啊,太依赖框架了,知其然不知其所以然。很多都不懂。。。 支持(0)反对(0)   

#9楼[楼主] 2017-01-13 08:36 仲强  

@ batsing
嗯嗯 其实我的思维不是不用,因为企业快速开发的时候还是要用的。只是我学原声,借鉴他们的思想,然后自己去学习这方面的知识,自己也尝试写,因为这样锻炼思维的全面的性和创造性很有帮助的。主要我也在前端的组件化和容器化的路上摸索着,写着一些框架,所以借鉴这方面的思维,对我的框架和思维有很大的帮助。只是现在前端很浮躁,没有多少人能静下心来去学习原声的东西,所以脱离了框架很多人都很茫然 支持(0)反对(0) http://pic.cnblogs.com/face/801930/20161012082514.png   

#10楼[楼主] 2017-01-13 08:39 仲强  

@ 求学求教求讲解
嗯嗯 是的 其实我也不强求别人,只是有时候,我研究的一些东西,总会有一些人说啥框架都有了,没必要的感觉。哎。毕竟一个人在技术上摸索还是需要很大毅力和鼓励的。我的目的只是让人知其然知其所以然,不至于以后离开了框架很茫然 支持(0) 反对(0) http://pic.cnblogs.com/face/801930/20161012082514.png   

#11楼[楼主]3602715 2017/1/13 8:44:14 2017-01-13 08:44 仲强  

@ 小不了
嗯嗯 其实也没什么,每个人追求的不一样,我只是尽力在我的路上走着,奔着自己的追求去 支持(0)反对(0) http://pic.cnblogs.com/face/801930/20161012082514.png    刷新评论 刷新页面返回顶部 注册用户登录后才能发表评论,请 登录注册访问网站首页。 【推荐】超50万VC++源码: 大型工控、组态\仿真、建模CAD源码2018!
【腾讯云】小程序普惠节精美模板1元起
h3bpm 活动 最新IT新闻:
· 乐视网复牌第二日再跌停 逾800万手卖单排队出逃
· 知名80后创业者茅侃侃离世 家中开煤气自杀
· 支付宝今年香港上市?马云终于发话了!
· 马云达沃斯论坛谈全球贸易:贸易不是武器,而是解决方案
· 两家机构数据显示:小米超三星 成印度手机老大
» 更多新闻... 阿里云C2-1208 最新知识库文章:
· 领域驱动设计在互联网业务开发中的实践
· 步入云计算
· 以操作系统的角度述说线程与进程
· 软件测试转型之路
· 门内门外看招聘
» 更多知识库文章...

导航

公告

昵称:仲强
园龄:2年5个月
粉丝:73
关注: 0 +加关注
< 2018年1月 >
31 1 2 3 4 5 6
7 8 9 10 11 12 13
14 15 16 17 18 19 20
21 22 23 24 25 26 27
28 29 30 31 1 2 3
4 5 6 7 8 9 10

统计

  • 随笔 - 58
  • 文章 - 0
  • 评论 - 209
  • 引用 - 0

搜索

 

常用链接

我的标签

随笔分类

随笔档案

积分与排名

  • 积分 - 32332
  • 排名 - 11378

最新评论

阅读排行榜

评论排行榜

推荐排行榜

Powered by:
博客园
Copyright © 仲强