【Struts2】(8)文件上传和下载
2015-12-16 16:53
567 查看
一. 文件上传的基本方法
1. 最简单的上传文件
我们新建一个Action类:public class UploadAction { private File myFile; public File getMyFile() { return myFile; } public void setMyFile(File myFile) { this.myFile = myFile; } public String upload() { try { FileUtils.copyFile(myFile, new File("d:/temp.jpg")); } catch (IOException e) { e.printStackTrace(); } return "success"; } }使用了FileUtils.copyFile将一个文件复制到另一个文件。
然后配置struts文件和对象的jsp文件:
<struts> <include file="common.xml"></include> <package name="basicstruts2" extends="common" namespace="/test"> <action name="upload" class="com.thr.struts2.action.UploadAction"> <result>/upload_success.jsp</result> </action> </package> </struts>
<body> <form action="/web/test/upload.action" enctype="multipart/form-data" method="post"> 选择文件:<input name="myFile" type="file"/><br /> <input type="submit" name="method:upload" value="上传" /> </form> </body>运行,选择一个文件之后点击提交就可以是上传文件了。
2. 获取文件名
如果我们想获取源文件相关的信息,例如文件名等,就需要这样子修改Action文件:public class UploadAction { private File myFile; private String myFileFileName; private String myFileContentType; public File getMyFile() { return myFile; } public void setMyFile(File myFile) { this.myFile = myFile; } public String getMyFileFileName() { return myFileFileName; } public void setMyFileFileName(String myFileFileName) { this.myFileFileName = myFileFileName; } public String getMyFileContentType() { return myFileContentType; } public void setMyFileContentType(String myFileContentType) { this.myFileContentType = myFileContentType; } public String upload() { try { System.out.println("文件名:" + myFile.getName()); System.out.println(myFileFileName); System.out.println(myFileContentType); FileUtils.copyFile(myFile, new File("d:/" + myFileFileName)); } catch (IOException e) { e.printStackTrace(); } return "success"; } }注意新创建的两个String变量,一个在myFile后面加FileName,另一个是在后面加ContentType,这两个变量一个是用来获取文件名,另一个是用来指定处理文件类型的,这样在传输文件的时候就可以按照原有的文件名进行上传了。
3. 上传到自己的web路径
可以使用FileUtils.copyFile(myFile, new File(ServletActionContext.getServletContext() .getRealPath("/upload/" + "/" + myFileFileName)));来上传到自己的空间下,这里在upload目录后又跟了一个"/"是因为它将/upload/整体解析为一个目录了,所以要在加一个斜杠。
为了避免上传时会遇到报错,还可以加入下面两个常量:
<constant name="struts.multipart.saveDir" value="D:/web/temp"></constant> <constant name="struts.multipart.maxSize" value="80000000"></constant>第一个是用来指定上传保存的临时目录,第二是允许上传文件的最大容量。
二. 上传文件至数据库
1. 以文件转换成字节数组格式上传至数据库
我们增加一个方法:public String upload2() { Connection conn = DB.getConnection(); String sql = "insert into t_user(id, my_file) values(?, ?)"; try { PreparedStatement ps = conn.prepareStatement(sql); ps.setInt(1, 12); ps.setBytes(2, FileUtils.readFileToByteArray(myFile)); ps.executeUpdate(); } catch (SQLException e) { e.printStackTrace(); } catch (IOException e) { e.printStackTrace(); } DB.closeConnection(conn); return "success"; }使用FileUtils的readFileToByteArray方法可以将文件类型转换为字节数组类型,然后插入到数据库。
2. 以字节数组转换器保存至数据库
要直接将byte数组存至数据库,就要写一个转换器:public class FileConverter extends DefaultTypeConverter { @Override public Object convertValue(Object arg0, Class arg1) { if (arg0 instanceof File[]) { try { byte[] bytes = FileUtils .readFileToByteArray(((File[]) arg0)[0]); return bytes; } catch (IOException e) { e.printStackTrace(); } } throw new RuntimeException("不是文件类型,无法转换!"); } }配置和之前配转化器一样,穿件UploadAction-conversion.properties:
myBytes=com.thr.struts2.converter.FileConverter在UploadAction中创建myBytes成员变量,生成set和get方法:
public String upload3() { Connection conn = DB.getConnection(); String sql = "insert into t_user(id, my_file) values(?, ?)"; try { PreparedStatement ps = conn.prepareStatement(sql); ps.setInt(1, 15); ps.setBytes(2, myBytes); ps.executeUpdate(); } catch (SQLException e) { e.printStackTrace(); } DB.closeConnection(conn); return "success"; }记得修改jsp页面的变量名为myBytes,这样就可以直接以byte数组存入数据库了。
三. 复杂参数传递和多文件上传
1. 复杂参数传递
新写一个CollectionAciton类,里面包括了一个List和一个Map:public class CollectionAction { private List<Contact> contacts; private Map<String, Contact> contactsMap; public List<Contact> getContacts() { return contacts; } public void setContacts(List<Contact> contacts) { this.contacts = contacts; } public Map<String, Contact> getContactsMap() { return contactsMap; } public void setContactsMap(Map<String, Contact> contactsMap) { this.contactsMap = contactsMap; } public String execute() { return "success"; } }里面装的类型就是我们之前的Contact类。
配置struts文件,写一个jsp文件用来显示上传内容:
<form action="/web/test/collection.action" enctype="multipart/form-data" method="post"> List:<br /> Contact:<br /> qq:<input name="contacts[0].qq" />, tel:<input name="contacts[0].tel" />, phone:<input name="contacts[0].phone" />,<br /> Contact2:<br /> qq:<input name="contacts[1].qq" />, tel:<input name="contacts[1].tel" />, phone:<input name="contacts[1].phone" />,<br /> Map:<br /> Contact:<br /> qq:<input name="contactsMap['contact'].qq" />, tel:<input name="contactsMap'contact'].tel" />, phone:<input name="contactsMap'contact'].phone" />,<br /> Contact2:<br /> qq:<input name="contactsMap['contact2'].qq" />, tel:<input name="contactsMap['contact2'].tel" />, phone:<input name="contactsMap['contact2'].phone" />,<br /> <input type="submit" value="上传" /> </form>通过这个文件,我们看到了如果使用OGNL表达式来传递复杂的参数。
2. 多文件上传
想要实现多文件上传,只需在jsp页面中添加多个input就可以了:<form action="/web/test/upload.action" enctype="multipart/form-data" method="post"> 选择文件1:<input name="multiFile" type="file"/><br /> 选择文件2:<input name="multiFile" type="file"/><br /> <input type="submit" name="method:multiUpload" value="上传" /> </form>然后在Action中指定我们的变量:
private File[] multiFile; private String[] multiFileFileName; private String[] multiFileContentType;这样子就可以获取我们上传的文件信息啦。
四. 文件下载
我们先修改一下数据库增加varchar类型的fileName和contentType类型。我们上传几个文件到数据库。创建一个用来下载文件的Action:
public class DownloadAction { private InputStream stream; private int id; public int getId() { return id; } public void setId(int id) { this.id = id; } public InputStream getStream() { InputStream inputStream = null; Connection conn = DB.getConnection(); String sql = "select myFile, fileName, contentType from t_user where id=?"; try { PreparedStatement ps = conn.prepareStatement(sql); ps.setInt(1, id); ResultSet rs = ps.executeQuery(); rs.next(); inputStream = rs.getBinaryStream("myFile"); ActionContext.getContext() .put("fileName", rs.getString("fileName")); ActionContext.getContext().put("contentType", rs.getString("contentType")); } catch (SQLException e) { e.printStackTrace(); } DB.closeConnection(conn); return inputStream; } public String execute() { return "success"; } }id用来接收页面上传过来的id,我们将文件名和文件类型保存到了ActionContext中,方便在配置文件中动态读取。
然后配置struts文件:
<action name="download" class="com.thr.struts2.action.DownloadAction"> <result type="stream"> <param name="contentType">%{#contentType}</param> <param name="inputName">stream</param> <param name="contentDisposition">attachment;filename="%{#fileName}"</param> </result> </action>最后写下载页面:
<body> <a href="/web/test/download.action?id=16">下载id16</a><br /> <a href="/web/test/download.action?id=17">下载id17</a><br /> <a href="/web/test/download.action?id=18">下载id18</a><br /> </body>id=16、17、18对应我们数据库中保存的3个id的文件。
相关文章推荐
- Spring中Quartz的配置
- Plus One leetcode java
- 详解Java解析XML的四种方法—DOM/SAX/jdom/dom4j
- Java API —— JDK5新特性
- my eclipse 删除项目时报这个错,An exception has been caught while processi
- struts2_06 struts2补充,值栈,属性驱动与模型驱动
- JAVA Sokcet(服务端)连接WebSocket个人总结
- 老李分享:JAVA性能监控工具
- 老李分享:《Java Performance》笔记2——JVM命令行选项及垃圾收集日志解析 2
- 老李分享:《Java Performance》笔记2——JVM命令行选项及垃圾收集日志解析 1
- struts_05 各种验证器,ognl表达式,struts2常用标签,防止表单重复提交,jfreeChart插件的运用
- 老李分享:《Java Performance》笔记1——性能分析基础 2
- 老李分享:《Java Performance》笔记1——性能分析基础 1
- Java多线程总结(4)— 线程范围内数据操作的隔离及ThreadLocal类
- struts2_04 常见servlet对象的获取,文件上传
- struts2_03 自定义类型转换器 拦截器
- Spring下面的@Transactional注解标志的讲解
- struts2_02
- struts2_01
- Java获取当前日期的前一个月,前一天的时间