【Struts2】(8)文件上傳和下載

一. 文件上傳的基本方法

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的文件。


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章