文件上传分为两部分,一部分是从客户端上传文件到服务器上的临时文件,另一部分是从服务器的临时目录拷贝到程序中定义的目标目录。
这两部分所占文件的上传时间的百分比无法准确确定,我在文件中将第一部分耗时定义为所占时间的80%,第二部分定义为总时间的20%。
1、在struts2的配置文件struts.xml文件中声明struts.multipart.parser
<struts>
<constant name="struts.objectFactory" value="spring" />
<constant name="struts.multipart.maxSize" value="100000000000"/>
<!-- 重新指定request封装类 -->
<bean type="org.apache.struts2.dispatcher.multipart.MultiPartRequest" name="requestParser"
class="com.web.Servlet.MyMultiPartRequest" />
<constant name="struts.multipart.parser" value="requestParser" />
。。。。。。。。。。
</struts>
2、根据声明定义自己的org.apache.struts2.dispatcher.multipart.MultiPartRequest继承类
我在struts.xml配置文件中定义的是com.web.Servlet.MyMultiPartRequest
MyMultiPartRequest类中内容可以直接拷贝JakartaMultiPartRequest类
(JakartaMultiPartRequest类位于structs2-core.jar的包中,我本人用的是struts2-core-2.3.15.1.jar包,可在网上查找源码拷贝到你的类中)
MyMultiPartRequest类拷贝JakartaMultiPartRequest类内容后需要有两次改动:
一是在原parseRequest方法中加入监听器
private List<FileItem> parseRequest(HttpServletRequest servletRequest, String saveDir) throws FileUploadException {
DiskFileItemFactory fac = createDiskFileItemFactory(saveDir);
ServletFileUpload upload = new ServletFileUpload(fac);
upload.setSizeMax(maxSize);
/*自己新建监听器*/
FileUploadListener progressListener = new FileUploadListener(servletRequest);
upload.setProgressListener(progressListener);//添加自己的监听器
return upload.parseRequest(createRequestContext(servletRequest));
}
二是cleanUp代码中做移除操作(理论上本处应该不用修改,但实际上我的程序运行时没有清楚上次信息,不知道是什么原因)
public void cleanUp() {
Set<String> names = files.keySet();
for (String name : names) {
List<FileItem> items = files.get(name);
for (FileItem item : items) {
if (LOG.isDebugEnabled()) {
String msg = LocalizedTextUtil.findText(this.getClass(), "struts.messages.removing.file",
Locale.ENGLISH, "no.message.found", new Object[]{name, item});
LOG.debug(msg);
}
if (!item.isInMemory()) {
item.delete();
files.remove(name); //添加的代码,不知道为什么程序没有自动移除上个文件信息,我只能自己处理了
}
}
}
}
3、写文件的监听器FileUploadListener
public class FileUploadListener implements ProgressListener{
private HttpSession session;
public FileUploadListener(HttpServletRequest request) {
session = request.getSession();
Map<String, String> map = new HashMap<String, String>();
session.setAttribute("state", map);
}
@Override
public void update(long readedBytes, long totalBytes, int currentItem) {
@SuppressWarnings("unchecked")
Map<String, String> map = (Map<String, String>)session.getAttribute("state");
double readed = Double.valueOf(readedBytes);
if(totalBytes < 0) { //当文件过大时,总字节数会变为负1,因为无法取到最大值,我私自的将总字节设为5G
totalBytes = 5000000000l;
}
if(totalBytes < readedBytes) { //当字节数大于5G时,我取当前字节数为总字节数
totalBytes = readedBytes;
}
double total = Double.valueOf(totalBytes);
map.put("result", String.valueOf((int)(readed / total * 80))); //我粗略的将文件上传到临时文件比例定义在80%
}
}
4、文件上传action
public class ImageManagementAction {
public void upload() {
Map<String, String> map = PropertiesUtils.getPropertiesMap(
"image.properties", PropertiesUtils.IMAGE_MAP);
String path = map.get("path");
InputStream is = null;
BufferedInputStream bin = null;
OutputStream os = null;
BufferedOutputStream bout = null;
HttpSession session = getSession();
Admin admin=(Admin) super.getCurrentLoginUser();
@SuppressWarnings("unchecked")
Map<String, String> stateMap = (Map<String, String>)session.getAttribute("state");
try {
is = new FileInputStream(file);
bin = new BufferedInputStream(is);
os = new FileOutputStream(path + fileFileName);
bout = new BufferedOutputStream(os);
byte buffer[] = new byte[8192];
int count = 0;
BigDecimal total = new BigDecimal(file.length());
BigDecimal readed = new BigDecimal(0);
while ((count = bin.read(buffer)) > 0) {
bout.write(buffer, 0, count);
readed = readed.add(new BigDecimal(count));
BigDecimal percent1 = readed.divide(total, 2, BigDecimal.ROUND_DOWN).multiply(new BigDecimal(20));
BigDecimal percent2 = new BigDecimal(80);
String result = (percent1.add(percent2)).intValue() + "";
stateMap.put("result", Integer.valueOf(result).toString());
}
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
} finally {
try {
bout.close();
os.close();
bin.close();
is.close();
} catch (IOException e) {
e.printStackTrace();
}
}
HttpServletResponse response = ServletActionContext.getResponse();
response.setContentType("text/html");
try {
response.getWriter().write("{success:true}");
} catch (IOException e) {
e.printStackTrace();
}
}
public void waitForUpload() {
HttpSession session = getSession();
@SuppressWarnings("unchecked")
Map<String, String> map = (Map<String, String>)session.getAttribute("state");
String result = map.get("result");
fillActionResult((Object)result);
}
}
其中upload方法是文件上传的方法,waitForUpload方法是定时读取文件进度的方法。
5、ext文件
var formUpload = new Ext.form.FormPanel({
fileUpload:true,
defaultType: 'textfield',
items: [{
xtype: 'filefield',
id: 'form-file',
fieldLabel: ‘image’,
labelAlign: 'right',
name: 'file',
buttonText: '浏览',
anchor: '90%',
allowBlank: false,
msgTarget: 'side',
labelWidth: 50
}]
}); //formUpload end
var myVar = null;
function waitForUpload(fileName) {
Ext.Ajax.request({
url: path+'/../image/image!waitForUpload.action',
params: {
"fileName": fileName
},
success: function(response){
var json = Ext.decode(response.responseText);
if(json.success){
Ext.MessageBox.updateProgress(json.resultObject / 100, json.resultObject + '%');
}
}
});
}
var winUpload = new Ext.Window({
title: 'title',
width: 400,
height:110,
minWidth: 300,
minHeight: 100,
layout: 'fit',
constrain : true,
plain:true,
bodyStyle:'padding:5px;',
buttonAlign:'center',
items: formUpload,
closable:false,
modal:true,
tools:[{
type:'close',
handler:function(){
winUpload.hide();
}
}],
buttons: [{
text: i18n._('upload'),
handler: function() {
if(formUpload.form.isValid()){
var fileName = Ext.getCmp('form-file').getValue();
winUpload.hide();
formUpload.getForm().submit({
url: path+'/../image/upload!upload.action',
success: function(form, action){
clearInterval(myVar);
Ext.MessageBox.updateProgress(0, '0%');
},
failure: function(form, action){
Ext.Msg.alert('Error', action.result.msg);
}
});
Ext.MessageBox.show({
title: 'upload',
width:240,
progress:true,
closable:false
});
myVar=setInterval(function(){waitForUpload(fileName)},1000);
}
}
},{
text: 'cancel',
handler:function(){winUpload.hide();}
}]
}); //winUpload end