Struts2框架通过对Common-FileUpload框架进行封装实现文件上传,主要包含两个jar包:commons-io.jar和commons-fileupload.jar
第一步:完成文件上传的要求
- 表单提交方式使用post(因为get方式会有地址长度限制)
- form标签的enctype属性值,修改为multipart/form-data(该编码格式会以二进制流方式处理表单)
- 在表单中增加文件上传项,<input type="file" name="upload"/>
第二步:在Action中得到上传文件和文件名
在action中定义成员变量,并生成set/get方法。注意:File变量的名是表单中文件上传项的name值,文件名也有特定格式
//文件上传 private File upload; //文件上传名(固定格式)文件变量名+FileName private String uploadFileName; public File getUpload() { return upload; } public void setUpload(File upload) { this.upload = upload; } public String getUploadFileName() { return uploadFileName; } public void setUploadFileName(String uploadFileName) { this.uploadFileName = uploadFileName; }
第三步:在Action中实际添加的方法中编写代码
这里是上传到D:abc这个路径,并且使用了FileUtils类,不要导错包
import org.apache.commons.io.FileUtils;
if(upload!=null){ File newFile=new File("D:\abc"+File.separatorChar+uploadFileName); FileUtils.copyFile(upload, newFile); }
当然,也可以使用Java的IO操作
要导入的包:
import java.io.FileInputStream; import java.io.FileOutputStream; import java.io.InputStream; import java.io.OutputStream;
操作代码:
if(upload!=null){ InputStream is=new FileInputStream(getUpload()); //根据上传的文件得到输入流 OutputStream os=new FileOutputStream("D:\abc"+File.separatorChar+uploadFileName);//指定输出位置 byte buffer[]=new byte[1024]; int count=0; while((count=is.read(buffer))!=-1){ os.write(buffer,0,count); //把文件写到指定位置的文件中 } os.close(); is.close(); }
存在的问题:
struts2文件上传的默认大小是2MB,超过该大小会报异常,浏览器会显示404的错误
解决办法是:在struts.xml文件中修改属性,进行自定义文件上传大小
加上下面这句话就可以了,value值是以字节为单位的
<!-- 设置文件上传大小 --> <constant name="struts.multipart.maxSize" value="209715200"></constant>
但是有可能上传超过我们设置大小的时候,还是会抛异常。可以在struts.xml文件的action配置中增加一个input返回结果,转跳到一个页面,用于提示或者显示失败
<result name="input">/jsp/error.jsp</result>
多文件上传
页面:
值得注意的是几个<s:file>标签的名字必须相同,这样取值的时候会把它们对应的值都封装到List中
<s:form action="" method="post" enctype="multipart/form-data"> <s:file name="upload" label="上传文件一"/> <s:file name="upload" label="上传文件二"/> <s:file name="upload" label="上传文件三"/> <s:submit value="上传"/> </s:form>
效果:
Action中的编码:
还是生成set/get方法,只不过要用List封装
private List<File> upload; private List<String> uploadFileName; public List<File> getUpload() { return upload; } public void setUpload(List<File> upload) { this.upload = upload; } public List<String> getUploadFileName() { return uploadFileName; } public void setUploadFileName(List<String> uploadFileName) { this.uploadFileName = uploadFileName; }
在具体的操作方法中添加
if(upload!=null){ for(int i=0;i<upload.size();i++){ File newFile=new File("D:\abc"+File.separatorChar+uploadFileName.get(i)); FileUtils.copyFile(upload.get(i), newFile); } }
上传图片文件到数据库
现将MySQL数据库的相应字段设置为Blob类型(用于存储二进制数据),MySQL中,BLOB是个类型系列,包括:TinyBlob、Blob、MediumBlob、LongBlob,这几个类型之间的唯一区别是在存储文件的最大大小上不同
MySQL的四种BLOB类型
类型 大小(单位:字节)
TinyBlob 最大 255
Blob 最大 65K
MediumBlob 最大 16M
LongBlob 最大 4G
作为一张图片来说,65k左右应该够用,不过现在很多图片的分辨率较高,也有几兆大小的,那时就换用MediumBlob
数据库字段完成之后,就开始编写代码:
这里我使用Java的I/O操作,将图片转换为二进制
File file = getPicture2(); //Struts2文件上传 byte[] buffer = null; if (file != null) { //判断文件是否为空 FileInputStream fis = new FileInputStream(file); buffer = new byte[fis.available()]; fis.read(buffer); //二进制流写入buffer fis.close(); } book.setPicture2(buffer); //再将buffer给Bean
最后只要在Dao层完成相应的数据库操作就好了
文件下载
对于西欧字符命名的文件,其下载直接在代码中用超链接指向要下载的文件即可:
<a href="image/example.jpg">下载</a>
而如果下载的文件中有非西欧字符(如中文)命名的,就不可以这样了,用上面的方法就会报错。Struts2提供的解决办法是:在页面实现一个超链接,它指向一个action请求,然后在对应的Action类中进行一些属性的处理后返回"SUCCESS",最后在action配置文件中的result中用param配置参数完成文件的下载。这些属性如下:
- inputName:用于指定Action类中作为输入流的属性名
- contentType:用于指定文件的类型(如果指定该参数,但下载一个图片类型时,会直接在浏览器中打开,若不配置,则会直接下载到硬盘)
- contentDisposition:该参数用于指定下载文件在客户端上的一些属性(如下载时默认的文件名,注意该文件名最后为西欧字符,如果为中文会出现乱码,用户在下载时可以自行更改)
- bufferSize:用于指定下载文件时的缓冲区
例如在WebRoot下建立一个image文件夹,其中放置一个文件“图片.png”
页面:
<html> <head> <title>文件下载</title> </head> <body> <a href="download.action">下载</a> </body> </html>
编写Action类(值得注意的是getTargetFile()这个方法与配置文件中的inputName属性值相对应):
package org.action; import java.io.InputStream; import org.apache.struts2.ServletActionContext; import com.opensymphony.xwork2.ActionSupport; public class DownloadAction extends ActionSupport { private String downloadFile; //生成downloadFile的set/get方法 public String getDownloadFile() { return downloadFile; //需要下载的文件路径 } public void setDownloadFile(String downloadFile) { //其值有action配置文件传入 this.downloadFile = downloadFile; } public InputStream getTargetFile(){ //根据文件名生成它的输入流 return ServletActionContext.getServletContext().getResourceAsStream(downloadFile); } public String execute() throws Exception { return SUCCESS; } }
配置struts.xml文件:
<?xml version="1.0" encoding="UTF-8" ?> <!DOCTYPE struts PUBLIC "-//Apache Software Foundation//DTD Struts Configuration 2.0//EN" "http://struts.apache.org/dtds/struts-2.0.dtd"> <struts> <package name="default" extends="struts-default"> <action name="download" class="org.action.DownloadAction"> <!-- 指定下载文件的路径 --> <param name="downloadFile">/image图片载.png</param> <!--type="stream"指定以流的方式返回--> <result name="success" type="stream"> <!-- 输入流名字,对应Action类中的getTargetfile()方法 --> <param name="inputName">targetFile</param> <!-- 设置下载文件的文件名 --> <param name="contentDisposition">filename="example.zip"</param> <!-- 设置下载文件缓存区大小 --> <param name="bufferSize">4096</param> </result> </action> </package> </struts>