在学习jsp/servlet中,我们学习了如何利用apache中的commons项目中的upload组件实现文件上传功能,而在strut2中也有相应的文件上传功能,现在我们将两个方式进行对比。
1.Http上传
(1)新建一个web工程fileUpload,部署好环境
(2)fileUpload.jsp:(必须为post提交,编码类型为multipart/form-data)
fileUploadResult.jsp:(文件上传基于http协议,而http协议又基于TCP传输协议,所以在底层涉及了IO的传 输,这时想读取所上传的文件信息,必须运用相对的读取IO的方法)
<body>
<%
InputStream is = request.getInputStream();
BufferedReader br = new BufferedReader(new InputStreamReader(is));
String buffer = null;
while(null != (buffer = br.readLine()))
{
out.print(buffer + "<br>");
}
br.close();
is.close();
%>
</body>
执行结果:(传文件的格式)
2.upload组件上传
(1)获取fileUpload组件,在apache官网下载commons-fileupload和IO-commons,放到lib目录下
(2)UploadServlet
public class UploadServlet extends HttpServlet
{
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp)
throws ServletException, IOException
{
DiskFileItemFactory factory = new DiskFileItemFactory();//生成工厂类实例
//设置各种属性
String path = req.getRealPath("E:\\Workbench\\Workspace2\\fileUpload\\WebRoot\\upload");
factory.setRepository(new File(path));//设置临时存储路径
factory.setSizeThreshold(1020*1024);//设置缓存字节数
ServletFileUpload upload = new ServletFileUpload(factory);//创建处理页面上传的文件类
try
{
List<FileItem> list = (List<FileItem>)upload.parseRequest(req);//获得前台的输入元素
for(FileItem item: list)
{
String name = item.getFieldName();//获得输入域参数
if(item.isFormField())//判断是否为文本框或者上传文件
{
String value = item.getString();//获得输入值
System.out.println(name + "=" + value);
req.setAttribute(name, value);
}
else
{
String value = item.getName();//得到文件名
int start = value.lastIndexOf("\\");
String fileName = value.substring(start + 1);
req.setAttribute(name, fileName);
System.out.println(path);
item.write(new File("E:\\Workbench\\Workspace2\\fileUpload\\WebRoot\\upload", fileName));
}
}
} catch (Exception e)
{
e.printStackTrace();
}
req.getRequestDispatcher("fileUploadResult.jsp").forward(req, resp);
}
}
3.struts2文件上传,底层也是基于fileUpload,也需要导入commons-fileupload和IO-commons.jar包
UploadAction:
private String username;
private File file;
private String fileFileName;//filed的名字,****FileString固定写法
private String fileContentType;//file的类型,***FileContentType固定写法
public String getUsername()
{
return username;
}
public void setUsername(String username)
{
this.username = username;
}
public File getFile()
{
return file;
}
public void setFile(File file)
{
this.file = file;
}
public String getFileFileName()
{
return fileFileName;
}
public void setFileFileName(String fileFileName)
{
this.fileFileName = fileFileName;
}
public String getFileContentType()
{
return fileContentType;
}
public void setFileContentType(String fileContentType)
{
this.fileContentType = fileContentType;
}
@Override
public String execute() throws Exception
{
String root = ServletActionContext.getRequest().getRealPath("/upload");
InputStream is = new FileInputStream(file);
System.out.println(root);
File destFile = new File(root,fileFileName);
OutputStream os = new FileOutputStream(destFile);
byte[] buffer = new byte[400];
int length = 0;
while((length = is.read()) != -1)
{
os.write(buffer, 0, length);
}
is.close();
os.close();
return SUCCESS;
}
运用struts进行文件传输,可以减少代码量的书写,省去普通字符串输入的读取问题。
注:运行过程中struts2会报出信息: Unable to find 'struts.multipart.saveDir' property setting. Defaulting to javax.servlet.context.tempdir 可以打开default.properties查看struts.multipart.saveDir= ,然后在src根目录下新建一个struts.properties,写上
4.Struts2在进行文件上传操作时,实际上是通过两个步骤实现的:
1) 首先将客户端上传的文件保存到struts.multipart.saveDir键所指定的目录中,如果该键所对应的目录不存在,那么就保存到javax.servlet.context.tempdir 环境变量所指定的目录中。
2) Action中所定义的File类型的成员变量file实际上指向的是临时目录中的临时文件,然后在服务器端通过 IO的方式将临时文件写入到指定的服务器端目录中。
5.如果要进行多文件上传,则可以
(1)fileUpload2.jsp:
<body>
<form action="fileUpload2.action" method="post" enctype="multipart/form-data">
username:<input type="text" name="username"><br>
file:<input type="file" name="file"><br>
file:<input type="file" name="file"><br>
file:<input type="file" name="file"><br>
<input type="submit" value="submit">
</form>
</body>
(2)FileUploadAciton2
public class FileUpload2 extends ActionSupport
{
private String username;
private List<File> file;
private List<String> fileFileName;
private List<String> fileContentTypeList;
public String getUsername()
{
return username;
}
public void setUsername(String username)
{
this.username = username;
}
public List<File> getFile()
{
return file;
}
public void setFile(List<File> file)
{
this.file = file;
}
public List<String> getFileFileName()
{
return fileFileName;
}
public void setFileFileName(List<String> fileFileName)
{
this.fileFileName = fileFileName;
}
public List<String> getFileContentTypeList()
{
return fileContentTypeList;
}
public void setFileContentTypeList(List<String> fileContentTypeList)
{
this.fileContentTypeList = fileContentTypeList;
}
@Override
public String execute() throws Exception
{
for(int i = 0; i < file.size(); i ++)
{
InputStream is = new FileInputStream(file.get(i));
String root = ServletActionContext.getRequest().getRealPath("/upload");
File destFile = new File(root, fileFileName.get(i));
OutputStream os = new FileOutputStream(destFile);
byte[] buffer = new byte[400];
int length = 0;
while(-1 != (length = is.read(buffer)))
{
os.write(buffer, 0, length);
}
os.close();
is.close();
}
return SUCCESS;
}
}
结果显示页面(使用struts标签库中的iterator循环显示):
6.struts的核心功能是通过一系列的拦截器来实现功能的,打开struts-default.xml查看到
<interceptor name="fileUpload" class="org.apache.struts2.interceptor.FileUploadInterceptor"/>
struts文件上传是通过FileUploadInterceptor这个拦截器类来实现的
7.查看FileUploadInterceptor拦截器类可以发现定义了,这个是规定的文件最大上传大小(通常为2M),这个在实际开发中是比较不方便,因此可以改变上传的最大容量。
struts.properties:
也可以在struts.xml中的“package元素”前指定,效果和前者一样