文件的上传和下载

本文讲解的是如何使用SpringMVC框架进行单文件上传,多文件以及文件下载。文件上传是Web应用经常需要面对的问题。对于Java应用而言上传文件有多种方式,包括使用文件流手工编程上传,基于commons-fileupload组件的文件上传,基于Servlet3及以上版本的文件上传等方式。本文重点介绍如何使用SpringMVC框架进行文件上传。

github项目代码:https://github.com/chegy218/ssm-review/tree/master/fileupload
文件上传
Spring MVC框架的文件上传是基于commons-fileupload组件的文件上传,只不过Spring MVC框架在原有文件上传组件上做了进一步封装,简化了文件上传的代码实现,取消了不同上传组件上的编程差异。
因此,需要commons-fileupload-1.3.1.jar和commons-io-2.4.jar。
现在,讲述一下如何下载JAR包,搞不懂CSDN上为什么有那么多人C币去下载别人上传的JAR包,现在介绍一个免费方法去下载JAR包,使用Maven Repository(JAR包仓库)
1,进入Maven官网(百度搜索Maven就可找到官网)
https://mvnrepository.com/
2,官网搜索JAR包的名字
文件的上传和下载
点击红圈内的链接。

3,选择点击JAR版本(一般选下载人数较多的)
文件的上传和下载4,点击jar即可下载
文件的上传和下载

----单文件上传
1,POJO类

public class FileDomain {
	private String description;
	private MultipartFile myfile;
	//省略setter和getter

2,控制器类

@Controller
public class FileUploadController {

	//得到一个用来记录日志的对象,这样在打印信息时能够标记打印的是哪个类的信息
	private static final Log logger = LogFactory.getLog(FileUploadController.class);
	
	/**
	 * 单文件上传
	 * @param fileDomain
	 * @param request
	 * @return
	 */
	@RequestMapping("/onefile")
	public String oneFileUpload(@ModelAttribute FileDomain fileDomain,
			HttpServletRequest request){
		
		String realpath = request.getServletContext().getRealPath("uploadfiles");
		logger.info(realpath);
		String fileName = fileDomain.getMyfile().getOriginalFilename();
		File targetFile = new File("C:/Users/Administrator/Downloads",fileName);
		if(!targetFile.exists()){
			targetFile.mkdirs();
		}
		
		//上传
		try{
			fileDomain.getMyfile().transferTo(targetFile);
			logger.info("成功");
		}catch(Exception e){
			e.printStackTrace();
		}
		return "showOne";
	}

3,SpringMVC配置文件

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
	xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:context="http://www.springframework.org/schema/context"
	xmlns:util="http://www.springframework.org/schema/util" xmlns:tx="http://www.springframework.org/schema/tx"
	xmlns:p="http://www.springframework.org/schema/p"
	xmlns:mvc="http://www.springframework.org/schema/mvc"
	xsi:schemaLocation="
        http://www.springframework.org/schema/beans
        http://www.springframework.org/schema/beans/spring-beans.xsd
        http://www.springframework.org/schema/context
        http://www.springframework.org/schema/context/spring-context.xsd
        http://www.springframework.org/schema/util 
		http://www.springframework.org/schema/util/spring-util.xsd
		http://www.springframework.org/schema/tx 
		http://www.springframework.org/schema/tx/spring-tx-2.5.xsd
		http://www.springframework.org/schema/mvc
		http://www.springframework.org/schema/mvc/spring-mvc.xsd">

	<!-- 使用扫描机制扫描控制器类,控制器类都在包及其子包下 -->
	<context:component-scan base-package="controller"></context:component-scan>

	<!-- 视图解析器 -->
	<bean id="jspViewResolver"
		class="org.springframework.web.servlet.view.InternalResourceViewResolver">
		<!-- 前缀 -->
		<property name="prefix" value="/WEB-INF/jsp/"></property>
		<!-- 后缀 -->
		<property name="suffix" value=".jsp"></property>
	</bean>
	
	<!-- 使用Spring的CommosMultipartResolver配置MultipartResolver用于文件上传 -->
	<bean id="multipartResolver" class="org.springframework.web.multipart.commons.CommonsMultipartResolver"
		p:defaultEncoding="UTF-8"
		p:maxUploadSize="5400000"
		p:uploadTempDir="fileUpload/temp">
	</bean>
	
	<!-- p:defaultEncoding="UTF-8"是请求的编码格式
		p:maxUploadSize="5400000"是允许上传文件的最大值,单位为字节
		p:uploadTempDir="fileUpload/temp"为上传文件的临时路径 -->
</beans>		

----多文件上传
1,创建POJO类

public class MultiFileDomain {
	private List<String> description;
	private List<MultipartFile> myfile;

2,多文件上传处理方法

/**
	 * 多文件上传
	 */
	@RequestMapping("/multifile")
	public String multiFileUpload(@ModelAttribute MultiFileDomain multiFileDomain,HttpServletRequest request){
		String realpath = null;
		realpath="C:/Users/Administrator/Downloads";
		File targetDir = new File(realpath);
		if(!targetDir.exists()){
			targetDir.mkdirs();
		}
		List<MultipartFile> files = multiFileDomain.getMyfile();
		for(int i=0; i < files.size();i++){
			MultipartFile file = files.get(i);
			String fileName = file.getOriginalFilename();
			File targetFile = new File(realpath,fileName);
			//上传
			try{
				file.transferTo(targetFile);
			}catch(Exception e){
				e.printStackTrace();
			}
		}
		logger.info("成功");
		return "showMulti";
	}

文件下载
实现文件下载有两种方法:一种是通过超链接实现下载,另一种是利用程序编程实现下载。通过超链接实现下载固然简单,但暴露了下载文件的真实位置,并且只能下载存放在Web应用程序所在的目录下的文件。利用程序编码实现下载可以增加安全访问控制,还可以从任意位置提供下载的数据,可以将文件存放到Web应用程序以为的目录中,也可以将文件保存到数据库中。

@Controller
public class FileDownController {
	//得到一个用来记录日志的对象,在打印时标记打印的是哪个类的信息
	private static final Log logger = LogFactory.getLog(FileDownController.class);
	
	//文件下载(图片展示)
	@RequestMapping("file/download.do")
	public ResponseEntity<byte[]> filedownload(String fileName) throws IOException {
		String path = "C:/Users/Administrator/Downloads/"+fileName;
		
		File file = new File(path);
		HttpHeaders headers = new HttpHeaders();
		headers.setContentType(MediaType.APPLICATION_OCTET_STREAM);
		return new ResponseEntity<byte[]>(FileUtils.readFileToByteArray(file), headers, HttpStatus.CREATED);
	}
	
	/**
	 * 显示要下载的文件
	 */
	@RequestMapping("showDownFiles")
	public String show(HttpServletRequest request,Model model){
		String realpath = null;
		realpath = "C:/Users/Administrator/Downloads";
		File dir = new File(realpath);
		File files[] = dir.listFiles();
		//获取该目录下的所有文件名
		ArrayList<String> fileName = new ArrayList<String>();
		for(int i=0;i < files.length;i++){
			fileName.add(files[i].getName());
			
		}
		model.addAttribute("files",fileName);
		return "showDownFiles";
	}
	
	//文件下载
	@RequestMapping("download.do")
	public ResponseEntity<byte[]> download(String fileName) throws IOException {
		String path = "C:/Users/Administrator/Downloads"+fileName;
//			System.out.println("------------>哈哈哈哈哈");
		File file = new File(path);
		HttpHeaders headers = new HttpHeaders();
		headers.setContentType(MediaType.APPLICATION_OCTET_STREAM);
		return new ResponseEntity<byte[]>(FileUtils.readFileToByteArray(file), headers, HttpStatus.CREATED);
	}
		
	/**
	 * 执行下载
	 */
	@RequestMapping("down")
	public String down(@RequestParam String filename,HttpServletRequest request,HttpServletResponse response){
		String aFilePath = null; //要下载的文件路径
		FileInputStream in = null; //输入流
		ServletOutputStream out = null; //输出流
		
		try {
			aFilePath = "C:/Users/Administrator/Downloads";
			//设置下载文件使用的报头
			response.setHeader("Content-Type", "application/x-msdownload");
			response.setHeader("Content-Disposition", "attachment;filename="+toUTF8String(filename));
			
			//读入文件
			in = new FileInputStream(aFilePath + "\\" +filename);
			//得到响应对象的输出流,用于向客户端输出二进制数据
			out = response.getOutputStream();
			out.flush();
			int aRead = 0;
			byte b[] = new byte[1024];
			while((aRead = in.read(b))!=-1 & in!=null){
				out.write(b,0,aRead);
			}
			out.flush();
			in.close();
			out.close();
		} catch (Exception e) {
			e.printStackTrace();
		}
		logger.info("下载成功");
		return null;
	}
	/**
	 * 下载保存时中文文件名的字符编码转换方法
	 * @param str
	 * @return
	 */
	public String toUTF8String(String str){
		StringBuffer sb = new StringBuffer();
		int len = str.length();
		for(int i=0; i < len; i++){
			//取出字符中的每个字符
			char c = str.charAt(i);
			//Unicode码值为0~255时,不做处理
			if(c>=0 && c<=255){
				sb.append(c);
			}else{
				//转换UTF-8编码
				byte b[];
				try {
					b = Character.toString(c).getBytes("UTF-8");
					
				} catch (UnsupportedEncodingException e) {
					e.printStackTrace();
					b = null;
					
				}
				//转换为%HH的字符串形式
				for(int j=0; j < b.length; j++){
					int k = b[j];
					if(k<0){
						k&=255;
					}
					sb.append("%" + Integer.toHexString(k).toUpperCase());
				}
			}
		}
		return sb.toString();
	}
	
}

注意:realpath,aFilePath,path都是本地的绝对路径