一.文件上传三要素
1)表单提交post(get提交有大小限制,post提交没有)
2)表单的enctype属性:必须为multipart/form-data
3)input的type属性为file
注:在idea中若项目中的文件夹为空则文件夹是不打包的(即:若web目录下有一个存放上传文件的文件夹,若为空则不会打包i,用//根目录路径,可以指定绝对路径,比如 /var/www/attached/ String rootPath = pageContext.getServletContext().getRealPath("/") + "upload/";
是找不到文件夹的)
二.文件上传所用过滤器和具体实现(可以去看相关api)
<interceptor name="fileUpload" class="org.apache.struts2.interceptor.FileUploadInterceptor"/>
FileUploadInterceptor类中有一段代码
if (files != null && files.length > 0) {
List<File> acceptedFiles = new ArrayList(files.length);
List<String> acceptedContentTypes = new ArrayList(files.length);
List<String> acceptedFileNames = new ArrayList(files.length);
String contentTypeName = inputName + "ContentType";
String fileNameName = inputName + "FileName";
由其中的 String contentTypeName = inputName + “ContentType”;和String fileNameName = inputName + “FileName”;两段可以得知文件的类型名称和文件名称分别为(file的name属性+”“拼接出来的)如下代码:
UploadAction:
package com.study.upload;
import com.opensymphony.xwork2.ActionSupport;
import org.apache.commons.io.FileUtils;
import java.io.File;
/**
* @author: Demon
* @date: 2019/1/26
* @time: 20:39
* Description:文件上传
*/
public class UploadAction extends ActionSupport{
/**
* 根据约定获取表单参数
* 一定要给setter方法
*/
//接收上传的文件 约定:名称来自于file的name属性
private File attach;
//接收文件类型 固定写法name名称+ContentType
private String attachContentType;
//接收文件的名称 固定写法name名称+FileName
private String attachFileName;
private String info;
//注入服务器的目录地址
private String savePath;
public void setAttach(File attach) {
this.attach = attach;
}
public void setAttachContentType(String attachContentType) {
this.attachContentType = attachContentType;
}
public void setAttachFileName(String attachFileName) {
this.attachFileName = attachFileName;
}
public void setInfo(String info) {
this.info = info;
}
public void setSavePath(String savePath) {
this.savePath = savePath;
}
@Override
public String execute() throws Exception {
//保存文件到服务器的硬盘
FileUtils.copyFile(attach,new File(savePath+attachFileName));
return SUCCESS;
}
}
xml:
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE struts PUBLIC
"-//Apache Software Foundation//DTD Struts Configuration 2.3//EN"
"http://struts.apache.org/dtds/struts-2.3.dtd">
<struts>
<package name="upload" extends="struts-default" namespace="/upload">
<action name="upload" class="com.study.upload.UploadAction">
<result name="success">/index.jsp</result>
<param name="savePath">g:/data/</param>
</action>
</package>
</struts>
jsp:
<form method="post" action="${pageContext.request.contextPath}/upload/upload.action" enctype="multipart/form-data">
文件:<input type="file" name="attach"/><br/>
描述:<input type="text" name="info"/><br/>
<input type="submit" value="上传"/>
</form>
三.文件上传的常用参数配置(一般默认常量放在default.properties中)
1)上传文件的大小限制 (可以更改)
<constant name=“struts.multipart.maxSize” value=“10701096"/>
2)修改临时文件上传目录(默认为空在tomcat中)
struts.multipart.saveDir=
constant修改即可
3)修改文件上传的允许类型和允许的后缀名(注意这里不能在constant中修改了)
需要覆盖拦截器栈中并且往FileUploadInterceptor中注入值(其实是调用其中的setter方法)
<action name="upload" class="com.study.upload.UploadAction">
<interceptor-ref name="defaultStack">
<!--改变允许上传的文件类型-->
<param name="fileUpload.allowedTypes">image/jpeg,image/jpg</param>
<!--修改文件允许的后缀名-->
<param name="fileUpload.allowedExtensions">jpg,jpeg,gif</param>
<!--若两者都有则取交集-->
</interceptor-ref>
<result name="success">/index.jsp</result>
<param name="savePath">g:/data/</param>
</action>
三.文件下载
jsp页面:download.jsp需要将服务器一个目录上的文件显示到前台
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<%@taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core"%>
<html>
<head>
<title>Title</title>
</head>
<body>
<table border="1px">
<tr>
<th>编号</th>
<th>名称</th>
<th>操作</th>
</tr>
<c:forEach items="${requestScope.strings}" var="src" varStatus="varsta">
<tr>
<td>${varsta.count}</td>
<td>${src}</td>
<td><a href="${pageContext.request.contextPath}/down/down_download.action?name=${src}">下载</a></td>
</tr>
</c:forEach>
</table>
</body>
</html>
DownAction:
1)其中list方法将服务器中文件放在request域对象中传入前台,里面的serverPath就是注入的服务器文件存放路径
2)download方法是将显示在前台的文件下载到本地
name是从前台传入的文件名称
需要给struts写出数据输入流
public InputStream getInputStream() {
try {
FileInputStream fileInputStream=new FileInputStream(new File(serverPath+name));
return fileInputStream;
} catch (Exception e) {
e.printStackTrace();
throw new RuntimeException(e);
}
}
上面是文件下载到本地的核心代码
将(服务器地址+文件名称)写出给struts2使用的输入流
package com.study.download;
import com.opensymphony.xwork2.ActionContext;
import com.opensymphony.xwork2.ActionSupport;
import java.io.File;
import java.io.FileInputStream;
import java.io.InputStream;
import java.util.Map;
/**
* @author: Demon
* @date: 2019/1/26
* @time: 22:00
* Description:文件下载
*/
public class DownAction extends ActionSupport{
private String serverPath;
private String name;
public void setName(String name) {
this.name = name;
}
public String getName() {
return name;
}
public void setServerPath(String serverPath) {
this.serverPath = serverPath;
}
public String list()throws Exception{
File file=new File(serverPath);
String[] strings=file.list();
//把文件转到jsp页面
ActionContext actionContext=ActionContext.getContext();
Map<String ,Object> map=actionContext.getContextMap();
map.put("strings",strings);
return SUCCESS;
}
//需要给struts写出数据输入流
public InputStream getInputStream() {
try {
FileInputStream fileInputStream=new FileInputStream(new File(serverPath+name));
return fileInputStream;
} catch (Exception e) {
e.printStackTrace();
throw new RuntimeException(e);
}
}
public String download(){
return "down";
}
}
xml配置:很关键
其中
1)文件下载视图的type一定为stream
2)通用的文件返回二进制为:application/octet-stream
3)struts2的xml:读取类中属性的方法类似于el表达式(前提类中必须有相应的getter方法)<param name="contentDisposition">attachment;filename=${name}</param>
xml源码:
<package name="download" extends="struts-default" namespace="/down">
<action name="down_*" class="com.study.download.DownAction" method="{1}">
<param name="serverPath">f:/photo/</param>
<result name="success" type="dispatcher">/download.jsp</result>
<!--文件下载关键:视图一定是stream-->
<result name="down" type="stream">
<!--往Streamesult类中注入内容-->
<!--返回给浏览器的文件类型 返回通用的二进制-->
<param name="contentType">application/octet-stream</param>
<!--返回给浏览器的输入流-->
<param name="inputName">inputStream</param>
<!--告诉浏览器下载资源方式${name}获取DownAction中的getName()中的name-->
<param name="contentDisposition">attachment;filename=${name}</param>
<!--缓存大小-->
<param name="bufferSize">1024</param>
</result>
</action>
</package>