SpringMVC之文件上传下载

一、文件上传

文件上传是WEB经常面对的问题,对于Java应用主要有以下三种上传文件的方式

  • 文件流手工编程
  • 基于commons-fileupload的组件
  • 基于servlet3的文件上传

(一)单文件上传

1、创建应用导入jar包

  • Spring MVC相关jar包
  • commons-fileupload组件相关jar包
  • JSTL的相关jar包

2、创建web.xml文件

配置DispatcherServlet和添加字符编码过滤器

<!--配置DispatcherServlet -->
	<servlet>
		<servlet-name>Springmvc</servlet-name>
		<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
		<load-on-startup>1</load-on-startup>
	</servlet>
	<servlet-mapping>
		<servlet-name>Springmvc</servlet-name>
		<url-pattern>/</url-pattern>
	</servlet-mapping>
	<!-- 避免中文乱码 -->
	<filter>
    	<filter-name>characterEncodingFilter</filter-name>
    	<filter-class>org.springframework.web.filter.CharacterEncodingFilter</filter-class>
    	<init-param>
      		<param-name>encoding</param-name>
      		<param-value>UTF-8</param-value>
    	</init-param>
    	<init-param>
     		 <param-name>forceEncoding</param-name>
      		<param-value>true</param-value>
    	</init-param>
  </filter>
  <filter-mapping>
    <filter-name>characterEncodingFilter</filter-name>
    <url-pattern>/*</url-pattern>
  </filter-mapping>

3、创建文件上传页面

1、设置methon属性为post
2、 enctype属性为multipart/form-data,该编码方式表明服务器以二进制流的方式来处理表单数据,并将文件内容封装到请求参数里
3、表单属性multiple设置为multiple,可同时上传多个文件

<form action="${pageContext.request.contextPath }/onefile" method="post"
		enctype="multipart/form-data">
		选择文件:<input type="file" name="myfile" multiple="multiple"/><br>
		文件描述:<input type="text" name="description"/><br>
		<input type="submit" value="提交"/>	
	</form>

4、创建pojo类
领域模型中的属性名对应文件上传界面的file类型的表单参数名

public class FileDomain {

	private String description;
	private List<MultipartFile> myfile;
	//省略getter和setter方法
}

5、创建控制器类

@Controller
public class FileUploadController {
	private static final Log Logger = LogFactory.getLog(FileUploadController.class);
	@RequestMapping("/onefile")
	public String oneFileUpload(@ModelAttribute FileDomain fileDomain,HttpServletRequest request) {
		
//		指定文档上传的路径,本项目的发布路径是在tomcat下的webapps目录中
		String realPath = request.getServletContext().getRealPath("/uploadfiles/");
//		如果文件夹不存在则创建
		File targetDir = new File(realPath);
		if(!targetDir.exists()) {
			targetDir.mkdirs();
		}
//		获得上传的文件集
		List<MultipartFile> files = fileDomain.getMyfile();	
		for(MultipartFile file:files) {
			String filename = file.getOriginalFilename();
			File targetFile = new File(realPath,filename);
			System.out.println("目标文件为:"+targetFile);
//			开始文件上传
			try {
//				使用MultipartFile接口方法完成文件上传到指定位置
				file.transferTo(targetFile);
				Logger.info("文件上传成功!");
			} catch (Exception e) {
				e.printStackTrace();
			}
		}
		return "showone";
	}
}

6、创建springmvc-servlet.xml配置文件

1、添加扫描机制
2、配置视图解析器
3、使用spring的commonMultipartResolver,id必须为internalResourceViewResolver

<!-- 使用扫描机制扫描控制器类 -->
	<context:component-scan base-package="Controller"></context:component-scan>
	<!-- 配置视图解析器 -->
	<bean class="org.springframework.web.servlet.view.InternalResourceViewResolver" 
			id="internalResourceViewResolver">
		<property name="prefix" value="/WEB-INF/views/"></property>
		<property name="suffix" value=".jsp"></property>
	</bean>
	
	<bean id="multipartResolver" class="org.springframework.web.multipart.commons.CommonsMultipartResolver"	>
		<property name="defaultEncoding" value="UTF-8"></property>
		<property name="maxUploadSize" value="5400000000"></property>
		<property name="uploadTempDir" value="fileUpload/temp"></property>
	</bean>

7、创建成功显示界面

运用JSTL的核心标签库,需要在报头上添加
<%@ taglib uri=“http://java.sun.com/jsp/jstl/core” prefix=“c” %>

<body>
	${fileDomain.description }<br>
	<!-- fileDomain.getMyfile().getOriginalFilename() -->
	<c:forEach  items="${fileDomain.myfile }" varStatus="loop">
		文件名称:${fileDomain.myfile[loop.count-1].originalFilename }<br>
	</c:forEach>
</body>

8、测试文件上传
在这里插入图片描述在这里插入图片描述
因为本项目的发布路径是在Tomcat中,最后在Tomcat下的webapps中会有上传的文件,当Tomcat服务器关闭时,文件路径也会消失。
在这里插入图片描述

(二)多文件上传

多文件上传和单文件上传类似,只需要将文件上传页面改为多文件上传,如下:

<body>
	<form action="${pageContext.request.contextPath }/multipFiles" method="post"
		enctype="multipart/form-data">
		选择文件1<input type="file" name="myfile" multiple="multiple"/><br>
		文件描述1<input type="text" name="description"/><br>
		选择文件2<input type="file" name="myfile" multiple="multiple"/><br>
		文件描述2<input type="text" name="description"/><br>
		选择文件3<input type="file" name="myfile" multiple="multiple"/><br>
		文件描述3<input type="text" name="description"/><br>
		<input type="submit" value="提交"/>	
	</form>
</body>

在这里插入图片描述在这里插入图片描述

二、文件下载

(一)文件下载的实现方法

  • 通过超链接下载
  • 利用程序编码实现下载

1、利用超链接下载简单,但是暴露了下载文件的真实位置,并且只能下载存放在Web应用程序所在目录下的文件,具有一定的局限性
2、利用程序编码下载可以增加安全访问机制,还可以从任意位置提供下载的数据,即可以将文件存放在Web应用程序之外的目录中,也可以将文件保存到数据库。但实现较第一种下载略显困难。

利用程序实现下载需要设置两个报头:

response.setHeader("Content-Type", "application/x-msdownload");
response.setHeader("Content-Disposition", "attachment; filename="+filename);

(二)文件下载的实现过程

在执行文件下载时,需保证,对应的文件目录存在文件,否则会报错
1、编写控制器类

1、showDownloadFiles方法获取可下载的文件名称。
2、down方法执行下载功能。
3、toUTF8String方法是下载保存时中文文件字符编码转换,不出现乱码。

①showDownloadFiles方法

//	用于显示文件
	private String showDownloadFiles(Model model,HttpServletRequest request) {
//		获得文档下载的路径
		String realpath = request.getServletContext().getRealPath("/uploadfiles");
//		获取下载的文件
		File dir = new File(realpath);
		File file[] = dir.listFiles();
		System.out.println(file);
 		ArrayList<String> filenames = new ArrayList<String>();
		for(int i = 0;i<file.length;i++) {
			filenames.add(file[i].getName());
		}
		model.addAttribute("files", filenames);
		return "showDownloadFiles";
	}

在这里插入图片描述②down方法

@RequestMapping("down")
	private String down(@RequestParam String filename,
						HttpServletRequest request,HttpServletResponse response) {
		String filepath = null;
		InputStream in = null;
		ServletOutputStream out = null;
		try {
//			获得文件下载的路径
			filepath = request.getServletContext().getRealPath("/uploadfiles");
//			设置文件下载时的报头
			response.setHeader("Content-Type", "application/x-msdownload");
            response.setHeader("Content-Disposition", "attachment; filename="+
            				toUTF8String(filename));
//          读入文件
            in = new FileInputStream(filepath+"\\"+filename);
//          获得响应对象的输出流,用于向客户端输出二进制数据
            out = response.getOutputStream();
            out.flush();
            int ahead = 0;
            byte b[] = new byte[1024];
            while ((ahead = in.read(b)) != -1 & in != null) {
				out.write(b, 0, ahead);
			}
            out.flush();
            in.close();
            out.close();
		} catch (Exception e) {
			e.printStackTrace();
		}
		logger.info("文件下载成功");
		return null;
	}

在这里插入图片描述
③toUTF8String方法

//	下载文件时中文文件字符编码的转换
	private 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();
	}

在这里插入图片描述2、创建文件列表显示页面
这里同样用到了JSTL标签库

<body>
	<table>
		<tr><td>可下载的文件名</td></tr>
		<c:forEach var="filename" items="${files }">
			<tr>
				<td>
				<a href="${pageContext.request.contextPath }/down?filename=${filename}">${filename}</a>
				</td>
			</tr>
		</c:forEach>
	</table>
</body>

三、总结

(一)文件上传遇到的坎儿

①显示上传空间不够,改一下配置文件中最大上传字节
在这里插入图片描述②web.xml中若没有指定springmvc-servlet.xml的初始化位置,则需要将这两个文件统一放在webcontent/web-inf下,否则运行时会显示“这是一个不愿公开的资源”(重点,昨天没注意白花了两三个小时在找bug)
在这里插入图片描述
③若没有在配置文件中添加扫描包机制,也可能会出现上述问题

(二)文件下载遇到的坑

敲重点敲重点敲重点(重要的事情说三遍)
在文件下载之前一定要确定下载的路径中存在文件,否则会有空指针报错。

道阻且长,人生不易啊!笔落!!!

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值