场景描述:
文件上传下载是应用当中常见的功能,本例实现主页面不刷新文件上传,和打包多文件下载功能,加强了用户操作上的连贯性和速度感。
实例实现:
界面:
1:
2(上传):
3(下载):
界面组成元素:
实现步骤:
- 建立dsFile(Dataset)为我们的存放数据,本例通过viewmodel实现类的onload事件为Dataset提供数据代码如下:
可以看到我们判断进行加载数据的Dataset是我们定义的dsFile时我们将数据注入进来。
public static List lstFiles = new ArrayList();
protected void doLoadData(ViewDataset dataset) throws Exception {
// Add your code here
super.doLoadData(dataset);
if ("dsFile".equals(dataset.getId())) {
dataset.fromDO(this.lstFiles);
}
}
*注:在本例中定义了一个静态的ArrayList来为Dataset提供数据完全是为了本例可以脱离数据库而更好演示,我们完全可以通过数据库或者其他方式提供数据。 - 建立一个tblFileInfo(DataTable)为我们展示dsFile中的数据。
- 建立frmFileInfo(AutoForm)在上传文件时,填写所要上传文件的详细信息。由于展现和功能的需要我们建立subwinAddFile(Subwindow)、btnBrowse(Button)、btnUpload(Button)、btnCancel(Button)、fileInput1(fileEditor),为了更好的展现我们将btnBrowse(Button)和fileInput1(fileEditor)放到div中添加到frmFileInfo(AutoForm)中。这样不仅仅为了更好的展现,而且为我们的多附件同时上传提供了可能性。
frmFileInfo中filePath(TextEditor)的onActive事件代码如下:
var pn=editor.parentNode; |
调用Function中的方法:
/** |
Jsp中布局如下:
<form id="uploadForm" name="uploadForm" target="upload" method="post" enctype="multipart/form-data" action="<%=request.getContextPath()%>/uploadFile.upload.d" style="padding:0px;margin:0px;"> |
fileInput1的class如下:
.FileInput{ |
fileInput1的onchange事件中调用Function方法如下:
/** |
- 使用form将frmFileInfo包含起来,这样做主要是为了当我们提交表单上传文件时可以将frmFileInfo中填写的关于上传文件的信息一起提交到服务器端。uploadForm(form)的action为"/Sample-Project/uploadFile.upload.d",需要我们在Dorado的mapping中进行配置,如下:
<controller name="uploadFile" clazz="view.UploadController">
<action name="upload">
<forward name="success" path="/upload.jsp" contextRelative="false" />
</action>
</controller>
UploadController类代码如下:此代码中包含存储上传文件方法storeUploadFile、下载文件方法outputDownloadFile、文件打包方法createFileZIP。package view;
import java.io.BufferedInputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.HashMap;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.sound.midi.SysexMessage;
import org.apache.commons.fileupload.DiskFileUpload;
import org.apache.commons.fileupload.FileItem;
import org.apache.commons.lang.SystemUtils;
import org.apache.tools.zip.ZipEntry;
import org.apache.tools.zip.ZipOutputStream;
import com.bstek.dorado.action.Action;
import com.bstek.dorado.action.mapping.ActionForward;
import com.bstek.dorado.biz.FileController;
import com.bstek.dorado.common.UserConfig;
import com.bstek.dorado.data.db.DBStatement;
import com.bstek.dorado.utils.*;
import com.bstek.dorado.common.*;
/**
* fileController
* @author Gavin
* @date 2008-9-5
*/
public class UploadController extends FileController {
/**
*
*/
private static final long serialVersionUID = 1L;
private static final String FOMART = ".zip";
private String FILEPATH=null;
/**
* 设定 DiskFileUpload 的相关属性.
* <p>
* 关于DiskFileUpload, 可以到www.apache.org/commons查找FileUpload的文档
* </p>
*
* @param request
* HttpServletRequest
* @param fileUpload
* DiskFileUpload
*/
protected void initFileUpload(HttpServletRequest request,
DiskFileUpload fileUpload) {
fileUpload.setSizeMax(UserConfig.getInt("file_max_size")); // 设定上传文件大小
}
/**
* 取得存放上传文件的工作目录
*
* @param request
* HttpServletRequest
* @param parameters
* MetaData
* @return String
*/
protected File getUploadWorkDirectory(HttpServletRequest request,
MetaData parameters) {
System.out.println(request.getSession().getServletContext()
.getRealPath("/"));
return new File(UserConfig.getString("file_path"));
}
/**
* 取得存储上传文件的文件名
*
* @param request
* HttpServletRequest
* @param fileName
* String
* @param parameters
* MetaData
* @return String
*/
protected String getStoreFileName(HttpServletRequest request,
String fileName, MetaData parameters) {
// 注意: 此处的代码仅用于演示上传文件的处理方式。
// 以系统时间戳为文件命名并不能有效的避免文件重名!
int pos = fileName.lastIndexOf(".");
String extName;
if (pos > 0) {
extName = fileName.substring(pos);
} else {
extName = "";
}
String fullFileName = System.currentTimeMillis() + extName;
return fullFileName;
}
/**
* 存储已经上传的文件
*
* @param request
* HttpServletRequest
* @param fileItem
* String
* @param storeFile
* String
* @param parameters
* MetaData
* @throws Exception
*/
@SuppressWarnings("unchecked")
protected void storeUploadFile(HttpServletRequest request,
FileItem fileItem, File storeFile, MetaData parameters)
throws Exception {
super.storeUploadFile(request, fileItem, storeFile, parameters);
String filePath = UserConfig.getString("file_path")
+ storeFile.getName();
String fileName = parameters.getString("fileName");
if (fileName == null"".equals(fileName.trim())) {
fileName = this.getFileName(fileItem.getName());
} else {
fileName = new String(fileName.getBytes("ISO8859-1"), "UTF-8");
}
String fileRemark = new String(parameters.getString("fileRemark")
.getBytes("ISO8859-1"), "UTF-8");
Map file=new HashMap();
file.put("fileRemark", fileRemark);
file.put("fileName", fileName);
file.put("filePath", filePath);
file.put("createDate", new Date());
FileUploadViewModel.lstFiles.add(file);
/**
* 此处可进行文件信息持久化
DBStatement dbst = new DBStatement();
dbst.setSql(DBStatement.INSERT, "Gfile");
dbst.parameters().setValue("fileRemark", fileRemark);
dbst.parameters().setValue("fileName", fileName);
dbst.parameters().setValue("filePath", filePath);
dbst.parameters().setDate("createDate", new Date());
dbst.execute();
*/
}
/**
* 取得将要下载的文件的文件名
*
* @param request
* HttpServletRequest
* @return String
*/
protected String getDownLoadFileName(HttpServletRequest request) {
return "文件下载"
+ System.currentTimeMillis() + FOMART;
}
protected String getFileName(String fileName) throws Exception {
fileName = fileName.substring(fileName.lastIndexOf("
") + 1);
fileName = fileName.substring(0, fileName.lastIndexOf("."));
return fileName;
}
@Override
protected InputStream getDownloadFileInputStream(HttpServletRequest request)
throws Exception {
this.FILEPATH=createFileZIP(request);
return new FileInputStream(this.FILEPATH);
}
@Override
protected void outputDownloadFile(HttpServletRequest arg0,
HttpServletResponse arg1) throws IOException, Exception {
super.outputDownloadFile(arg0, arg1);
if(this.FILEPATH!=null&&UserConfig.getBoolean("file_delete")){
File file=new File(this.FILEPATH);
file.delete();
}
}
/**
* 生成文件压缩包,并返回压缩包地址
* @param request
* @param response
* @return
* @throws IOException
*/
private String createFileZIP(HttpServletRequest request) throws IOException{
List<File> lstFile = new ArrayList<File>();
String filePaths = request.getParameter("fp");
String fileNames = request.getParameter("fn");
String[] strFileName = fileNames.split(",");
String[] strFilePath = filePaths.split(",");
int sign;
File file = new File(UserConfig.getString("file_path"),this.getDownLoadFileName(request) );
ZipOutputStream outputStream = new ZipOutputStream(
new FileOutputStream(file));
for (int i = 0; i < strFilePath.length; i++) {
String filepath = strFilePath[i];
String filename = strFileName[i] + filepath.substring(filepath.lastIndexOf("."));
File tempFile=new File(filepath);
ZipEntry entry = new ZipEntry(filename);
outputStream.putNextEntry(entry);
BufferedInputStream binputStream = new BufferedInputStream(
new FileInputStream(tempFile));
byte[] data = new byte[1024];
sign = binputStream.read(data);
while (sign != -1) {
outputStream.write(data, 0, sign);
sign = binputStream.read(data);
}
outputStream.closeEntry();
binputStream.close();
}
outputStream.close();
return file.getPath();
}
}
如果上传成功将跳转到upload.jsp,代码如下:调用file-upload.jsp中Function的afterUpload方法更新数据,代码如下:<%@ page contentType="text/html; charset=UTF-8" %>
<html>
<head>
<title></title>
<script language="JavaScript">
/*var filePath="<%=request.getAttribute("filePath")%>";*/
if(parent) parent.afterUpload();
</script>
</head>
<body>
</body>
</html>/**
* 设置上传完成后更新dataset
*/
function afterUpload(){
dsFile.flushData();
subwinAddFile.hide();
} - 在jsp中添加iframe如下:
将iframe隐藏,name与上面添加的form的target一致,uploadForm(form)的提交动作将在iframe中进行,这样上传文件时主页面不刷新功能基本实现。
<iframe name="upload" style="display:none" ></iframe>
- 建立菜单menuTop(menu)和menubarTop(menubar)。
代码如下:
<Control type="Menu" id="menuTop"> |
调用Function中方法:
/** |
- 建立cmdFileDownload(RequestCommand)和cmdFileDelete(UpdateCommand)。
cmdFileDownload代码如下:
<Control method="post" id="cmdFileDownload" type="RequestCommand"> |
cmdFileDelete代码如下:
<Control id="cmdFileDelete" type="UpdateCommand" method="deleteFile" async="true"> |
Viewmodel中的deleteFile方法代码如下:
public void deleteFile(ParameterSet parameters, ParameterSet outparameters) |
*注:如果输出参数key为$message,前台将以弹出框形式将value显示出来。
延伸思路:
正如上文所说,我们仍然可以将本例改造成多文件上传,每添加一个文件就动态生成fileEditor,后台代码也需要进行修改,如果你有兴趣可以尝试一下。
Attachments:



