今天在写Struts2实现文件上传的例子的时候遇到一个问题,不管上传什么文件都出现java.lang.NullPointerException,查了下struts的文档和源码才发现问题出在哪,标记下···
上传文件的jsp代码:
<body>
<form action="fileUpload" method="post" enctype="multipart/form-data" >
上传文件:<input type="file" name="file"><br>
<input type="submit" value="上传">
<input type="reset">
</form>
</body>
其中enctype="multipart/form-data"是必须的,file对应的是action中的属性名
action代码:
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.InputStream;
import java.io.OutputStream;
import org.apache.struts2.ServletActionContext;
import com.opensymphony.xwork2.ActionSupport;
public class FileUploadAction 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;
}
public String execute()throws Exception{
InputStream inputStream = new FileInputStream(file);
String path = ServletActionContext.getServletContext().getRealPath("/a");
File toFile = new File(path, this.getFileFileName());
OutputStream outputStreams = new FileOutputStream(toFile);
byte[] buffer = new byte[1024];
int length = 0;
while((length = inputStream.read(buffer)) > 0){
outputStreams.write(buffer, 0, length);
}
inputStream.close();
outputStreams.close();
return SUCCESS;
}
}
在jsp中只有file一个属性名,而action中有三个参数,其他两个参数是怎样来的?原来struts中的FileUploadInterceptor这个拦截器已经帮我们做了一些工作,它会通过file这个属性找到对应的文件名和文件类型,只是我们要按照它设定的命名规则来命名这两个属性的setter方法,规则是:file的setter方法名+FileName;file的setter方法名+ContentType
struts.xml:
<struts>
<constant name="struts.enable.DynamicMethodInvocation" value="false" />
<constant name="struts.devMode" value="true" />
<constant name="struts.objectFactory" value="spring" />
<include file="struts-default.xml" />
<package name="default" namespace="/" extends="struts-default">
<action name="fileUpload" class="com.jyu.FileUploadAction">
<result name="success">/success.jsp</result>
<result name="input">/fileupload.jsp</result>
</action>
</package>
</struts>
下面是FileUploadInterceptor这个类中给出的例子:
* <p/> <u>Example code:</u>
* <p/>
* <pre>
* <!-- START SNIPPET: example-configuration -->
* <action name="doUpload" class="com.example.UploadAction">
* <interceptor-ref name="fileUpload"/>
* <interceptor-ref name="basicStack"/>
* <result name="success">good_result.jsp</result>
* </action>
* <!-- END SNIPPET: example-configuration -->
* </pre>
* <p/>
* <!-- START SNIPPET: multipart-note -->
* <p/>
* You must set the encoding to <code>multipart/form-data</code> in the form where the user selects the file to upload.
* <p/>
* <!-- END SNIPPET: multipart-note -->
* <p/>
* <pre>
* <!-- START SNIPPET: example-form -->
* <s:form action="doUpload" method="post" enctype="multipart/form-data">
* <s:file name="upload" label="File"/>
* <s:submit/>
* </s:form>
* <!-- END SNIPPET: example-form -->
* </pre>
* <p/>
* And then in your action code you'll have access to the File object if you provide setters according to the
* naming convention documented in the start.
* <p/>
* <pre>
* <!-- START SNIPPET: example-action -->
* package com.example;
* <p/>
* import java.io.File;
* import com.opensymphony.xwork2.ActionSupport;
* <p/>
* public UploadAction extends ActionSupport {
* private File file;
* private String contentType;
* private String filename;
* <p/>
* public void setUpload(File file) {
* this.file = file;
* }
* <p/>
* public void setUploadContentType(String contentType) {
* this.contentType = contentType;
* }
* <p/>
* public void setUploadFileName(String filename) {
* this.filename = filename;
* }
* <p/>
* public String execute() {
* //...
* return SUCCESS;
* }
* }
* <!-- END SNIPPET: example-action -->