最近做了一个下载文档的功能,于是联想到了上传功能,于是自己研究了一下后台语言是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;
}

第二种方式:通道方式

/**
* 使用通道的方式上传文件
* @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;
}

其实两种方式的差别不是特别大,大家可以自己研究一下!!
注意:在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的情况下的文件上传,今天就到此为止吧,抬头发现,人都走了,我也该下班去锻炼身体了!

文件上传之Java篇的更多相关文章

  1. 【转】JSch - Java实现的SFTP(文件上传详解篇)

    JSch是Java Secure Channel的缩写.JSch是一个SSH2的纯Java实现.它允许你连接到一个SSH服务器,并且可以使用端口转发,X11转发,文件传输等,当然你也可以集成它的功能到 ...

  2. JSch - Java实现的SFTP(文件上传详解篇)

    JSch是Java Secure Channel的缩写.JSch是一个SSH2的纯Java实现.它允许你连接到一个SSH服务器,并且可以使用端口转发,X11转发,文件传输等,当然你也可以集成它的功能到 ...

  3. JSch - Java实现的SFTP(文件上传详解篇) [转载]

    文章来源:http://www.cnblogs.com/longyg/archive/2012/06/25/2556576.html JSch是Java Secure Channel的缩写.JSch是 ...

  4. JSch - Java实现的SFTP(文件上传详解篇)(转)

    JSch是Java Secure Channel的缩写.JSch是一个SSH2的纯Java实现.它允许你连接到一个SSH服务器,并且可以使用端口转发,X11转发,文件传输等,当然你也可以集成它的功能到 ...

  5. 求超大文件上传方案( Java )

    最近遇见一个需要上传百兆大文件的需求,调研了七牛和腾讯云的切片分段上传功能,因此在此整理前端大文件上传相关功能的实现. 在某些业务中,大文件上传是一个比较重要的交互场景,如上传入库比较大的Excel表 ...

  6. 完整的多文件上传实例(java版)

    昨天刚刚做了一个文件列表上传,后端很简单,用 MultipartFile[] files 获取文件流数组,后端就当IO流操作就可以,似乎好像没啥好写的,但是!!!!!前端是真的糙单.要是自己写一个前端 ...

  7. HttpApplication实战大文件上传 (第四篇)

    一.Asp.net中的文件上传 在Asp.net 1.1中,文件在上传过程中将被全部保存在内存中,对于大文件来说,会造成内存空间的过度使用,可能会招致恶意攻击.为了解决这个问题,Asp.net在配置文 ...

  8. 文件上传之Ajax篇

    AJAX上传文件 1.为什么要写这篇文章  楼主前几天去北京面试,聊起ajax上传文件, 面试官告之不能,遂讨论之,不得果,于是写下这篇文章,希望能和大家一起学习 2.正文 首先,要使用ajax上传文 ...

  9. 超大文件上传方案( Java )

    1.介绍enctype enctype 属性规定发送到服务器之前应该如何对表单数据进行编码. enctype作用是告知服务器请求正文的MIME类型(请求消息头content-type的作用一样) 1. ...

随机推荐

  1. laydate实现设置最小时间为当前时间

    当前时间之前的日期不能选择,添加个min,主要代码如下: var now = new Date(); startTime= laydate.render({ elem: '#test1', type: ...

  2. 【转】IOS获取屏窗高度踩坑之window.outerHeight

    近日本人在直接使用window.outerHeight获取屏窗高度时 在iphone 6中出现等于0的情况,从而导致页面发生错误 后找遍代码,测试无数,终于让我逮住了这个该死兼容 window.out ...

  3. Webstorm在MAC下的安装方法

    一 .注册时,在打开的License Activation窗口中选择“License server”,在输入框输入下面的网址: http://idea.codebeta.cn (新,感谢Rachels ...

  4. VS2010-MFC(利用MFC向导生成单文档应用程序框架)

    一.VC++与MFC 讲VC++免不了要提MFC,MFC全称Microsoft Foundation Classes,也就是微软基础类库.它是VC++的核心,是C++与Windows API的结合,很 ...

  5. 杂项-公司:Amazon

    ylbtech-杂项-公司:Amazon 亚马逊公司(Amazon,简称亚马逊:NASDAQ:AMZN),是美国最大的一家网络电子商务公司,位于华盛顿州的西雅图.是网络上最早开始经营电子商务的公司之一 ...

  6. Jeecg-Boot 2.0 版本发布,基于Springboot+Vue 前后端分离快速开发平台

    目录 Jeecg-Boot项目简介 源码下载 升级日志 Issues解决 v1.1升级到v2.0不兼容地方 系统截图 Jeecg-Boot项目简介 Jeecg-boot 是一款基于代码生成器的智能开发 ...

  7. PAT甲级——A1091 Acute Stroke【30】

    One important factor to identify acute stroke (急性脑卒中) is the volume of the stroke core. Given the re ...

  8. cmake 2.8.12在redhat 4.4下安装

    以前安过,忘了,今天记笔记这里

  9. .NET Framework的属性类对控件的支持功能

     ToolBoxItem 此属性为类特性.属于工具箱属性,可以设置当前控件是否在工具箱中显示,以及所在工具箱项的类型名称等信息.默认生成的控件都显示在工具箱中. 更多设计时属性介绍: 4.3 属性的 ...

  10. Spark运行架构详解

    原文引自:http://www.cnblogs.com/shishanyuan/p/4721326.html 1. Spark运行架构 1.1 术语定义 lApplication:Spark Appl ...