jspSmartUpload(model1的年代);
apache-commons-fileupload,Struts2默认上传组件;
Servlet3.0使用的Part,但Servlet3.0还没有普及;
COS,Struts2支持,不过已经停止更新很久了;
pell,Struts2支持。
Struts2默认使用的是commons-fileUpload组件完成上传的,使用Struts2会大量简化上传文件的开发。
这一工作由fileUpload拦截器来完成。
它会查看当前请求的enctype是否为multipart/form-data,如果不是就会直接“放行”;
如果是,那么它会去解析表单,然后把解析的结果传递给Action的属性!
fileUpload拦截器对会对Action提供很大的“帮助”,同时它也会对Action提出一些“小小的要求”。
Action需要提供3个属性:
private File myUpload
private String myUploadContentType
private String myUploadFileName
上传文件首先我们需要给出一个页面,页面中要有一个表单:
upload.jsp
UploadAction
public class UploadAction extends ActionSupport {
private String username;
public void setUsername(String username) {
this.username = username;
}
private File myUpload;
private String myUploadContentType;
private String myUploadFileName;
private String savepath = "/WEB-INF/uploads";
public void setMyUpload(File myUpload) {
this.myUpload = myUpload;
}
public void setMyUploadContentType(String myUploadContentType) {
this.myUploadContentType = myUploadContentType;
}
public void setMyUploadFileName(String myUploadFileName) {
this.myUploadFileName = myUploadFileName;
}
public String execute() throws Exception {
System.out.println(username);
System.out.println(this.myUploadContentType);
System.out.println(this.myUploadFileName);
System.out.println(this.myUpload.getAbsolutePath());
this.savepath = ServletActionContext.getServletContext().getRealPath(savepath);
File destFile = new File(savepath, myUploadFileName);
FileUtils.copyFile(myUpload, destFile);
return NONE;
}
}
struts.xml
可以通过Struts2的常量来完成对上传的配置,下面是与上传相关的常量:
l struts.multipart.parser:指定使用的上传组件,默认值为jakarta,表示使用commons-fileupload组件,Struts2还支持cos和pell;
l struts.multipart.saveDir:临时目录,如果没有指定临时目录,那么临时文件会在Tomcat的work目录中;
l struts.multipart.maxSize:整个大小限制,默认值为2097152,即2M。注意,这个限制是整个请求的大小,而不是单一文件的大小。
当上传的表单超出了限制时,拦截器会向fieldError中添加错误信息!
当执行wokflow拦截器时,会发现fieldError中存在错误,这时就会跳转到input视图,所以我们需要为Action指定input视图。
case:
12097152
jpg,jpeg,bmp
image/pjpeg
dojo\..*,^struts\..*,^session\..*,^request\..*,^application\..*,^servlet(Request|Response)\..*,parameters\...*
input,back,cancel,browse
input,back,cancel,browse
/upload/demo1.jsp
/upload/demo1.jsp
/upload/demo2.jsp
/upload/demo2.jsp
修改提示信息:(重写配置文件中的信息)
fileUpload拦截器也有3个参数,我们可以给fileUpload拦截器配置这3个参数:
l maximumSize:上传的单个文件的大小限制;
l allowedTypes:允许上传文件的类型,多个类型以逗号隔开;
l allowedExtensions:允许上传文件的扩展名,多个扩展名以逗号隔开;
/demo1/upload.jsp
/WEB-INF/uploads
524288
jpg,png,bmp
在上传文件时如果出现错误,那么在input视图显示的错误信息都是英文的。
如果想替换这些信息,需要知道这些错误信息的资源key,然后在我们自己的国际化资源文件中指定这些key的新值即可。
与上传相关的错误信息都在org.apache.struts2包下的struts-message.properties文件中。
struts.messages.error.uploading=Error uploading: {0}
struts.messages.error.file.too.large=The file is to large to be uploaded: {0} "{1}" "{2}" {3}
struts.messages.error.content.type.not.allowed=Content-Type not allowed: {0} "{1}" "{2}" {3}
struts.messages.error.file.extension.not.allowed=File extension not allowed: {0} "{1}" "{2}" {3}
struts.messages.upload.error.SizeLimitExceededException=Request exceeded allowed size limit! Max size allowed is: {0} but request was: {1}!
我们可以在src下res.properties文件,在这个文件中对象以上资源key进行替换。
然后在struts.xml文件中给出
package cn.itheima.e_fileupload;
import java.io.File;
import java.util.UUID;
import org.apache.struts2.ServletActionContext;
import com.opensymphony.xwork2.ActionContext;
import com.opensymphony.xwork2.ActionSupport;
public class Demo1Action extends ActionSupport {
private File file; //跟表单提交的键一致
private String fileContentType;
private String fileFileName;
public String getFileContentType() {
return fileContentType;
}
public void setFileContentType(String fileContentType) {
this.fileContentType = fileContentType;
}
public String getFileFileName() {
return fileFileName;
}
public void setFileFileName(String fileFileName) {
this.fileFileName = fileFileName;
}
public File getFile() {
return file;
}
public void setFile(File file) {
this.file = file;
}
@Override
//将文件放入 res文件夹下
public String execute() throws Exception {
System.out.println(file);
//----------------------------
//1 获得res文件夹的路径
String dirPath = ServletActionContext.getServletContext().getRealPath("/res");
//2 创建目标文件
String fileName = UUID.randomUUID().toString();
File target = new File(dirPath+"/"+fileName);
//3 将file拷贝到目标文件中
file.renameTo(target);
//----------------------------------
System.out.println("上传文件的Mime类型:"+fileContentType);
System.out.println("上传文件的文件名称:"+fileFileName);
return SUCCESS;
}
}
/upload/demo1.jsp
/upload/demo1.jsp
当需要上传多个文件时,如果每个对应Action的3个属性,那么这会使Action的属性过多的现象。
处理这一问题的方法是在表单中设置所有的名称为相同名称,然后在Action中给出数组属性即可。
uploads.jsp
UploadsAction
public class UploadsAction extends ActionSupport {
private File[] myUpload;
private String[] myUploadContentType;
private String[] myUploadFileName;
private String savepath;
public void setSavepath(String savepath) {
this.savepath = savepath;
}
public void setMyUpload(File[] myUpload) {
this.myUpload = myUpload;
}
public void setMyUploadContentType(String[] myUploadContentType) {
this.myUploadContentType = myUploadContentType;
}
public void setMyUploadFileName(String[] myUploadFileName) {
this.myUploadFileName = myUploadFileName;
}
public String execute() throws Exception {
savepath = ServletActionContext.getServletContext().getRealPath(savepath);
for(int i = 0; i < myUpload.length; i++) {
System.out.println("文件名:" + myUploadFileName[i]);
System.out.println("文件类型:" + myUploadContentType[i]);
FileUtils.copyFile(myUpload[i], new File(savepath, myUploadFileName[i]));
}
return NONE;
}
}
其中Struts2也允许我们使用List类型来代替数组属性。
UploadsAction.java
public class UploadsAction extends ActionSupport {
private List myUpload;
private List myUploadContentType;
private List myUploadFileName;
…
}
package cn.itheima.e_fileupload;
import java.io.File;
import java.util.Arrays;
import java.util.UUID;
import org.apache.struts2.ServletActionContext;
import com.opensymphony.xwork2.ActionContext;
import com.opensymphony.xwork2.ActionSupport;
public class Demo2Action extends ActionSupport {
private File[] file;
private String[] fileContentType;
private String[] fileFileName;
public File[] getFile() {
return file;
}
public void setFile(File[] file) {
this.file = file;
}
public String[] getFileContentType() {
return fileContentType;
}
public void setFileContentType(String[] fileContentType) {
this.fileContentType = fileContentType;
}
public String[] getFileFileName() {
return fileFileName;
}
public void setFileFileName(String[] fileFileName) {
this.fileFileName = fileFileName;
}
@Override
//将文件放入 res文件夹下
public String execute() throws Exception {
System.out.println("上传文件:"+Arrays.toString(file));
System.out.println("上传文件的Mime类型:"+Arrays.toString(fileContentType));
System.out.println("上传文件的文件名称:"+Arrays.toString(fileFileName));
return SUCCESS;
}
}