文件上传
文件上传和下载是java web中常见的操作,文件上传主要是将文件通过IO流传放到服务器的某一个特定的文件夹下,而文件下载则是与文件上传相反,将文件从服务器的特定的文件夹下的文件通过IO流下载到本地。
对于文件上传,浏览器在上传的过程中是将文件以流的形式提交到服务器端的,如果直接使用Servlet获取上传文件的输入流然后再解析里面的请求参数是比较麻烦,所以一般选择采用apache的开源工具common-fileupload这个文件上传组件。这个common-fileupload上传组件的jar包可以去apache官网上面下载。common-fileupload是依赖于common-io这个包的,所以还需要下载这个包。
一、开发环境搭建
创建一个FileUploadAndDownLoad项目,加入Apache的commons-fileupload文件上传组件的相关Jar包,如下图所示:
二、实现文件上传
2.1 搭建前台页面
upload.html代码如下:
<div>
<h5>文件上传</h5><hr/>
<form id="file_upload_id" name="file_upload_name" >
<div><input type="file" name="file_upload"/></div>
<div onclick = "upload()"><input type="button" value="上传" /></div>
</form>
</div>
对upload.html添加js:
<script>
function upload(){
var formdata = new FormData($('#file_upload_id')[0]);
$.ajax({
url: 'cloud/load/upload',
type: 'POST',
data: formdata,
dataType:'JSON',
cache: false,
processData: false,
contentType: false ,
success : function(date){
alert(date.mes);
},
error : function(e){
alert("error");
}
});
}
</script>
说明:
在spring mvc框架下,通过spring注解,这里的ajax的url指向的是UploadAndDownloadController的upload()方法
2.2 controller
UploadAndDownloadController.java代码如下:
package com.cloud.web.controller;
import java.io.IOException;
import java.util.HashMap;
import javax.annotation.Resource;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.springframework.stereotype.Controller;
import org.springframework.ui.ModelMap;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.multipart.MultipartFile;
import com.cloud.web.service.FileLoadService;
@Controller
@RequestMapping("/load")
public class UploadAndDownloadController {
@Resource
public FileLoadService fileLoadService;
@RequestMapping(value = "/upload", method = RequestMethod.POST)
@ResponseBody
public HashMap<String,Object> upload(@RequestParam("file_upload") MultipartFile file, HttpServletRequest request, HttpServletResponse response, ModelMap model) throws ServletException, IOException {
String extName = "gif,jpg,jpeg,png,bmp,swf,flv,mp3,wav,wma,wmv,mid,avi,mpg,asf,rm,rmvb,doc,docx,xls,xlsx,ppt,htm,html,txt,zip,rar,gz,bz2,jsp";///文件类型
long fileSizeMax=1024 * 1024 * 50;//文件大小
HashMap<String,Object> map = new HashMap<String,Object>();
request.setCharacterEncoding("UTF-8");// 解决上传的中文文件乱码问题
response.setContentType("text/html;charset=UTF-8");
long fileSizeMax=Long.parseLong(size);
String mes =fileLoadService.doUpload(file,request, extName, fileSizeMax);
map.put("mes", mes);
return map;
}
}
2.3 service接口
FileLoadService程序如下:
package com.cloud.web.service;
import java.io.IOException;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import org.springframework.web.multipart.MultipartFile;
public interface FileLoadService {
String doUpload(MultipartFile file, HttpServletRequest request, String extName, long fileSizeMax) throws ServletException, IOException;
String genChildDirectory(String realPath);
}
2.4 service的实现类
FileLoadServiceImpl.java程序如下:
package com.cloud.web.service.impl;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.text.DateFormat;
import java.text.SimpleDateFormat;
import java.util.Date;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import org.springframework.stereotype.Service;
import org.springframework.web.multipart.MultipartFile;
import com.cloud.web.service.FileLoadService;
@Service
public class FileLoadServiceImpl implements FileLoadService{
@Override
public String doUpload(MultipartFile file, HttpServletRequest request, String extName, long fileSizeMax) throws ServletException, IOException{
String realPath = request.getSession().getServletContext().getRealPath("/WEB-INF/")+"/upload/"; // 存放路径
String msg="";//返回消息
try {
String fileName = file.getOriginalFilename();//获取文件名
String fileExt = fileName.substring(fileName.lastIndexOf(".") + 1).toLowerCase();// 获取文件格式
if (fileName != null) {
if(!extName.contains(fileExt)){
msg = "文件格式不正确";
}else if(file.getSize() > fileSizeMax){
msg = "文件过大";
}else{
Date now = new Date();
DateFormat df = new SimpleDateFormat("yyyyMMddHHmmss");
String str = df.format(now);
String nFileName=str+"_"+fileName;//对文件重命名,防止文件重名
String childDirectory = genChildDirectory(realPath);//按日期创建目录
File storeDirectory = new File(realPath + File.separator + childDirectory);//获取新目录的路径
if (!storeDirectory.exists()) {
storeDirectory.mkdirs();
}
//获取item中的上传文件的输入流
InputStream is = file.getInputStream();
//创建一个文件输出流
FileOutputStream out = new FileOutputStream(storeDirectory + "\\" + nFileName);
//创建一个缓冲区
byte buffer[] = new byte[1024];
//判断输入流中的数据是否已经读完的标致
int len = 0;
while((len = is.read(buffer)) > 0){
out.write(buffer, 0, len);
}
//关闭输出流
out.close();
//关闭输入流
is.close();
msg=fileName + "上传成功";
}
}
} catch (Exception e) {
e.printStackTrace();
}
return msg;
}
//按日期创建目录
@Override
public String genChildDirectory(String realPath) {
Date now = new Date();
DateFormat df = new SimpleDateFormat("yyyy-MM-dd");
String str = df.format(now);
File file = new File(realPath, str);
if (!file.exists()) {
file.mkdirs();
}
return str;
}
}
界面展示:
文件上传位置:
说明:
文件上传需要注意的几点:
1、为保证服务器安全,上传文件应该放在外界无法直接访问的目录下,比如放于WEB-INF目录下。
2、为防止文件覆盖的现象发生,要为上传文件产生一个唯一的文件名。
3、为防止一个目录下面出现太多文件,要使用hash算法打散存储。
4、要限制上传文件的最大值。
5、要限制上传文件的类型,在收到上传文件名时,判断后缀名是否合法。
以上 文件上传功能完成!