一、文件上传
上传流程:
1、jsp页面上传文件
2、后台获取文件流(原理都是一样的,实现方式有所不同。
sevelet一般用ServletFileUpload从HttpServletRequest获取;
struts2会自动将文件流封装为File对象;springmvc则是MultipartFile)
3、获取输出流,在相应目录生成文件
下面结合以前做的项目,我给个简单的例子。
前台jsp上传代码就有不说了。如果用form的话,enctype="multipart/form-data"注意别丢了。
由于一般项目有多个地方需要上传文件,所以上传代码我一般建一个文件处理类,上传地址都在配置文件里配置。代码如下:
/**
* 根据配置文件的key获取对应的值
* @param key
* @return
*/
public static String getPropertyValue(String key){
Properties props = new Properties();
InputStream in = null;
in = FileTools.class.getClassLoader().getResourceAsStream("config.properties");
try {
props.load(in);
in.close();
} catch (FileNotFoundException e1) {
e1.printStackTrace();
} catch (IOException e1) {
e1.printStackTrace();
}
return props.getProperty(key);
}
/**
* 上传单个文件
* @param uploadFile 上传的文件
* @param uploadFileName 上传的文件名称
* @param uploadPath 上传的文件保存地址
* @return
*/
public static ResponseJson uploadFile(File uploadFile, String uploadFileName,String uploadPath) {
ResponseJson responseJson = new ResponseJson();
Result result = new Result();
boolean success = false;
if(uploadPath==null){
//如果服务器是linux,需要修改为filePathForLinux
String os = IpUtils.getOSName();
if (os.startsWith("linux")||os.startsWith("Linux")){
uploadPath = getPropertyValue("filePathForLinux");
}else{
uploadPath = getPropertyValue("filePath");
}
}
uploadPath = uploadPath + File.separator + DateUtils.getYMD();
System.out.println("上传文件临时名称: " + uploadFile.getName());
System.out.println("文件原名: " + uploadFileName);
System.out.println("文件保存地址: "+uploadPath);
//查看文件大小
if(uploadFile.length()<=0){
result.setMsg("上传的文件为空文件");
}else if(uploadFile.length()>0 && uploadFile.length()<153600000){
File file1 = new File(new File(uploadPath), uploadFileName);
if (file1.exists()) {
result.setMsg("已经有同名文件存在");
}else {
File dir = new File(uploadPath);
if (!(dir.exists()))
dir.mkdirs();
//上传文件
try {
FileUtils.copyFile(uploadFile, file1);
result.setMsg("文件上传成功");
success = true;
} catch (IOException e) {
e.printStackTrace();
result.setMsg("文件保存不成功");
}
}
}else{
result.setMsg("上传的文件大于50M");
}
result.setSuccess(success);
result.setName(uploadFileName);
responseJson.setFilePath(uploadPath);
responseJson.setSuccess(success);
responseJson.setResult(result);
return responseJson;
}
代码中 //如果服务器是linux,需要修改为filePathForLinux
String os = IpUtils.getOSName();
if (os.startsWith("linux")||os.startsWith("Linux")){
uploadPath = getPropertyValue("filePathForLinux");
}else{
uploadPath = getPropertyValue("filePath");
}
解释:
a>.这一块主要是因为我在windows下开发测试的上传路径和linux下不一样(因为我都用的是绝对路径),
因此如果不这样判断的话,每次开发完部署到服务器上时,路径就出错。所以我就先判断当前是什么系统,然后就调用该系统对应的上传目录
b>.除此之外,文件上传还需要判断文件类型、文件大小等,但个人认为这些最好是在前台做判断,做判断的目的就是为了不要让不合理的文件传到后台,对吧?
那如果在后台判断的话,你文件都传到后台了,还进行什么判断,不是已经迟了吗?无非就是保存与不保存的区别了
二、文件下载
相对于上传而言,下载逻辑就稍微复杂点了。流程如下:
1、读取待下载文件路径。
2、获取文件输入流(从待下载文件获取输入流)
3、设置文件输出流(即设置HttpServletResponse)。
4、核心:从输入流读入文件,从输出流生成文件。
示例代码如下:
/**
* 下载单个文件
* @param response
* @param filePath 下载的文件保存地址
* @param fileName 下载的文件名称
* @return
* @throws Exception
*/
public static Result downloadFile(HttpServletResponse response,String filePath,String fileName) throws Exception {
Result result = new Result();
result.setSuccess(false);
if("".equals(filePath)||null==filePath){
result.setMsg("文件路径异常");
}else{
// File file = new File(filepath);
System.out.println("-------开始下载--------"+fileName);
File file = new File(filePath,fileName);
if(file.exists()){
response.setHeader("Content-Type", "application/force-download");
//把文件名转码使前台可以显示中文名
response.setHeader("Content-Disposition", "attachment; filename=\""+
new String(fileName.getBytes("gb2312"), "ISO8859-1" )+"\"");
ServletOutputStream os = response.getOutputStream();
BufferedInputStream fin = new BufferedInputStream(new FileInputStream(file));
try {
byte[] content = new byte[1024];
int length;
while ((length = fin.read(content, 0, content.length)) != -1){
os.write(content, 0, length);
}
result.setSuccess(true);
} catch (Exception e) {
System.out.println("文件下载失败");
result.setMsg("文件下载失败");
}finally{
fin.close();
os.flush();
os.close();
}
}else{
System.out.println("要下载的文件不存在");
result.setMsg("要下载的文件不存在");
}
}
return result;
}
解释:
a>.这里返回的是我自定义的Result消息类,用于封装下载操作返回的信息。
b>.当然response头的设置不是唯一的,适合自己的就是最好的。
c>.文件下载过程中还会遇到乱码问题,无非就是字符集混乱了,耐心点就肯定能解决。
好了,简要的总结就到这里了。