上传笔记【一】webUploader 多文件上传并保存数据库

项目:status2 spring hibernate

最近写了个模块,人员档案库,由于客户要求要实现多文件上传,所以苦逼的又要学习新的知识了,多文件上传已经实现了,所以在这里做个笔记。

1,首先到官网下载js,css,引入项目


<link rel="stylesheet" type="text/css" href="/js/webuploader/css/webuploader.css">
<script type="text/javascript" src="/js/webuploader/js/jquery-1.9.1.min.js"></script>
<script type="text/javascript" src="/js/webuploader/js/webuploader.min.js"></script>

jsp页面:

<script type="text/javascript" src="${pageContext.request.contextPath}/ctcst/archives/upload.js"></script>
<div id="wrapper">
    <div id="container">
        <!--头部,相册选择和格式选择-->
        <div id="uploader">
            <div class="queueList">
                <div id="dndArea" class="placeholder">
                    <div id="filePicker"></div>
                    <p>或将文件拖到这里,单个文件大小不超过2M,单次上传文件总大小不超过20M</p>
                </div>
            </div>
            <div class="statusBar" style="display:none;">
                <div class="progress">
                    <span class="text">0%</span>
                    <span class="percentage"></span>
                </div>
                <div class="info"></div>
                <div class="btns">
                    <div id="filePicker2"></div><div class="uploadBtn">开始上传</div>
                </div>
            </div>
        </div>
    </div>
</div>

下面是js:

(function( $ ){
    // 当domReady的时候开始初始化
    $(function() {
        var $wrap = $('#uploader'),
            // 图片容器
            $queue = $( '<ul class="filelist"></ul>' )
                .appendTo( $wrap.find( '.queueList' ) ),
            // 状态栏,包括进度和控制按钮
            $statusBar = $wrap.find( '.statusBar' ),
            // 文件总体选择信息。
            $info = $statusBar.find( '.info' ),
            // 上传按钮
            $upload = $wrap.find( '.uploadBtn' ),
            // 没选择文件之前的内容。
            $placeHolder = $wrap.find( '.placeholder' ),
            $progress = $statusBar.find( '.progress' ).hide(),
            // 添加的文件数量
            fileCount = 0,
            // 添加的文件总大小
            fileSize = 0,
            // 所有文件的进度信息,key为file id
            percentages = {},
                   
        // 实例化
        uploader = WebUploader.create({
            pick: {
                id: '#filePicker',
                label: '点击选择文件',
                name:"multiFile"
            },
            formData: {
               //这里可以向后台传自定义的参数比如 key:value
            },
            dnd: '#dndArea',
            paste: '#uploader',
            swf: '../../js/webuploader/Uploader.swf',//引用Uploader.swf,去官网下载
            fileVal:'multiFile',
            chunked: false, // 是否分片上传 
            chunkSize: 512 * 1024,
            server:  'http://localhost:8080/ctcst/archives_uploadInformation.action', //提交到服务器
            //规定文件上传的格式
             accept: {
                 title: 'file',
                 extensions: 'gif,jpg,jpeg,bmp,png',
                 mimeTypes: 'image/*'
             },
            // 禁掉全局的拖拽功能。这样不会出现图片拖进页面的时候,把图片打开。
            disableGlobalDnd: true,
            fileNumLimit: 10,
            fileSizeLimit: 20 * 1024 * 1024,    // 20 M
            fileSingleSizeLimit: 2 * 1024 * 1024    // 2 M
        });
        // 拖拽时不接受 js, txt 文件。
        uploader.on( 'dndAccept', function( items ) {
            var denied = false,
                len = items.length,
                i = 0,
                // 修改js类型
                unAllowed = 'text/plain;application/javascript ';
            for ( ; i < len; i++ ) {
                // 如果在列表里面
                if ( ~unAllowed.indexOf( items[ i ].type ) ) {
                    denied = true;
                    break;
                }
            }
            return !denied;
        });
        // 添加“添加文件”的按钮,
        uploader.addButton({
            id: '#filePicker2',
            label: '继续添加'
        });
 
        uploader.on('ready', function() {
            window.uploader = uploader;
        });
 
        // 上传失败触发
        uploader.on('uploadError', function (file, reason) {
            console.log(file);
            console.log(reason);
           console.log('上传失败' + reason);
        });
 
        //成功时触发
        uploader.on('uploadSuccess', function (file, response) {
           console.log(file);
            console.log(response);
            console.log('上传成功' + response);
        });
        // 文件上传后服务端响应,服务端处理失败返回false,调用uploadError事件
        uploader.on('uploadAccept', function(obj, ret){
            console.log(obj);
            console.log(ret);
             console.log('uploadAccept===执行了');
        });
 
        // 当有文件添加进来时执行,负责view的创建
        function addFile( file ) {
            var $li = $( '<li id="' + file.id + '">' +
                    '<p class="imgWrap"></p>'+
                    '<p class="info">' + file.name + '</p>' +
                    '<p class="progress"><span></span></p>' +
                    '</li>' ),
 
                $btns = $('<div class="file-panel">' +
                    '<span class="cancel">删除</span>' +
                    '<span class="rotateRight">向右旋转</span>' +
                    '<span class="rotateLeft">向左旋转</span></div>').appendTo( $li ),
                $prgress = $li.find('p.progress span'),
                $wrap = $li.find( 'p.imgWrap' ),
                $info = $('<p class="error"></p>'),
 
                showError = function( code ) {
                    switch( code ) {
                        case 'exceed_size':
                            text = '文件大小超出';
                            break;
 
                        case 'interrupt':
                            text = '上传暂停';
                            break;
 
                        default:
                            text = '上传失败,请重试';
                            break;
                    }
 
                    $info.text( text ).appendTo( $li );
                };
 
            if ( file.getStatus() === 'invalid' ) {
                showError( file.statusText );
            } else {
                // @todo lazyload
                $wrap.text( '预览中' );
                uploader.makeThumb( file, function( error, src ) {
                    var img;
 
                    if ( error ) {
                        // 跟据文件类型显示对应缩略图 jpg,png直接预览
                        // gif,jpg,jpeg,bmp,png,zip,rar,pdf,xls,xlsx,doc,docx
                        var fileExt = file.ext;
                        switch (fileExt) {
                            case 'zip':
                                src = getadress() + '/csim/ctcst/archives/images/ZIP.jpg';
                                break;
                            case 'xlsx':
                                src = getadress() + '/csim/ctcst/archives/images/XLSX.png';
                                break;
                            case 'rar':
                                src = getadress() + '/csim/ctcst/archives/images/RAR.jpg';
                                break;
                            case 'pdf':
                                src = getadress() + '/csim/ctcst/archives/images/PDF.jpg';
                                break;
                            case 'xls':
                                src = getadress() + '/csim/ctcst/archives/images/XLS.png';
                                break;
                            case 'doc':
                                src = getadress() + '/csim/ctcst/archives/images/DOC.png';
                                break;
                            case 'docx':
                                src = getadress() + '/csim/ctcst/archives/images/DOCX.png';
                                break;
                            default :
                                $wrap.text( '文件格式不支持预览' );
                                return;
                        }
 
 
                    }
 
                    if( isSupportBase64 ) {
 
                        img = $('<img src="'+src+'">');
                        $wrap.empty().append( img );
                    }
                }, thumbnailWidth, thumbnailHeight );
 
                percentages[ file.id ] = [ file.size, 0 ];
                file.rotation = 0;
            }
 
            file.on('statuschange', function( cur, prev ) {
                if ( prev === 'progress' ) {
                    $prgress.hide().width(0);
                } else if ( prev === 'queued' ) {
                    //取消旋转删除div
                    //$li.off( 'mouseenter mouseleave' );
                    //$btns.remove();
                }
 
                // 成功
                if ( cur === 'error' || cur === 'invalid' ) {
                    //console.log( file.statusText );
                    showError( file.statusText );
                    percentages[ file.id ][ 1 ] = 1;
                } else if ( cur === 'interrupt' ) {
                    showError( 'interrupt' );
                } else if ( cur === 'queued' ) {
                    percentages[ file.id ][ 1 ] = 0;
                } else if ( cur === 'progress' ) {
                    $info.remove();
                    $prgress.css('display', 'block');
                } else if ( cur === 'complete' ) {
                    $li.append( '<span class="success"></span>' );
                }
 
                $li.removeClass( 'state-' + prev ).addClass( 'state-' + cur );
            });
 
            $li.on( 'mouseenter', function() {
                $btns.stop().animate({height: 30});
            });
 
            $li.on( 'mouseleave', function() {
                $btns.stop().animate({height: 0});
            });
 
            $btns.on( 'click', 'span', function() {
                var index = $(this).index(),
                    deg;
 
                switch ( index ) {
                    case 0:
                        uploader.removeFile( file );
                        return;
 
                    case 1:
                        file.rotation += 90;
                        break;
 
                    case 2:
                        file.rotation -= 90;
                        break;
                }
 
                if ( supportTransition ) {
                    deg = 'rotate(' + file.rotation + 'deg)';
                    $wrap.css({
                        '-webkit-transform': deg,
                        '-mos-transform': deg,
                        '-o-transform': deg,
                        'transform': deg
                    });
                } else {
                    $wrap.css( 'filter', 'progid:DXImageTransform.Microsoft.BasicImage(rotation='+ (~~((file.rotation/90)%4 + 4)%4) +')');
                }
 
 
            });
            $li.appendTo( $queue );
        }
 
        // 负责view的销毁
        function removeFile( file ) {
            var $li = $('#'+file.id);
 
            delete percentages[ file.id ];
            updateTotalProgress();
            $li.off().find('.file-panel').off().end().remove();
        }
     });   
    
 
})( jQuery );


后台接收数据如下:
第一步:建一个vo类,用于接收前台传来的参数


public class UploadImagesVo {
    private String id;
    //文件上传需要的参数
    private File multiFile[];
    private String multiFileFileName[];
 
     public String getId() {
        return id;
    }
 
    public void setId(String id) {
        this.id = id;
    }
    public File[] getMultiFile() {
        return multiFile;
    }
 
    public void setMultiFile(File[] multiFile) {
        this.multiFile = multiFile;
    }
 
    public String[] getMultiFileFileName() {
        return multiFileFileName;
    }
 
    public void setMultiFileFileName(String[] multiFileFileName) {
        this.multiFileFileName = multiFileFileName;
    }
}

第二步:创建一个实体类:

Entity
@Table(name = "PX_DA_UPLOAD_INFO")
public class UploadInfromation {
    private String id;
    private String dataCategory;//资料类别 ,个人资料 班级资料
    private String type;//类型 如:培训详情,鉴定详情
    private String batchNo;//班级编号==属于哪个班级
    private String fileName;//重命名之后的文件名称
    private String uploadName;//文件原始名称
    private String fileId;//文件的唯一标识
    private String path;//文件全路径
    private String filePath;//文件所在路径
    private String jgNo; //上传文件机构编号
    private String idNumber; //个人身份证
    @Id
    @GeneratedValue(generator = "upload_info_uuid")
    @GenericGenerator(name = "upload_info_uuid", strategy = "uuid")
    public String getId() {
        return id;
    }
 
    public void setId(String id) {
        this.id = id;
    }
 
    public String getIdNumber() {
        return idNumber;
    }
 
    public void setIdNumber(String idNumber) {
        this.idNumber = idNumber;
    }
 
    public String getFileId() {
        return fileId;
    }
 
    public void setFileId(String fileId) {
        this.fileId = fileId;
    }
 
    public String getFilePath() {
        return filePath;
    }
 
    public void setFilePath(String filePath) {
        this.filePath = filePath;
    }
 
    public String getDataCategory() {
        return dataCategory;
    }
 
    public void setDataCategory(String dataCategory) {
        this.dataCategory = dataCategory;
    }
 
    public String getType() {
        return type;
    }
 
    public void setType(String type) {
        this.type = type;
    }
 
    public String getBatchNo() {
        return batchNo;
    }
 
    public void setBatchNo(String batchNo) {
        this.batchNo = batchNo;
    }
 
    public String getFileName() {
        return fileName;
    }
 
    public void setFileName(String fileName) {
        this.fileName = fileName;
    }
 
    public String getUploadName() {
        return uploadName;
    }
 
    public void setUploadName(String uploadName) {
        this.uploadName = uploadName;
    }
    public String getPath() {
        return path;
    }
 
    public void setPath(String path) {
        this.path = path;
    }
 
    public String getJgNo() {
        return jgNo;
    }
 
    public void setJgNo(String jgNo) {
        this.jgNo = jgNo;
    }
}

第三步:建一个action类:

@SuppressWarnings("serial")
public class ArchivesAction extends ActionSupport implements ModelDriven<UploadImagesVo>{
    private UploadImagesVo vo = new UploadImagesVo();
    private IUploadImagesService uploadService;
    /**
     * 上传信息
     */
    public void uploadInformation(){
        Json json = new Json();
        try {
            UploadInformVo up = uploadService.uploadInformations(vo);
            json.setObj(up);
            json.setSuccess(true);
        }catch (Exception e){
            e.printStackTrace();
            json.setMsg(e.getMessage());
        }
        writeJson(json);
    }
    /**
     * 写出json
     * @param object 任何类型
     */
    public void writeJson(Object object) {
        try {
            String json = JSON.toJSONStringWithDateFormat(object, "yyyy-MM-dd");
            ServletActionContext.getResponse().setContentType(
                    "text/html;charset=utf-8");
            ServletActionContext.getResponse().getWriter().write(json);
            ServletActionContext.getResponse().getWriter().flush();
            ServletActionContext.getResponse().getWriter().close();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
 
    public IUploadImagesService getUploadService() {
        return uploadService;
    }
    @Resource
    public void setUploadService(IUploadImagesService uploadService) {
        this.uploadService = uploadService;
    }
 
    @Override
    public UploadImagesVo getModel() {
        return vo;
    }
}

第四步:创建一个Dao接口,既然要保存到数据库,那Dao层是必有得

public interface IUploadInformDao extends IBaseDAO<UploadInfromation,String>{
    
}

第五步:创建一个Dao并实现Dao接口

@Component
public class UploadInformDao extends BaseDAO <UploadInfromation,String> implements IUploadInformDao {
   
    
}

第六步:创建一个service的接口:

public interface  IUploadImagesService {
 
    /**
     * 文件上传
     * @param vo
     * @throws Exception
     */
    public UploadInformVo uploadInformations(UploadImagesVo vo) throws Exception;
 
}

第七步:现在Entity,action,service接口,Dao都有已经创建好了,可以开始实现业务逻辑了,创建一个service层并实现接口

@Component
public class UploadImagesService   implements IUploadImagesService  {
    private IUploadInformDao uploadInformDao;
    /**
     * 文件上传
     * @param vo
     * @throws Exception
     */
    public UploadInformVo uploadInformations(UploadImagesVo  vo) throws Exception{
            //取到当前登录的用户信息
            Users user = SecurityUser.getCurrentUserInfo();
            //生成MD5值
            String MD5 = getMd5ByFile(vo.getMultiFile()[0]);
            //上传的文件名
            String fileName =MD5+vo.getMultiFileFileName()[0].substring(vo.getMultiFileFileName()[0].lastIndexOf("."));
            //指定输出的路径,从项目的配置文件里读取
            PropertiesUtil propertiesu = PropertiesUtil.getInstance();
            String path = propertiesu.getKeyValue("archivesPath");
            if(!StringUtil.isNull(vo.getLx())){
                path+= File.separatorChar+vo.getLx();
            }
            if(!StringUtil.isNull(vo.getTypes())){
                path+=File.separatorChar+vo.getTypes();
            }
            if(!StringUtil.isNull(vo.getBatchNo())){
                path+=File.separatorChar+vo.getBatchNo();
            }
            if(!StringUtil.isNull(vo.getIdNumber())){
                path+=File.separatorChar+vo.getIdNumber();
            }
            //查询上传的图片是否已经上传过了,每个图片的MD5是唯一的
            UploadInfromation upload = new UploadInfromation();
            upload.setFilePath(path);
            upload.setFileId(MD5);
            List<UploadInfromation> list = uploadInformDao.findByProperties(upload);
            if(list.size() > 0){
                throw  new Exception(vo.getMultiFileFileName()[0]+" 文件在"+path+" 这个路径中已存在");
            }
            //取到文件并调用outFile方法写到指定的路径
            File file = vo.getMultiFile()[0];
             outFile(path, file,fileName);
 
             //然后把数据保存到数据库    
            if(!StringUtil.isNull(vo.getBatchNo())){
                upload.setBatchNo(vo.getBatchNo());
            }
            if(!StringUtil.isNull(vo.getIdNumber())){
                upload.setIdNumber(vo.getIdNumber());
            }
            upload.setDataCategory(vo.getLx());
            upload.setType(vo.getTypes());
            upload.setFileName(fileName);
            upload.setUploadName(vo.getMultiFileFileName()[0]);
            String filePath = path + File.separatorChar +fileName;
            upload.setPath(filePath);
            upload.setJgNo(user.getUnitId());
            uploadInformDao.save(upload);
 
            //通过写出去图片的路径生成Base64编码,并用vo返回到jsp页面展示
            String str = imageToBase64(upload.getPath());
            UploadInformVo vov = new UploadInformVo();
            BeanUtils.copyProperties(upload,vov);
            String s = vo.getMultiFileFileName()[0].substring(vo.getMultiFileFileName()[0].indexOf(".")+1,vo.getMultiFileFileName()[0].length());
            String src = "data:image/"+s+";base64,"+str;
            vov.setBase64(src);
        return vov;
    }
 
    /**
     * 生成md5
     * @param file 图片文件
     * @return MD5值
     * @throws FileNotFoundException
     */
    private  String getMd5ByFile(File file) throws FileNotFoundException {
        String value = null;
        FileInputStream in = new FileInputStream(file);
        try {
            MappedByteBuffer byteBuffer = in.getChannel().map(FileChannel.MapMode.READ_ONLY, 0, file.length());
            MessageDigest md5 = MessageDigest.getInstance("MD5");
            md5.update(byteBuffer);
            BigInteger bi = new BigInteger(1, md5.digest());
            value = bi.toString(16);
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            if(null != in) {
                try {
                    in.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
        return value;
    }
 
    /**
     * 通过文件路径将文件转成Base64编码
     * @param path 文件路径
     * @return base64结果
     */
    private String imageToBase64(String path) {
        // 将图片文件转化为字节数组字符串,并对其进行Base64编码处理
        byte[] data = null;
        // 读取图片字节数组
        try {
            InputStream in = new FileInputStream(path);
            data = new byte[in.available()];
            in.read(data);
            in.close();
        } catch (IOException e) {
            e.printStackTrace();
        }
        // 对字节数组Base64编码
        BASE64Encoder encoder = new BASE64Encoder();
        return encoder.encode(data);// 返回Base64编码过的字节数组字符串
    }
 
    /**
     * 指定的地方写出文件
     * @param outPath 文件路径
     * @param tempFile 文件
     * @param fileName 文件名
     * @throws IOException 错误异常
     */
    private void outFile(String outPath,File tempFile,String fileName) throws IOException {
        RandomAccessFile raFile = null;
        BufferedInputStream inputStream=null;
        try{
            File dirFile = new File(outPath);
            if(!dirFile.exists()) {
                dirFile.mkdirs();
            }
            File outFile = new File(outPath + File.separatorChar +fileName);
            raFile = new RandomAccessFile(outFile, "rw");
            raFile.seek(raFile.length());
            inputStream = new BufferedInputStream(new FileInputStream(tempFile));
            byte[] buf = new byte[1024];
            int length = 0;
            while ((length = inputStream.read(buf)) != -1) {
                raFile.write(buf, 0, length);
            }
        }catch(Exception e){
            throw new IOException(e.getMessage());
        }finally{
            try {
                if (inputStream != null) {
                    inputStream.close();
                }
                if (raFile != null) {
                    raFile.close();
                }
            }catch(Exception e){
                throw new IOException(e.getMessage());
            }
        }
    }
 
    public IUploadInformDao getUploadInformDao() {
        return uploadInformDao;
    }
    @Resource
    public void setUploadInformDao(IUploadInformDao uploadInformDao) {
        this.uploadInformDao = uploadInformDao;
    }
}


总结:到这里一个完整示例的多文件上传,再把数据保存到数据库已经完成了,这个示例仅供参考,毕竟我们用的框架是不一样,还有项目的ssh框架还有一定的分装,但是实现思路都是一样的,在这里留个笔记。也希望能给同学们一点启发,谢谢。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值