Web实战之文件上传

贾蔷
• 阅读 2281

前言

由于讨厌各种上传插件和UI绑定,同样是为了自己练练手,我写了一个十分小巧的jQuery上传插件——JFile

文档链接

提供的功能

  • 多文件上传
  • 中途取消
  • 文件大小、类型限制设定
  • 能取到进度(进度条UI可以自己定制哦)
  • 可选的上传图片预览
  • 类似于jQuery AJAX的调用风格

依赖

  • 上传依赖于FormData和Level2的XHttpRequest(一般都支持)
  • 预览依赖于HTML5的File API
  • jQuery

使用

var jq=$('#input').upload(url,{
    preview:true,
    limits:{
        fieldSize:40,
        ...
    },
    ...
}).done(function(data,status,xhr){..})
  .fail(function(xhr,status,err){..})
  .always(function(xhr,status,err){..})
  .progress(function(percentage){..});
jq.abort();

源代码

/**
 * Created by suemi on 14-12-8.
 */
(function($){
    $.fn.upload=function(url,settings){

        var option={
            method:'POST',
            action:url,
            dataType:'json',
            limits:{},
            preview:null
        };
        if(!settings) var settings={};
        $.extend(option,settings);
        var getXhr = function(){
            var xhr;
            return function(){
                if (xhr) return xhr;
                if (typeof XMLHttpRequest !== 'undefined') {
                    xhr = new XMLHttpRequest();
                } else {
                    var v = [
                        "Microsoft.XmlHttp",
                        "MSXML2.XmlHttp.5.0",
                        "MSXML2.XmlHttp.4.0",
                        "MSXML2.XmlHttp.3.0",
                        "MSXML2.XmlHttp.2.0"
                    ];
                    for (var i=0; i < v.length; i++){
                        try {
                            xhr = new ActiveXObject(v[i]);
                            break;
                        } catch (e){}
                    }
                }
                return xhr;
            }
        }();
        function checkExtension(dst,src){
            var tmp=dst.split('/');
            if(tmp[0]=='image'){
                if($.inArray('image/*',src)==-1){
                    if($.inArray(tmp[1],src)==-1) return false;
                    else return true;
                }
                else return true;
            }
            else{
                if($.inArray(tmp[1],src)==-1) return false;
                else return true;
            }
        }




        var fileList=[];
        $(this).each(function(){
            for(var i=0;i<this.files.length;i++){
                fileList.push(this.files[i]);
            }
        });
        return $.Deferred(function(){
            var xhr=getXhr();
            var defer=this;
            this.abort=function(){
              if(xhr) xhr.abort();
              return defer;
            };
            this.preview=function(tmp){
                for(var i in fileList){
                    var file=fileList[i];
                    if(file.type.split('/')[0]=='image'){
                        if(!window.FileReader){
                            alert('Too old browser, you need a modern one!');
                            return defer;
                        }
                        var reader=new FileReader();
                        reader.name=file.name;
                        reader.onloadend=function(evt){
                            console.log(this.num);
                            if(reader.error) tmp.append($('<p>'+this.name+' fails to be loaded</p>'));

                            else tmp.append($('<img>',{'src':evt.target.result,'alt':this.name}));
                        };
                        reader.readAsDataURL(file);
                    }
                    else continue;
                }
                return defer;
            };
            if(window.FormData) var form=new FormData();
            else{
                // alert('Too old for your browser, get a modern one!');
                this.reject(xhr,null,new Error('Too Old Browser'));
                return this;
            }
            if(!xhr){
                this.reject(xhr,null,new Error('Too Old Browser'));
                return this;
            }
            if(!option.action){
                this.reject(xhr,null,new Error('URL Needed'));
                return this;
            }
            xhr.open(option.method,option.action);
            xhr.upload.addEventListener('progress',function(evt){
                if(evt.lengthComputable){
                    var complete=evt.loaded/evt.total | 0;
                }
                defer.notify(complete);
            });

            xhr.onreadystatechange=function(){
                if(this.readyState!==4) return;
                if(this.status==200){
                    var data;
                    switch(option.dataType){
                        case 'text':
                            data=this.responseText;
                            break;
                        case 'html':
                            data= $.parseHTML(this.responseText);
                            break;
                        case 'xml':
                            data= $.parseXML(this.responseXML);
                            break;
                        case 'json':
                            data= $.parseJSON(this.responseText);
                            break;
                        default :break;
                    }
                    defer.resolve(data,this.status,this);
                }
                else{
                    defer.reject(this,this.status,this.responseText);
                }
            };
            if(fileList.length==0){
                //defer.reject(xhr,xhr.status,new Error('No File Select'));
                return defer;
            }
            if(option.limits.fieldSize&&option.limits.fieldSize<fileList.length){
                var err=new Error('Too Many Files');
                defer.reject(xhr,xhr.status,err);
                return defer;
            }
            for(var i in fileList){
                var file=fileList[i];
                if(option.limits.validExtension&&!checkExtension(file.type,option.limits.validExtension)){
                    var err=new Error('File Type Error');
                    err.filename=file.name;
                    defer.reject(xhr,xhr.status,err);
                    continue;
                }
                if(option.limits.fileSize&&option.limits.fileSize<file.size){
                    var err=new Error('Too Large Size');
                    defer.reject(xhr,xhr.status,err);
                    return defer;
                }

                if(option.start) option.start(file);
                form.append(i,file,file.name);
                if(option.maxSize) option.maxSize-=file.size;
            }
            if(option.preview) this.preview(option.preview);
            xhr.send(form);
            return defer;
        });
    };
})(jQuery);
点赞
收藏
评论区
推荐文章
李志宽 李志宽
2年前
【小白必学】文件上传的漏洞介绍及常见防御方法
01文件上传漏洞原理在文件上传的功能处,若服务端脚本语言未对上传的文件进行严格验证和过滤,导致恶意用户上传恶意的脚本文件时,就有可能获取执行服务端命令的能力,这就是文件上传漏洞。02文件上传漏洞触发点相册、头像上传、视频、照片分享、附件上传(论坛发帖、邮箱
happlyfox happlyfox
4年前
.net web core 如何编码实现文件上传功能
关于我前言在进行Web前后端分析开始时,我们经常会碰到文件上传的需求。上传用户头像,上传认证材料、审核材料等,这些都可以归类为文件上传功能。今天主要把自己在开发过程中的心得进行一个整理,供大家学习。开启静态文件中间件默认情况下,静态文件(如HTML、CSS、图像和JavaScript)是ASP.NETCore应用直接提供给客户端的资产。开启静态
Wesley13 Wesley13
3年前
uploadify,swfupload等flash上传session丢失问题,无法接收到表单
大部分网站的上传文件功能都要求用户登陆,而判断用户登陆状态一般是用session标记。现在流行flash上传插件,优点是显示每个文件上传的进度条,可中途取消,暂停等等。然而用flash上传插件有个问题,那就是上传的时候flash会丢失session,服务端会以为是游客而拒绝处理。解决办法是有的,下面慢慢道来:我们知道,php里启用sessio
Easter79 Easter79
3年前
SpringBoot2.0 基础案例(14):基于Yml配置方式,实现文件上传逻辑
本文源码GitHub地址:知了一笑https://github.com/cicadasmile/springbootbase一、文件上传文件上传是项目开发中一个很常用的功能,常见的如头像上传,各类文档数据上传等。SpringBoot使用MultiPartFile接收来自表单的file文件,然后执
Stella981 Stella981
3年前
SpringBoot2.0 基础案例(14):基于Yml配置方式,实现文件上传逻辑
本文源码GitHub地址:知了一笑https://github.com/cicadasmile/springbootbase一、文件上传文件上传是项目开发中一个很常用的功能,常见的如头像上传,各类文档数据上传等。SpringBoot使用MultiPartFile接收来自表单的file文件,然后执
Stella981 Stella981
3年前
ShardingSphere学习:06
实战代码后续上传(https://gitee.com/"实战代码后续上传")代码同上篇一致,只是配置文件不同。我们主要看一下,配置文件。分表配置由于的单库分表,所以只配置一个数据源就可以了配置数据源spring.shardingsphere.datasource.namestest0tes
Stella981 Stella981
3年前
Cordova
增加相机插件      cordovapluginaddcordovaplugincamera(如果删除add改为remove )增加文件上传插件   cordovapluginaddcordovapluginfiletransfer<!DOCTYPEhtml<html
可莉 可莉
3年前
20+ 个很棒的 jQuery 文件上传插件或教程
文件上传是网站很常见的功能之一,通过使用jQuery可以让上传过程更加人性化,更好的用户体验。本文介绍20个jQuery的文件上传插件,其中有一些是教程。1\.Plupload(http://www.oschina.net/p/plupload"Plupload")Plupload是一个Web浏览器上的界面友好的文件上传模块,可
Wesley13 Wesley13
3年前
PHP代码审计笔记
0x01最简单的文件上传未进行文件类型和格式做合法性校验,任意文件上传漏洞代码示例:新建一个提供上传文件的 upload.html<html创建上传脚本  upload\_file.php<?php漏洞利用:可上传任意文件!(https://oscimg.oschina.net/oscnet/a
Wesley13 Wesley13
3年前
Java多线程导致的的一个事物性问题
业务场景我们现在有一个类似于文件上传的功能,各个子站点接受业务,业务上传文件,各个子站点的文件需要提交到总站点保存,文件是按批次提交到总站点的,也就是说,一个批次下面约有几百个文件。      考虑到白天提交这么多文件会影响到子站点其他系统带宽,我们将分站点的文件提交到总站点这个操作过程独立出来,放到晚上来做,具体时间是晚上7:00到早上7:00。
前端文件上传的几种交互造轮子 | 京东云技术团队
前端文件上传本来是一个常规交互操作,没什么特殊性可言,但是最近在做文件上传,需要实现截图粘贴上传,去找了下有没有什么好用的组件,网上提供的方法有,但是没找完整的组件来支持cv上传,经过了解发现可以用剪贴板功能让自己的cv实现文件上传,于是自己就整合了目前几种文件上传的交互方式,码了一个支持cv的vue3文件上传组件(造个轮子)。
贾蔷
贾蔷
Lv1
墙里秋千墙外道。墙外行人,墙里佳人笑。笑渐不闻声渐悄,多情却被无情恼。
文章
6
粉丝
0
获赞
0