服务热线:13616026886

技术文档 欢迎使用技术文档,我们为你提供从新手到专业开发者的所有资源,你也可以通过它日益精进

位置:首页 > 技术文档 > JAVA > 新手入门 > 基础入门 > 查看文档

深入分析java中webwork的文件上传机制

点击上传按钮后,webwork的程序流如下:

step 1)进入servletdispatcher.service

public void service(httpservletrequest request, httpservletresponse response) 
throws servletexception {
........

request = wraprequest(request);
......... 
}

step2)进入servletdispatcher.wraprequest

protected httpservletrequest wraprequest(httpservletrequest request) 
throws ioexception {
........................

if (multipartrequest.ismultipart(request)) {
request = new multipartrequestwrapper(request, getsavedir(), getmaxsize());
}

return request;
}

step3)进入multipartrequestwrapper的构造方法

public multipartrequestwrapper(httpservletrequest request, string savedir, int maxsize) 
throws ioexception {
.....................

//step3.1)获取webwork.preperties配置的parser
string parser = "";

parser = configuration.getstring("webwork.multipart.parser");

// if it's not set, use pell
if (parser.equals("")) {
log.warn("property webwork.multipart.parser not set." +
" using com.opensymphony.webwork.dispatcher.multipart.pellmultipartrequest");
parser = "com.opensymphony.webwork.dispatcher.multipart.pellmultipartrequest";
}
// legacy support for old style property values
else if (parser.equals("pell")) {
parser = "com.opensymphony.webwork.dispatcher.multipart.pellmultipartrequest";
} else if (parser.equals("cos")) {
parser = "com.opensymphony.webwork.dispatcher.multipart.cosmultipartrequest";
} else if (parser.equals("jakarta")) {
parser = "com.opensymphony.webwork.dispatcher.multipart.jakartamultipartrequest";
}

//step3.2)获取后通过反射实例化parser
try {
class baseclazz = 
com.opensymphony.webwork.dispatcher.multipart.multipartrequest.class;

class clazz = class.forname(parser);

// make sure it extends multipartrequest
if (!baseclazz.isassignablefrom(clazz)) {
adderror("class '" + parser + "' does not extend multipartrequest");

return;
}

// get the constructor
constructor ctor = clazz.getdeclaredconstructor(new class[]{
class.forname("javax.servlet.http.httpservletrequest"),
java.lang.string.class, int.class
});

// build the parameter list
object[] parms = new object[]{
request, savedir, new integer(maxsize)
};

// instantiate it
multi = (multipartrequest) ctor.newinstance(parms);
.................................................
}

step4 进入jakartamultipartrequest的构造方法(在webwork配置的parser是jakarta所以进入了这个方法,如果你配置不同的parser回进入不同的parser

public jakartamultipartrequest(httpservletrequest servletrequest, string savedir, int maxsize)
throws ioexception {

//设置保存参数
diskfileupload upload = new diskfileupload();
// we must store all uploads on disk because the ww multipart api is missing streaming
// capabilities
upload.setsizethreshold(0);
upload.setsizemax(maxsize);
if (savedir != null) {
upload.setrepositorypath(savedir);
}

// parse the request
try {

/**此方法生成文件,将请求中的每个参数都生成一个
*临时文件比如upload_00000017.tmp, upload_00000018.tmp等,
*就算是form提交的参数也如此
*/
list items = upload.parserequest(servletrequest);

......................
}

执行完第四步,然后推出servletdispatcher.wraprequest,进入serviceaction方法,开始action及其拦截器的栈调用

在此过程中会删除非上传文件的临时文件,至于哪一步删除,我还没看出来,有时候很早有时候很晚,有时候甚至没有删除,我怀疑有个dameon在做这个事。

进入action和调用栈后,拦截器或action可通过如下代码访问上传的临时文件multipartrequestwrapper wrapper = (multipartrequestwrapper) req;

file doc = wrapper.getfiles("doc")[0];

从上面的分析可以看出:

1)如果你使用webwork来上传文件(在进入action栈之前不修改源码或者做一些扩展、覆盖之类的动作),在进入action栈的时候文件已经上 传,而且其文件名很难跟踪(upload_00000017.tmp,到底是00000017,0000018,或者0000022等等),毕竟有很多人 上传文件,所以临时文件名很难确定,所以如果你想知道上传的进度很难。

2)利用webwork上传文件是两次拷贝过程,webwork首先从request的输入流中将文件流输出到一个临时文件,然后你再将此临时文件拷贝到你需要指定的路径。

扫描关注微信公众号