一、文件上传
上传流程:
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>.文件下载过程中还会遇到乱码问题,无非就是字符集混乱了,耐心点就肯定能解决。
好了,简要的总结就到这里了。