一、文件上传
1.1 文件上传
在 Web 开发中,使用应用层协议 HTTP,通过在请求头中设置传输的内容类型 Content-Type 为 multipart/form-data; boundary=流分隔符值
来上传文件,这个流分隔符用来区分一个文件上传的开始和结束。
<%-- 文件上传 表单提交的方式--%>
<%-- 文件上传的规范:enctype="multipart/form-data" method="post"--%>
<form enctype="multipart/form-data" action="upload" method="post">
选择上传的文件:<input type="file" name="file">
<input type="submit" value="点击上传" id="btn1">
</form>
表单中的enctype 属性说明:
- application/x-www=form-urlencoded:默认方式,只处理表单域中的 value 属性值,采用这种编码方式的表单会将表单域中的值处理成 URL 编码方式。
- multipart/form-data:这种编码方式会以二进制流的方式来处理表单数据,这种编码方式会把文件域指定文件的内容也封装到请求参数中,不会对字符编码。
- text/plain:除了把空格转换为 “+” 号外,其他字符都不做编码处理,这种方式适用直接通过表单发送邮件。
1.2 文件下载
通过在响应消息头中设置 Content-Disposition 和 Content-Type 使得浏览器无法使用某种方式或者激活某个程序来处理 MIME 类型的文件,来让浏览器提示是否保存文件,也就是文件的下载。
response.setHeader("content-disposition","attachment;filename="+filename);
response.setContentType("application/octet-stream");
二、SpringMVC中的文件上传与下载
前提:自己在本机配置一个虚拟目录
可以在tomcat的conf目录下面的server.xml中设置:
在文件的Host标签中设置虚拟目录:
<Context path="/updatefile" docBase="E:\tomcat_test_uploadAndupdown" reloadable="true"/>
属性说明:
代码说明
元素,用于将本地文件系统中的一个目录,映射成一个可供Web浏览器访问的虚拟根目录
path属性 | 用于指定Web应用的虚拟路径 |
---|---|
docBase属性 | 用于指定该虚拟路径,所映射到的本地文件系统目录 |
reloadable | 如果设置为true,则tomcat服务器在运行时,会监视WEB-INF/classes和WEB-INF/lib目录下类的改变 |
详细可参考:
2.1 文件表单上传
1.配置文件上传解析器,限制上传文件的大小
<bean id="multipartResolver" class="com.gx.CommonsMultipartResolverPlus.PlusCommonsMultipartResolver">
</bean>
这个拦截器可以对上传文件进行一些限定:比如设置编码,设置文件上传的大小
<!--设置请求编码-->
<property name="defaultEncoding" value="UTF-8"/>
<property name="uploadTempDir" value="WEB-INF/tmp"/>
<!--设置允许单个上传文件的最大值,不要在这里配置-->
<!--<property name="maxUploadSizePerFile" value="31457280"/>-->
<!--延迟解析,在Controller中抛出异常-->
<property name="resolveLazily" value="true"/>
当文件上传大小出现异常的时候,设置resolveLazily属性为true,在拦截器中对文件上传进行限制,拦截器抛出异常,在Controller中获取异常,进行处理。
拦截器限制文件的大小(这里只写了一个preHandle方法):
public class FileUploadInterceptor implements HandlerInterceptor {
private long maxSize;
@Override
public boolean preHandle(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, Object o) throws Exception {
if (httpServletRequest != null && ServletFileUpload.isMultipartContent(httpServletRequest)) {
ServletRequestContext servletRequestContext = new ServletRequestContext(httpServletRequest);
long requestSize = servletRequestContext.contentLength();
if (requestSize > maxSize) {
// 抛出异常
throw new MaxUploadSizeExceededException(maxSize);
}
}
return true;
}
public void setMaxSize(long maxSize) {
this.maxSize = maxSize;
}
}
Controller处理异常
@ExceptionHandler(MaxUploadSizeExceededException.class)
public String handException(MaxUploadSizeExceededException e, HttpServletRequest request) {
request.setAttribute("msg", "文件超过了指定大小,上传失败!");
return "fileupload";
}
2.表格实现文件上传
<form enctype="multipart/form-data" action="upload" method="post">
选择上传的文件:<input type="file" name="file">
<input type="submit" value="点击上传" id="btn1">
</form>
<script>
$(function () {
$("#btn1").click(function(){
var tt= setInterval(function(){
$.ajax({
type: "get",
url: "uploadState",
success: function (result) {
console.log(result);
$("#uploadFileState").text(result.msg);
if (result.msg=="ok"){
clearInterval(tt)
}
}
});
},1000);
});
</script>
3.后台controller
//配置文件上传的路径
public String TargetPath="E:\\tomcat_test_uploadAndupdown";
@RequestMapping(value = "/uploadState",method = RequestMethod.POST)
public String upload(@RequestParam("uploadFile") CommonsMultipartFile uploadFile) throws IOException {
//获取文件在客户端真实名字
String fname = uploadFile.getOriginalFilename();
////如果出现文件名称相同的话,我们需要将存储的文件名称唯一化。加入UUID保证文件名唯一
String uuidName= UUID.randomUUID().toString();
File TargetFile = new File(TargetPath+File.separator+FileRealName);
//将文件储存在服务器的位置
uploadFile.transferTo(TargetFile);
return "index";
}
过程:
前台表单提交之后,springMVC识别多媒体文件之后,会将表单内容自动注入到 CommonsMultipartFile中。我们可以通过getOriginalFilename()方法获取到文件的名称,为了防止文件名重名,使用UUID对文件名进行处理。然后根据我们自己的需求,将文件上传到一个文件夹或者是一个服务器的上面。
2.2 Ajax实现上传文件
Ajax实现文件上传的优点:页面无刷新上传
1.可以参考上面配置文件上传解析器,限制文件大小
2. 发送Ajax实现文件上传
<input type="file" name="file" id="file" >
<input type="submit" id="btn2" value="上传文件">
<script>
$("#btn2").click(function () {
//取表单的数据
var formData=new FormData();
formData.append("file",$("#file")[0].files[0]);
alert(formData)
$.ajax({
url:"uploadAjax",//文件返回一个ajax
type:"post",
data:formData,
contentType:false,//大小写错误的话报400
//Required CommonsMultipartFile parameter 'xxx' is not present
processData:false,
success:function (result) {
console.log(result.msg);
}
})
});
</script>
3.Controller
@RequestMapping(value = "/uploadAjax",method = RequestMethod.POST)
@ResponseBody
public Map uploadAjax(@RequestParam("file") CommonsMultipartFile file, HttpServletRequest request) throws IOException {
//获取上传文件的真实名字
String FileRealName = file.getOriginalFilename();
String uuidName = UUID.randomUUID().toString();//保证名称唯一
//传递到当前项目的目录下
File TargetFile = new File(TargetPath+File.separator+FileRealName);
//文件存储的位置
file.transferTo(TargetFile);
Map<String, String> msp = new HashMap<>();
msp.put("msg","文件上传完毕");
System.out.println(TargetFile.getAbsolutePath());
return msp;
}
2.3 多文件上传
多文件表单上传:
<form enctype="multipart/form-data" action="uploadMore" method="post">
选择上传的文件:<input type="file" name="file"><br>
选择上传的文件:<input type="file" name="file"><br>
选择上传的文件:<input type="file" name="file"><br>
<input type="submit" value="点击上传" >
</form>
@RequestMapping(value = "/uploadMore",method = RequestMethod.POST)
public String uploadMore(@RequestParam("file") CommonsMultipartFile[] files, HttpServletRequest request) {
try {
for (CommonsMultipartFile file : files) {
//获取上传文件的真实名字
String FileRealName = file.getOriginalFilename();
//传递到当前项目的目录下
File TargetFile = new File(TargetPath+File.separator+FileRealName);
//文件存储的位置
file.transferTo(TargetFile);
}
} catch (IOException e) {
e.printStackTrace();
} catch (IllegalStateException e) {
e.printStackTrace();
}
return "index";
}
2.4 文件下载
文件上传下载设置返回值为ResponseEntity
@RequestMapping("/downLoadFile/{fileName:.+}")
public ResponseEntity downLoadFile(@PathVariable("fileName")String fileName, HttpServletRequest request) throws IOException {
System.out.println(fileName);
File file = new File(TargetPath + File.separator + fileName);
//处理中文
String agent = request.getHeader("user-agent");
fileName = DownLoadUtils.getFileName(agent, fileName);
//读取文件
byte[] bytes = FileUtils.readFileToByteArray(file);
HttpHeaders httpHeaders = new HttpHeaders();
//设置响应头
httpHeaders.setContentType(MediaType.APPLICATION_OCTET_STREAM);
// fileName = new String(fileName.getBytes("UTF-8"), "iso8859-1");
httpHeaders.setContentDispositionFormData("attachment",fileName);
ResponseEntity responseEntity = new ResponseEntity(bytes,httpHeaders, HttpStatus.OK);
System.out.println("文件下载成功");
return responseEntity;
}
根据前端url中获取到需要下载的文件名。文件下载最重要的是设置响应头。通过httpHeaders进行设置
httpHeaders.setContentType(MediaType.APPLICATION_OCTET_STREAM);
httpHeaders.setContentDispositionFormData("attachment",fileName);
也可以通过response进行相应头的设置
response.setContentType("application/octet-stream");
response.setHeader("content-disposition","attachment;filename="+fileName);
处理中文的问题
1.编写工具类,上面代码所使用的DownLoadUtils,根据浏览器的请求头中user-agent属性进行编码的设置
public class DownLoadUtils {
public static String getFileName(String agent, String filename) throws UnsupportedEncodingException {
if (agent.contains("MSIE")) {
// IE浏览器
filename = URLEncoder.encode(filename, "utf-8");
filename = filename.replace("+", " ");
} else if (agent.contains("Firefox")) {
// 火狐浏览器
BASE64Encoder base64Encoder = new BASE64Encoder();
filename = "=?utf-8?B?" + base64Encoder.encode(filename.getBytes("utf-8")) + "?=";
} else {
// 其它浏览器
filename = URLEncoder.encode(filename, "utf-8");
}
return filename;
}
}
调用方法,传入agent以及文件名。
-
使用Sting的一个构造方法,对编码进行设置
public String(byte bytes[], String charsetName) throws UnsupportedEncodingException { this(bytes, 0, bytes.length, charsetName); }
headers.setContentDispositionFormData("attachment",new String((filename).getBytes("utf-8"),"iso-8859-1"));
ResponseEntity
ResponseEntity可以标识整个http相应,包括状态码、头部信息以及响应体内容
- 可以使用任意类型作为响应体;
- 可以通过编程方式指明响应状态,根据不同场景返回不同状态;
- 设置http响应头;
ResponseEntity responseEntity = new ResponseEntity(bytes,httpHeaders, HttpStatus.OK);
状态码 、数据 和 头信息
转载:https://blog.csdn.net/weixin_45707030/article/details/106577643