使用Struts1实现文件上传(一)
今天研究了一下Struts的文件上传机制,可以方便的将客户端文件上传至服务器端,感觉很方便、实用,特此记录一下。
完成文件上传功能大致需要以下几个步骤:
(1)创建用于文件上传的JSP页面;
(2)创建用于承载数据的ActionForm;
(3)创建用于处理上传的Action;
(4)配置文件上传大小;
(5)配置从web.xml文件中读取文件存放路径;
步骤一:创建用于文件上传的JSP页面
在项目中新建一个用于文件上传的JSP页面,如命名为:FileUpload.jsp,在页面的顶头处引入Struts的html标签库。
- <%@ taglib uri="http://struts.apache.org/tags-html" prefix="html" %>
<%@ taglib uri="http://struts.apache.org/tags-html" prefix="html" %>
并在页面的<body></body>标签内书写如下代码:
- <html:form enctype="multipart/form-data" action="/fileUpload" method="post">
- <html:file property="uploadFile"></html:file>
- <html:submit>Upload File</html:submit>
- </html:form>
<html:form enctype="multipart/form-data" action="/fileUpload" method="post">
<html:file property="uploadFile"></html:file>
<html:submit>Upload File</html:submit>
</html:form>
<html:form>是Struts表单,要想用此表单上传文件必须要设置 enctype 和 method 参数才行,enctype 参数用于设置该表单的编码方式,当该表单中包含了<input type = "file"> 或 <html:file> 是必须要将enctype的属性值设置为:"multiparty/form-data" ,并且要将表单的提交方式Method属性设置为"Post";在action处填入处理表单的Action访问路径。
<html:file>是Struts提供的文件上传组件,其属性property要与承载数据的ActionForm类的FormFile类型的属性保持一一对应的关系。ActionForm类中的属性书写见步骤二。
步骤二:创建用于承载数据的ActionForm
在项目中新建一个ActionForm的子类,如命名为:FileUploadForm.java,在其中新增一个FormFile类型的属性uploadFile,并设置getter、setter方法。
在Struts中,一个FormFile类型的对象对应Form表单中创送的一个文件,Struts将上传的文件信息封装金FormFile中,通过FormFile提供的方法可以方便的进行文件的操作。其实FormFile是一个接口,位于 org.apache.struts.upload.FormFile 中,它定义了操作上传文件的基本方法。
FormFile接口定义的常用方法:
(1) getFileName()/setFileName() //用于获取或设置文件名;
(2) getFileSize() / setFileSize() //用于获取或设置文件字节数;
(3) getFileData() //用于获取文件的字节数组,用于小的文件;
(4) getInputStream() //用于获取文件的输入流,用于较大的文件;
(5) destory() //销毁FromFile;
步骤三:创建用于处理上传的Action
在项目中新建一个Action的子类,如命名为:FileUploadAction.java,在其execute方法中添加处理代码。
在代码中可以看到,我们从FileUploadForm中找到了FormFile类型的属性,通过其提供的方法得到文件的信息,并将其存入服务器的磁盘中。在保存的过程中需要用到文件流的一些基本操作。
到此为止,文件的上传已经基本成功,剩下的两步为配置文件上传大小和从web.xml文件中读取文件存放路径,可以选择学习。
步骤四:配置文件上传大小
在Struts中可以配置上传文件的大小,以避免服务器的硬盘消化不良。
打开项目中WebRoot\WEB-INF\struts-config.xml ,切换至源码视图,在其中添加如下节点信息,便可以控制上传文件的大小了。
其中maxFileSize属性的单位可以是K,也可以是M或G;Struts在写 FormFile类时借助的是fileupload中的API,设置的默认大小为250M
注意:操作struts-config.xml文件时应当特别注意各个节点间的顺序,因为Struts要求配置文件的各个元素顺序有一定的要求,顺序一旦被打乱,也就意味着web容器即将进入瘫痪状态,因此在添加<controler>节点时,要将此节点添加在<action-mapping>和<message-resources>节点之间。
附:Struts-config.xml配置文件各元素的顺序列表。
步骤五:配置从web.xml文件中读取文件存放路径
在步骤三中的代码中我们已经看到,在保存文件时,我写的是一个固定的存放路径,有没有什么办法让它动态改变呢?答案是肯定的,Struts提供了一些方法可以读取web.xml中读取数据,那么我们可以把存放的路径存放在web.xml文件中,存储文件时再将路径读取出来。这样做的好处是,如果存放路径发生改变,我们只需要修改配置文件,而不需要改动代码。
打开项目WebRoot\WEB-INF\web.xml , 找到一个servlet,在该servlet的节点下添加如下代码:
要想读取此节点的信息,在处理上传文件的Action代码中加入如下代码:
到此基于Struts的文件上传操作已经基本完成。
使用Struts1实现文件上传(二)
在使用Struts1实现文件上传(一)中,我将文件保存在服务器端的硬盘里,有没有办法将其保存在Oracle10g数据库中呢?答案是肯定的,只需要对程序稍加改造就可以实现将文件保存在数据库中。用到时再将文件从数据库中还原出来供用户下载。
在数据库中保存文件的方法和保存其他基本数据类型相差不多,只是要存入即可,但是其对应的数据类型比较特殊,一般选择二进制的数据类型。Oracle10g中提供了RAW和Long RAW数据类型,这两中数据类型用于保存二进制的数据;二进制类型的好处在于当数据在不同系统之间传输时,可以不做任何数据类型的转换,方便了系统之间的操作。RAW类型的最大宽度为2000字节,而Long RAW类型的最大宽度可以达到2GB,非常适合保存图像、声音、视频等数据量较大的数据。
因此,要想将文件保存在数据库中用到时在取出来,就要完成三个步骤:
(1)新建Oracle10g数据表,在表中添加Long RAW类型的字段;
(2)在程序中将上传的文件以流的形式保存到数据库中;
(3)将文件从数据库中还原出来。
一、新建Oracle10g数据表
在Oracle10g中新建一张数据表,如命名为UploadFiles,在表中添加相应的字段;
其中FileContent便是用来存放文件的Long RAW二进制数据类型。
二、将上传文件保存在数据库
剩下的工作便是在程序中编写代码将用户上传的文件保存在数据库中了,主要的代码已经在文章“使用Struts1实现文件上传(一)”中实现,现在只需要将原来保存在文件中的部分代码替换为保存在数据库的代码即可。
当用户点击上传后就可以将文件存储在数据库中了。
三、将文件从数据库中还原出来
当用户需要用到文件时,就需要从数据中将文件查询出来,方法也很简单,看代码:
将文件从数据库中读取出来后得到的将是一个InputStream类型的对象,可以根据需要操作这个对象还原文件。
struts1文件上传和下载
FileAction
import org.apache.struts.action. * ;
import javax.servlet.http. * ;
import com.actionForm.FileActionForm;
import org.apache.struts.actions.DispatchAction;
import java.util.Date;
import java.text. * ;
import org.apache.struts.upload.FormFile;
import java.io. * ;
import java.net.URLEncoder;
import com.dao. * ;
public class FileAction extends DispatchAction {
private JDBConnection connection =new JDBConnection();
//以下方法实现文件的上传
public ActionForward upLoadFile(ActionMapping mapping, ActionForm form,
HttpServletRequest request,
HttpServletResponse response) throws
Exception {
ActionForward forward=null;
Date date = new Date();
FileActionForm fileActionForm = (FileActionForm) form;
//FormFile用于指定存取文件的类型
FormFile file = fileActionForm.getFile(); //获取当前的文件
// 获得系统的绝对路径 String dir = servlet.getServletContext().getRealPath("/image");
//我上传的文件没有放在服务器上。而是存在D:D:\\loadfile\\temp\\
String dir="D:\\loadfile\\temp\\";
int i = 0;
String type = file.getFileName();
while(i!=-1){
//找到上传文件的类型的位置,这个地方的是'.'
i = type.indexOf(".");
/**//* System.out.println(i);*/
/**//*截取上传文件的后缀名,此时得到了文件的类型*/
type = type.substring(i+1);
}
// 限制上传类型为jpg,txt,rar;
if (!type.equals("jpg") && !type.equals("txt")&& !type.equals("bmp"))
{//当上传的类型不为上述类型时,跳转到错误页面。
forward=mapping.findForward("error");
}
else
{
// 将上传时间加入文件名(这个地方的是毫秒数)
String times = String.valueOf(date.getTime());
//组合成 time.type
String fname = times + "." + type;
//InInputStream是用以从特定的资源读取字节的方法。
InputStream streamIn = file.getInputStream(); //创建读取用户上传文件的对象
//得到是字节数,即byte,我们可以直接用file.getFileSize(),也可以在创建读取对象时用streamIn.available();
// int ok=streamIn.available();
int ok=file.getFileSize();
String strFee = null;
//这个地方是处理上传的为M单位计算时,下一个是以kb,在下一个是byte;
if(ok>=1024*1024)
{
float ok1=(((float)ok)/1024f/1024f);
DecimalFormat myformat1 = new DecimalFormat("0.00");
strFee = myformat1.format(ok1)+"M";
System.out.println(strFee+"M");
}
else if(ok>1024 && ok<=1024*1024)
{
double ok2=((double)ok)/1024;
DecimalFormat myformat2=new DecimalFormat("0.00");
strFee = myformat2.format(ok2)+"kb";
System.out.println(strFee+"kb");
}
else if(ok<1024)
{
System.out.println("aaaaaaaaa");
strFee=String.valueOf(ok)+"byte";
System.out.println(strFee);
}
System.out.println( streamIn.available()+"文件大小byte");
//这个是io包下的上传文件类
File uploadFile = new File(dir); //指定上传文件的位置
if (!uploadFile.exists() || uploadFile == null) { //判断指定路径dir是否存在,不存在则创建路径
uploadFile.mkdirs();
}
//上传的路径+文件名
String path = uploadFile.getPath() + "\\" + fname;
//OutputStream用于向某个目标写入字节的抽象类,这个地方写入目标是path,通过输出流FileOutputStream去写
OutputStream streamOut = new FileOutputStream(path);
int bytesRead = 0;
byte[] buffer = new byte[8192];
//将数据读入byte数组的一部分,其中读入字节数的最大值是8192,读入的字节将存储到,buffer[0]到buffer[0+8190-1]的部分中
//streamIn.read方法返回的是实际读取字节数目.如果读到末尾则返回-1.如果bytesRead返回为0则表示没有读取任何字节。
while ((bytesRead = streamIn.read(buffer, 0, 8192)) != -1) {
//写入buffer数组的一部分,从buf[0]开始写入并写入bytesRead个字节,这个write方法将发生阻塞直至字节写入完成。
streamOut.write(buffer, 0, bytesRead);
}
// 关闭输出输入流,销毁File流。
streamOut.close();
streamIn.close();
file.destroy();
String paths=path;
System.out.println(paths);
String fileName = Chinese.toChinese(fileActionForm.getFileName()); //获取文件的名称
//String fileSize = String.valueOf(file.getFileSize());
String fileDate = DateFormat.getDateInstance().format(date);
String sql = "insert into tb_file values('" + fileName + "','" +
strFee + "','" + fileDate + "','" + paths + "')";
connection.executeUpdate(sql);
connection.closeConnection();
forward=mapping.findForward("upLoadFileResult");
}
return forward;
}
//实现文件的下载
public ActionForward downFile(ActionMapping mapping, ActionForm form,
HttpServletRequest request,
HttpServletResponse response) throws
Exception {
String path = request.getParameter("path");
System.out.println(path+"111");
BufferedInputStream bis = null;
BufferedOutputStream bos = null;
OutputStream fos = null;
InputStream fis = null;
//如果是从服务器上取就用这个获得系统的绝对路径方法。 String filepath = servlet.getServletContext().getRealPath("/" + path);
String filepath=path;
System.out.println("文件路径"+filepath);
File uploadFile = new File(filepath);
fis = new FileInputStream(uploadFile);
bis = new BufferedInputStream(fis);
fos = response.getOutputStream();
bos = new BufferedOutputStream(fos);
//这个就就是弹出下载对话框的关键代码
response.setHeader("Content-disposition",
"attachment;filename=" +
URLEncoder.encode(path, "utf-8"));
int bytesRead = 0;
//这个地方的同上传的一样。我就不多说了,都是用输入流进行先读,然后用输出流去写,唯一不同的是我用的是缓冲输入输出流
byte[] buffer = new byte[8192];
while ((bytesRead = bis.read(buffer, 0, 8192)) != -1) {
bos.write(buffer, 0, bytesRead);
}
bos.flush();
fis.close();
bis.close();
fos.close();
bos.close();
return null;
}
}
FileActionForm
import org.apache.struts.action. * ;
import org.apache.struts.upload. * ;
public class FileActionForm extends ActionForm {
private String fileName;//上传文件的名称
private String fileSize;//上传文件的大小
private String filePath;//上传文件到服务器的路径
private String fileDate;//上传文件的日期
private FormFile file;//上传文件
public String getFileName() {
return fileName;
}
public FormFile getFile() {
return file;
}
public String getFileSize() {
return fileSize;
}
public String getFilePath() {
return filePath;
}
public String getFileDate() {
return fileDate;
}
public void setFileName(String fileName) {
this.fileName = fileName;
}
public void setFile(FormFile file) {
this.file = file;
}
public void setFileSize(String fileSize) {
this.fileSize = fileSize;
}
public void setFilePath(String filePath) {
this.filePath = filePath;
}
public void setFileDate(String fileDate) {
this.fileDate = fileDate;
}
}
index.jsp
< tr >
< td width ="115" rowspan ="4" align ="center" >< img src ="<%=form.getFilePath()%>" width ="100" height ="100" ></ td >
< td width ="133" align ="center" > 图片名称: <% = form.getFileName() %> </ td >
</ tr >
< tr align ="center" >
< td > 图片大小: <% = form.getFileSize() %> </ td >
</ tr >
< tr align ="center" >
< td > 上传日期: <% = form.getFileDate() %> </ td >
</ tr >
< tr >
< td align ="center" >< a href ="fileAction.do?method=downFile&path=<%=form.getFilePath()%>" >< img src ="priture/bottond.jpg" ></ a >
</ td >
</ tr >
</ table >
< html:form action ="fileAction.do?method=upLoadFile" enctype ="multipart/form-data" onsubmit ="return Mycheck()" >
< table height ="52" border ="0" align ="center" cellpadding ="0" cellspacing ="0" >
< tr align ="center" >
< td width ="60" height ="26" > 图片名称: </ td >
< td width ="160" > < html:text property ="fileName" /> </ td >
< td width ="60" > 图片路径: </ td >
< td width ="198" > < html:file property ="file" /> </ td >
</ tr >
< tr align ="right" >
< td height ="26" colspan ="4" > < html:submit > 上传 </ html:submit > </ td >
</ tr >
</ table >
</ html:form >
struts-config.xml
<! DOCTYPE struts-config PUBLIC "-//Apache Software Foundation//DTD Struts Configuration 1.2//EN" "http://struts.apache.org/dtds/struts-config_1_2.dtd" >
< struts-config >
< form-beans >
< form-bean name ="fileActionForm" type ="com.actionForm.FileActionForm" />
</ form-beans >
< action-mappings >
< action name ="fileActionForm" parameter ="method" path ="/fileAction" scope ="request" type ="com.action.FileAction" validate ="true" >
< forward name ="upLoadFileResult" path ="/result.jsp" />
< forward name ="error" path ="/fail.jsp" ></ forward >
</ action >
</ action-mappings >
< message-resources parameter ="ApplicationResources" />
</ struts-config