您的位置:首页 > 编程语言 > Java开发

【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的文件。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: