• 文件上传之Java篇


    最近做了一个下载文档的功能,于是联想到了上传功能,于是自己研究了一下后台语言是java的情况下怎样实现将文件上传到指定的目录,以下是项目的语言:

    1、后台用jfinal框架

    2、前台用jquery提交

    3、样式用了bootstrap和jquery

    中间还因为需求发现了一个不错的jquery库,后面会有讲解,不多啰嗦了,下面直接开始吧:

    一、前端

    1、先添加一个上传文件的按钮:

    <button id="upload_blog" type="button" class="btn btn-info btn-lg" >
        <span class="glyphicon glyphicon-upload">上传</span>
    </button>

    注意:button和span中的class都是bootstrap中的样式,直接拿过来用,不过用之前是要引入bootstrap相关样式的!!!


    2、点击上传文件的按钮弹出一个选择上传文件的modal(模态框):

    <div class="modal fade" id="myModal" role="dialog">
        <div class="modal-dialog">
    
        <!-- Modal content-->
        <div class="modal-content">
            <div class="modal-header">
                <button type="button" class="close" data-dismiss="modal" id="close">&times;</button>
                <h4 class="modal-title">上传文件</h4>
            </div>
            <div class="modal-body">
                <div id="sizecheck" class="alert alert-danger">
                    提示:上传文件大小不能超过50M!
                </div>
                    <form action="" enctype="multipart/form-data" id="upload_file_form" accept="application/msword">
                <span style="display: inline;margin-left: 50px;">请选择上传文件:</span><input id="file1" type="file" name="up_blog" style="display: inline;">
                <div id="filecheck" class="alert alert-danger"><strong>Warning!</strong>只能上传pdf和word两种类型的文件</div>
                </form>
            </div>
            <div class="modal-footer">
                <button id="yes_blog" type="button" class="btn btn-info">确定</button>
                <button id="no_blog" type="button" class="btn btn-info" data-dismiss="modal">取消</button>
            </div>
        </div>
        </div>
    </div>

    上面是弹出的选择文件的模态框,点击确定按钮会向后台发送上传文件的请求:

    3、提交表单,将上传请求发送到服务器:

    $("#upload_blog").click(function(){
            $("#myModal").modal();
            $("#filecheck").attr("hidden","hidden");
            $("#sizecheck").attr("hidden","hidden");
            
            $("#yes_blog").click(function(){
                $("#upload_file_form").ajaxSubmit({
                    url:"/blog/uploadFile",
                    type:"POST",
                    dataType:"json",
                    async:false,
                    data:{},
                    beforeSubmit:function(){
                        //先判断文件类型--只能上传word、pdf或txt等文本类型的文件
                        var fileName = $("#file1").val();
                        var extension = fileName.substr(fileName.lastIndexOf("."));
                        if(extension==".pdf" || extension==".doc" || extension==".docx"){
                            $("#filecheck").attr("hidden","hidden");
                        }else{
                            $("#filecheck").removeAttr("hidden");
                            return false;
                        }
                        
                        //判断上传文件的大小
                        var fileSize =  $("#file1")[0].files[0].size;
                        //获取的文件大小单位是比特byte
                        if((fileSize/(1024*1024))>50){
                            $("#sizecheck").removeAttr("hidden");
                            return false;
                        }else{
                            $("#sizecheck").attr("hidden","hidden");
                        }
                    },
                    success:function(m){
                        if(m.error=="1"){
                            alert(m.message);
                            clearFile();
                            return false;
                        }else{
                            $("#close").trigger("click");
                            toastr.success("文件上传成功!");
                            clearFile();
                            return true; 
                        }
                    }
                });
            });
        });

    上面的JS代码就会将上传文件的表单提交到后台,在提交表单之前进行了一系列的验证:
    第一:判断文件类型,只能上传word、pdf和txt等文本类型,否则会有提示并阻止表单的提交;

    第二:判断文件的大小是否超过50M,否则会有提示并阻止表单的提交;

    二、后台:

     1、jfinal的controller中完成uploadFile方法:

    /**
         * 上传文件
         * @throws IOException 
         * @throws FileNotFoundException 
         */
        public void uploadFile(){
            /*String fileDate = new SimpleDateFormat("yyyy-MM-dd").format(new Date());*/
            UploadFile uploadFile = this.getFile();
            JSONObject jsonObj = new JSONObject();
            String fileName = uploadFile.getFileName();
            File file = uploadFile.getFile();
            String extension = fileName.substring(fileName.lastIndexOf("."));
            String prefix;
            if(extension.equals(".jpg")||extension.equals(".png")||extension.equals(".gif")){
                prefix = "images";
            }else{
                prefix = "docs";
            }
            String filePath = file.getAbsolutePath();
            File targetDir = new File(filePath.substring(0,filePath.indexOf(fileName))+prefix);
            File targetFile = new File(targetDir.getPath()+"/"+fileName);
            if(!targetDir.exists()){
                targetDir.mkdir();
            }
            //字节数组方式上传文件
            //jsonObj = BlogService.sevice.uploadByByte(filePath, fileName, file, targetFile);
            //通道方式上传文件
            jsonObj = BlogService.sevice.uploadByChanel(filePath, fileName, file, targetFile);
            renderJson(jsonObj.toJSONString());
        }


    注意:在上面的代码中可以看到有【字节数组方式上传文件】和【通道方式上传文件】,这是我在实现过程中发现的,并对这两种方法都做了实现:

    2、在service中编写业务逻辑,有两种方式:

    第一种方式:字节数组方式

    /**
         * 使用字节的方式上传文件
         * @param filePath
         * @param fileName
         * @param sourceFile
         * @param targetFile
         * @return
         */
        public JSONObject uploadByByte(String filePath,String fileName,File sourceFile,File targetFile){
            FileInputStream fis = null;
            FileOutputStream fos = null;
            JSONObject jsonObj = new JSONObject();
            try {
                
                fis = new FileInputStream(sourceFile);
                int fileSize = fis.available();
                fos = new FileOutputStream(targetFile);
                byte[] file_byte = new byte[fileSize];
                if(fis.read(file_byte,0, fileSize)!=-1){
                    fos.write(file_byte, 0, fileSize);
                }
                jsonObj.put("error", 0);
                sourceFile.delete();
            } catch (FileNotFoundException e) {
                jsonObj.put("error", 1);
                jsonObj.put("message", "上传出现错误,请稍后再上传");
            }catch (Exception e) {
                jsonObj.put("error", 1);
                jsonObj.put("message", "文件写入服务器出现错误,请稍后再上传");
            }finally{
                try {
                    fis.close();
                    fos.close();
                    deleteAllFile(new File(filePath.substring(0,filePath.indexOf(fileName))));
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
            return jsonObj;
        }
    View Code

    第二种方式:通道方式

    /**
         * 使用通道的方式上传文件
         * @param filePath
         * @param fileName
         * @param sourceFile
         * @param targetFile
         * @return
         */
        public JSONObject uploadByChanel(String filePath,String fileName,File sourceFile,File targetFile){
            JSONObject jsonObj = new JSONObject();
            FileInputStream fis = null;
            FileOutputStream fos = null;
            FileChannel in = null;
            FileChannel out = null;
            try {
                targetFile.createNewFile();
                fis = new FileInputStream(sourceFile);
                fos = new FileOutputStream(targetFile);
                in = fis.getChannel();//得到对应的文件通道
                out = fos.getChannel();
                in.transferTo(0,in.size(),out);//连接两个通道,并且从in通道读取后写入out通道
                jsonObj.put("error", "0");
            } catch (IOException e) {
                jsonObj.put("error", "1");
                jsonObj.put("message", "文件写入服务器出错,请稍后再传!");
            }finally{
                try {
                    fis.close();
                    fos.close();
                    in.close();
                    out.close();
                    deleteAllFile(new File(filePath.substring(0,filePath.indexOf(fileName))));
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
            return jsonObj;
        }
    View Code

    其实两种方式的差别不是特别大,大家可以自己研究一下!!
    注意:在controller中对文件上传的位置进行了自定义:

    首先Jfinal默认保存路径是webroot下的upload文件夹,要想保存在自己定义的文件夹中,先要在jfinal中进行配置,如果我要保存在webroot下的/static/upload中就要进行下面的配置:

    me.setBaseUploadPath(PathKit.getWebRootPath()+"/static/upload");

    然后要根据文件的类型,在自定义路径下分类创建不同的文件夹保存文件。controller中调用service之前的代码就是做了这个功能:

    UploadFile uploadFile = this.getFile();
            JSONObject jsonObj = new JSONObject();
            String fileName = uploadFile.getFileName();
            File file = uploadFile.getFile();
            String extension = fileName.substring(fileName.lastIndexOf("."));
            String prefix;
            if(extension.equals(".jpg")||extension.equals(".png")||extension.equals(".gif")){
                prefix = "images";
            }else{
                prefix = "docs";
            }
            String filePath = file.getAbsolutePath();
            File targetDir = new File(filePath.substring(0,filePath.indexOf(fileName))+prefix);
            File targetFile = new File(targetDir.getPath()+"/"+fileName);
            if(!targetDir.exists()){
                targetDir.mkdir();
            }

    最后,会发现即便是自己根据文件类型在默认路径下定义了新的文件夹,而且文件也会分类保存在相应的文件夹下,但是jfinal还是会在默认路径下保存一份文件,这样同一份文件,在默认路径下和默认路径下的自定义路径中都
    保存了一份,如下图所示:

    所以为了上文件只保存在指定的目录中,就要做一个删除upload目录下的冗余文件的操作,就是service中调用的deleteAllFile(new File(filePath.substring(0,filePath.indexOf(fileName))));这部分,实现如下:

        /**
         * 删除默认路径下的文件
         * @param file
         */
        public void deleteAllFile(File file){
                File[] files = file.listFiles();
                for(int i=0;i<files.length;i++){
                    File filei = files[i];
                    if(filei.isFile()){
                        filei.delete();
                    }
                }
        }


    以上所有步骤就完成了一次上传文件到指定目录的功能,下面说一下刚开始说的发现的有趣的jquery库,可以在提交表单的代码中看到这么一句:

    toastr.success("文件上传成功!");

    其实这是一个提示框,而且可以设置自动消失,避免用户知道自己操作成功之后还要手动关闭提示框的操作,下面说一下这个技术的实现:
    第一步:下载相关的包,并引入相关文件:

    只要搜索toastr.js下载就会找到github资源路径,下载压缩包,解压后找到这几个文件:

    不一定都能用到,但是都放在lib里,以备不时之需,我在这里只用到了这几个:

    <link rel="stylesheet" type="stylesheet" href="../../static/js/lib/bootstrap/css/message/toastr.min.css">
    <link rel="stylesheet" type="stylesheet" href="../../static/js/lib/bootstrap/css/message/messenger.css">
    <script type="text/javascript" src="../../static/js/lib/bootstrap/js/message/messenger.min.js?v=${version}"></script>
    <script type="text/javascript" src="../../static/js/lib/bootstrap/js/message/messenger-theme-future.js?v=${version}"></script>

    第二步:使用前进行配置:

    /*提示框配置  */
        toastr.options = {
                /* closeButton:false,//是否配置关闭按钮
                debug:false,//是否开启debug模式
                neweastOnTop:false,//新消息是否排在最上面
                progressBar:false,//是否显示进度条
                preventDuplicates:false,//是否阻止弹出多个消息框
                onclick:null,//点击回调函数
                showDuration:"300",//显示动作时间
                hideDuration:"300",//隐藏动作时间 */
                positionClass: "toast-center",//消息框的显示的位置
                timeOut:"1000",//自动关闭的超时时间,即1秒后关闭
                /* extentedTimeOut:"1000",
                showEasing:"swing",
                hideEasing:"liner",
                showMethod:"fadeIn",//显示的方式
                hideMethod: "fadeOut",//关闭的方式 */
        }

    上面是所有配置信息以及作用的解释,值得注意的是,positionClasss属性,默认的值有:

    可以看到,这些属性值中,提示框的位置都是在边缘,没有在中间的,所以我就自定义了一个处于中间位置的class:toaster-center

    大家也可以根据自己的页面属性自定义 !!

    配置完之后就是使用了,其实使用起来很简单,就一句代码的事:

    toastr.success("文件上传成功!");

    success方式只是定义了弹出框的背景颜色,总共有四种方式:
    1、success成功:绿色

    2、info信息:蓝色

    3、warning警告:橙色

    4、error错误:深红色

    这个颜色的标准跟bootstrap中是一样的!

    以上就是本次文件上传的所有代码,以及延伸jquery库的介绍,下次会介绍后台语言选择PHP的情况下的文件上传,今天就到此为止吧,抬头发现,人都走了,我也该下班去锻炼身体了!

    最美好的时光里,不要一直是一个lowser!
  • 相关阅读:
    MyBatis学习篇
    常见两大类(个人和企业)登记主体小程序的区别
    Redis学习篇
    Spring注解之参数校验@Validated和@Valid
    Spring学习篇
    Windows安装OnlyOfiice教程
    Java序列化和反序列化
    数据库种类大全
    C# Web请求URL编码转换 URL转码 UrlDecode UrlEncode
    使用DockerCertBot获取SSL证书
  • 原文地址:https://www.cnblogs.com/hellowhy/p/6413390.html
Copyright © 2020-2023  润新知