0x0 工欲善其事,必先利其器
安装配置 Tomcat 9,集成环境用 IntelliJ IDEA,这样可以避免很多繁琐的步骤。
0x1 建立项目
注意还需要勾选 Web Application,完成之后 IDEA 会自动下载 Struts2 依赖库:
程序发布后,Struts2 作为依赖库也需要部署到线上环境中,在 Project Structure 中可以设置 Struts2 类库随程序发布:
0x3 实现
为了简化程序,只实现上传页面,Action 的执行执行结果直接使用字符串返回。
在 src 目录下新建包,开始编写实现类:
package com.soxfmr.fileupload;
import com.opensymphony.xwork2.ActionSupport;
import org.apache.commons.io.FileUtils;
import java.io.ByteArrayInputStream;
import java.io.File;
import java.io.IOException;
import java.io.InputStream;
public class FileUploadAction extends ActionSupport {
private static final String PATH_UPLOAD = "uploads";
private InputStream inputStream;
private File entity;
private String entityFileName;
private String entityContentType;
public InputStream getInputStream() {
return inputStream;
}
public void setInputStream(InputStream inputStream) {
this.inputStream = inputStream;
}
public String getEntityContentType() {
return entityContentType;
}
public void setEntityContentType(String entityContentType) {
this.entityContentType = entityContentType;
}
public String getEntityFileName() {
return entityFileName;
}
public void setEntityFileName(String entityFileName) {
this.entityFileName = entityFileName;
}
public File getEntity() {
return entity;
}
public void setEntity(File entity) {
this.entity = entity;
}
public String httpFileUpload() {
String ret = "error.";
if (entity != null) {
// 因为实际 Action 返回类型是流,所以写法是如此之蛋疼
// 注意这里没对文件进行任何判断
try {
File dstFile = new File(PATH_UPLOAD, entityFileName);
FileUtils.copyFile(entity, dstFile);
ret = "success!";
} catch (IOException e) {
e.printStackTrace();
}
} else {
ret = "No file represent";
}
inputStream = new ByteArrayInputStream(ret.getBytes());
return SUCCESS;
}
}
上传页面:
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>Home</title>
</head>
<body>
<form action="httpFileUpload.action" method="POST" enctype="multipart/form-data">
<label>File: </label>
<input type="file" name="entity">
<input type="submit" value="Upload">
</form>
</body>
</html>
上传页面里并没有 FileName 和 ContentType 等字段,这些字段由 Struts2 框架自动获取,并通过 set 方法自动赋值给 Action 对象。
等等为啥 Struts2 会知道应该设置哪个变量?
其规则是通过 File 变量名定义,例如;
private File image;
则文件信息会设置到 xxFileName 和 xxContentType:
private String imageFileName;
private String imageContentType;
struts.xml 配置文件:
<struts>
<package name="fileManager" extends="struts-default" namespace="/">
<action name="httpFileUpload" class="com.soxfmr.fileupload.FileUploadAction" method="httpFileUpload">
<result type="stream">
<param name="contentType">text/plain</param>
<param name="inputName">inputStream</param>
</result>
</action>
</package>
</struts>
package 中 extends 字段需要设置为 struts-default,才能正常引用返回类型。struts-default 中定义了各种 Result Type:
0x4 完成
上传测试:
返回结果:
相关参考资料:
Struts 2 - File Uploads
Return a string from Struts2 action to jQuery