文件上傳的原理:css
表單元素的enctype屬性指定的是表單數據的編碼方式,該屬性有3個值:html
1) application/x-www-form-urlencoded:這是默認編碼方式,它只處理表單域裏的value屬性值,採用這種編碼方式的表單會將表單域的java
值處理成URL編碼方式。web
2) multipart/form-data:這種編碼方式的表單會以二進制流的方式來處理表單數據,這種編碼方式會把文件域指定文件的內容也封裝到數據庫
請求參數裏。apache
3) text/plain:這種方式主要適用於直接經過表單發送郵件的方式。數組
文件上傳是web應用常常用到的一個知識。原理是,經過爲表單元素設置enctype=」multipart/form-data」屬性,讓表單提交的數據以二瀏覽器
進制編碼的方式提交,在接收此請求的Servlet中用二進制流來獲取內容,就能夠取得上傳文件的內容,從而實現文件的上傳。緩存
在Java領域中,有兩個經常使用的文件上傳項目:一個是Apache組織Jakarta的Common-FileUpload組件tomcat
([url]http://commons.apache.org/fileupload/[/url]),另外一個是Oreilly組織的COS框架([url]http://www.servlets.com/cos/[/url])。利用這兩個框架都能很方便
的實現文件的上傳。
==================================
Struts2上傳文件
增長commons-fileupload-1.2.jar和commons-io-1.3.1.jar到lib
=====
jsp
=====
form 的 enctype 設置爲 multipart/form-data
==============
UploadAction
==============
private String username;
private String password;
private File file; // 對應文件域
private String fileFileName; // 前面的File屬性的名字 + FileName(固定的)
private String fileContent; // 前面的File屬性的名字 + Content
// setter... getter...
String execute() throws Exception {
InputStream is = new FileInputStream( file );
String root = ServletActionContext.getRequest().getRealPath("/upload");
File destFile = new File(root,this.getFileFileName());
OutputStream os = new FileOutputStream( destFile );
byte[] buffer = new byte[400];
int length = 0;
while( (length = is.read(buffer)) > 0 ) {
os.write(buffer,0,length);
}
is.close();
os.close();
return SUCCESS;
}
=================
中文問題
=================
不過我所有用UTF-8並未遇到中文問題
struts2-core包
struts-default.xml ----攔截器的設置
org.apache.struts2.default.properties ----全局屬性的設置
33行 strusts.i18n.encoding=UTF-8 默認UTF-8
能夠在struts.xml下進行設置
<struts>
設置字符集
<constant name="struts.i18n.encoding" value="gbk"/>
設置上傳文件緩存
<constant name="struts.multipart.saveDir" value="c:/"/>
</struts>
其餘屬性
struts.multipart.parser=jakarta struts2採用那種方式上傳
pell
cos
struts.multipart.maxSize=2097152 默認上傳文件最大的請求大小2M
struts.action.extension=action 整個url的後綴名
================
上傳多個文件
================
有兩種方式:
1.數組
File[] file 文件
String[] fileFileName 文件名
String[] fileContentType 文件類型
2.集合
List<File> file
List<String> fileFileName
List<String> fileContentType
--------
action中:
--------
String execute() {
for(int i = 0; i < file.size(); i++) {
InputStream is = new FileInputStream(file.get(i));
String root = ServletActionContext.getRequest().getRealPath("/upload");
File destFile = new File(root,this.getFileFileName().get(i));
...
}
return SUCCESS;
}
------
jsp中:
------
多個file時,file的名字要一致,都要叫file,它會自動set到跟file名對應的List中去
<s:file name="file" />
<s:file name="file" />
<s:file name="file" />
========================
上傳任意個文件
========================
<td id="more">
<input type="button" value="添加" />
</td>
------
JS:
------
funcation addMore() {
var td = document.getElementById("more");
//生成一個換行符
var br = document.createElement("br");
//建立一個input組件
var input = document.createElement("input");
var button = document.createElement("input");
//指定類型 爲 file 爲文件上傳
input.type = "file";
//指定組件的名字
input.name = "file";
button.type = "button";
button.value = "刪除";
//爲刪除按鈕註冊一個事件
button.onclick = function() {
//alert("刪除按鈕");
//刪除一行
td.removeChild(br);
td.removeChild(input);
td.removeChild(button);
}
//將建立的組件加到<td>中
td.appendChild(br);
td.appendChild(input);
td.appendChild(button);
}
=======================
限制上傳類型
=======================
org.apache.struts2.interceptor.FileUploadInterceptor類
Long maximumSize:最大上傳大小---每個文件的大小,不是總和
String allowedTypes:容許的類型
-------------
struts.xml
-------------
<struts>
<action ...>
<result name="input">/upload.jsp</result>
<result .../>
加入一個上傳文件的攔截器並設置其屬性
<interceptor-ref name="fileUpload">
<param name="maximumSize">409600</param> 單個上傳文件最大不能超過400K
<param name="allowedTypes">...</param> mime類型,多個用逗號分開
</interceptor-ref>
** 加入默認的攔截器
<interceptor-ref name="defaultStack" />
</action>
</struts>
注:後綴能夠到tomcat/conf/web.xml中找<mime-type>中的字符串
--------------
upload.jsp
--------------
添加<s:fielderror />
----------------------
更改顯示的錯誤信息
----------------------
org.apache.struts2中 找到struts-messages.properties
-----------------------
上傳文件類型不匹配
struts.messages.error.content.type.not.allowed=Content-Type not allowed: {0} "{1}" {2}
-----------------------
上傳文件大小超出規定
struts.messages.error.file.too.large=File too large: {0} "{1}" {2}
-----------------------
上傳文件出錯
struts.messages.error.uploading=Error uploading: {0}
建立一個全局的屬性文件 /src/messages.properties
struts.messages.error.content.type.not.allowed=不支持上傳該類型的文件
struts.messages.error.file.too.large=上傳文件過大,請重試
struts.messages.error.uploading=上傳文件時發生錯誤
---------
國際化
---------
<constant name="struts.custom.i18n.resources" value="messages"/>
messages_en_US.properties
messages_zh_CN.properties
==============================
下載
==============================
處理下載的類:org.apache.struts2.dispatcher.StreamResult
== 屬性 ==
String contentType = "text/plain";
String contentLength;
String contentDisposition = "inline";
String inputName = "inputStream";
InputStream inputStream;
int bufferSize = 1024;
== 說明 ==
contentType
內容類型,和互聯網MIME標準中的規定類型一致,例如text/plain表明純文本,text/xml表示XML,image/gif表明GIF圖片,image/jpeg表明JPG圖片
用來作動態文件下載的,事先並不知道將來的文件類型是什麼,那麼咱們能夠把它的值設置成爲:application/octet-stream;charset=ISO8859-1 ,注意必定要加入charset,不然某些時候會致使下載的文件出錯
inputName
下載文件的來源流,對應着action類中某個類型爲Inputstream的屬性名,例如取值爲inputStream的屬性須要編寫getInputStream()方法
contentDisposition
文件下載的處理方式,包括內聯(inline)和附件(attachment)兩種方式,而附件方式會彈出文件保存對話框,不然瀏覽器會嘗試直接顯示文件。取值爲:attachment;filename="struts2.txt",表示文件下載的時候保存的名字應爲struts2.txt。若是直接寫filename="struts2.txt",那麼默認狀況是表明inline,瀏覽器會嘗試自動打開它,等價於這樣的寫法:inline; filename="struts2.txt"
bufferSize
下載緩衝區的大小
# contentType屬性和contentDisposition分別對應着HTTP響應中的頭Content-Type和Content-disposition頭。
如:
HTTP頭內容:
HTTP/1.1 200 OK
Server: Apache-Coyote/1.1
Content-disposition: attachment;filename="struts2.txt"
Content-Type: text/plain
Transfer-Encoding: chunked
Date: Sun, 02 Mar 2008 02:58:25 GMT
----------
action
----------
Class DownloadAction extends ActionSupport {
private String path;
// setter... getter...
//必須返回一個輸入流,該流是讓用戶下載的
public InputStream getDownloadFile() {
//從某個文件得到流 --這裏是得到項目root下upload下的文件
//也能夠 new FileInputStream("c:/test.text");
return ServletActionContext.getServletContext().getResourceAsStream("/upload/struts2.ppt");
}
public String execute() throws Exception {
return SUCCESS;
}
}
-----------
struts.xml
-----------
<action name="download" class="org.scorpio.jh.struts2.upload.action.DownloadAction">
<!-- 依賴注入文件路徑 -->
<param name="path">/download/xhtml.txt</param>
<!-- 設置結果類型爲 流 -->
<result name="success" type="stream">
<!-- 設置內容類型 -->
<param name="contentType">text/plain</param>
<!-- 設置下載文件的名字 attachment:做爲附件,filename=:指定下載文件名-->
<param name="contentDisposition">attachment;filename="xhtml.txt"</param>
<!-- 設置下載文件的輸入流對應的方法 downloadFile對應DownloadAction中的getDownloadFile()-->
<param name="inputName">downloadFile</param>
<!-- 指定下載文件的緩衝大小 -->
<param name="bufferSize">4096</param>
</result>
</action>
==========================
解決下載文件名中文問題
==========================
1.在下載action獲取文件名的方法中先進行轉碼而後再返回
path = new String( path.getBytes(), "ISO-8859-1" );
2.xml配置文件動態的獲取path的值
<param name="contentDisposition">attachment;filename="${path}"</param>
${path} 用於動態的獲取所配置的action中path成員的值,至關於調用getPath()方法
3. /*解決中文亂碼問題,設置後產生一個新的String對象此對象以改變了編碼*/
String newpath=URLEncoder.encode(path,"utf-8");
-------
action
-------
private String path;
public String getPath() {
try { //轉換成西歐字符集
path = new String( path.getBytes(), "ISO-8859-1" );
} catch (UnsupportedEncodingException e) {
e.printStackTrace();
}
return path;
}
public void setPath(String path) {
this.path = path;
}
---------------
struts.xml
---------------
<action name="download" class="org.scorpio.jh.struts2.upload.action.DownloadAction">
<param name="path">/download/wmlscript實例.txt</param>
<result name="success" type="stream">
<param name="contentType">text/plain</param>
<!-- 動態的獲取 DownloadAction的path屬性 -->
<param name="contentDisposition">attachment;filename="${path}"</param>
<param name="inputName">downloadFile</param>
<param name="bufferSize">4096</param>
</result>
</action>
=================
安全隱患
=================
訪問者若是精通Struts 2的話,它可能使用這樣的帶有表單參數的地址來訪問:
[url]http://localhost:8080/struts2hello/download3.action?inputPath=/WEB-INF/web.xml[/url],這樣的結果就是下載後的文件內容是您系統裏面的web.xml的文件的源代碼,甚至還能夠用這種方式來下載任何其它JSP文件的源碼。這對系統安全是個很大的威脅。做爲一種變通的方法,讀者最好是從數據庫中進行路徑配置,而後把Action類中的設置inputPath的方法通通去掉,簡言之就是刪除這個方法定義:
public void setPath(String path) {
this.path = path;
}
而實際狀況則應該成爲 download.action?fileid=1 相似於這樣的形式來進行。或者呢,讀者能夠在execute()方法中進行路徑檢查,若是發現有訪問不屬於download下面文件的代碼,就一概拒絕,不給他們返回文件內容。例如,咱們能夠把剛纔類中的execute()方法加以改進,成爲這樣:
public String execute() throws Exception {
// 文件下載目錄路徑
String downloadDir = ServletActionContext.getServletContext().getRealPath("/download");
// 文件下載路徑
String downloadFile = ServletActionContext.getServletContext().getRealPath(inputPath);
java.io.File file = new java.io.File(downloadFile);
downloadFile = file.getCanonicalPath();// 真實文件路徑,去掉裏面的..等信息
// 發現企圖下載不在 /download 下的文件, 就顯示空內容
if(!downloadFile.startsWith(downloadDir)) {
return null;
}
return SUCCESS;
}
這時候若是訪問者再企圖下載web.xml的內容,它只能獲得一個空白頁,如今訪問者只能下載位於/download目錄下的文件
其餘的一些資料:
Struts 2中實現文件上傳
[url]http://www.blogjava.net/max/archive/2007/03/21/105124.html[/url]
Struts 2中實現文件下載(修正中文問題)
[url]http://www.blogjava.net/beansoft/archive/2008/03/03/183468.html[/url]
附:contentType類型.
'ez' => 'application/andrew-inset',
'hqx' => 'application/mac-binhex40',
'cpt' => 'application/mac-compactpro',
'doc' => 'application/msword',
'bin' => 'application/octet-stream',
'dms' => 'application/octet-stream',
'lha' => 'application/octet-stream',
'lzh' => 'application/octet-stream',
'exe' => 'application/octet-stream',
'class' => 'application/octet-stream',
'so' => 'application/octet-stream',
'dll' => 'application/octet-stream',
'oda' => 'application/oda',
'pdf' => 'application/pdf',
'ai' => 'application/postscript',
'eps' => 'application/postscript',
'ps' => 'application/postscript',
'smi' => 'application/smil',
'smil' => 'application/smil',
'mif' => 'application/vnd.mif',
'xls' => 'application/vnd.ms-excel',
'ppt' => 'application/vnd.ms-powerpoint',
'wbxml' => 'application/vnd.wap.wbxml',
'wmlc' => 'application/vnd.wap.wmlc',
'wmlsc' => 'application/vnd.wap.wmlscriptc',
'bcpio' => 'application/x-bcpio',
'vcd' => 'application/x-cdlink',
'pgn' => 'application/x-chess-pgn',
'cpio' => 'application/x-cpio',
'csh' => 'application/x-csh',
'dcr' => 'application/x-director',
'dir' => 'application/x-director',
'dxr' => 'application/x-director',
'dvi' => 'application/x-dvi',
'spl' => 'application/x-futuresplash',
'gtar' => 'application/x-gtar',
'hdf' => 'application/x-hdf',
'js' => 'application/x-javas
cript', 'skp' => 'application/x-koan', 'skd' => 'application/x-koan', 'skt' => 'application/x-koan', 'skm' => 'application/x-koan', 'latex' => 'application/x-latex', 'nc' => 'application/x-netcdf', 'cdf' => 'application/x-netcdf', 'sh' => 'application/x-sh', 'shar' => 'application/x-shar', 'swf' => 'application/x-shockwave-flash', 'sit' => 'application/x-stuffit', 'sv4cpio' => 'application/x-sv4cpio', 'sv4crc' => 'application/x-sv4crc', 'tar' => 'application/x-tar', 'tcl' => 'application/x-tcl', 'tex' => 'application/x-tex', 'texinfo' => 'application/x-texinfo', 'texi' => 'application/x-texinfo', 't' => 'application/x-troff', 'tr' => 'application/x-troff', 'roff' => 'application/x-troff', 'man' => 'application/x-troff-man', 'me' => 'application/x-troff-me', 'ms' => 'application/x-troff-ms', 'ustar' => 'application/x-ustar', 'src' => 'application/x-wais-source', 'xhtml' => 'application/xhtml+xml', 'xht' => 'application/xhtml+xml', 'zip' => 'application/zip', 'au' => 'audio/basic', 'snd' => 'audio/basic', 'mid' => 'audio/midi', 'midi' => 'audio/midi', 'kar' => 'audio/midi', 'mpga' => 'audio/mpeg', 'mp2' => 'audio/mpeg', 'mp3' => 'audio/mpeg', 'aif' => 'audio/x-aiff', 'aiff' => 'audio/x-aiff', 'aifc' => 'audio/x-aiff', 'm3u' => 'audio/x-mpegurl', 'ram' => 'audio/x-pn-realaudio', 'rm' => 'audio/x-pn-realaudio', 'rpm' => 'audio/x-pn-realaudio-plugin', 'ra' => 'audio/x-realaudio', 'wav' => 'audio/x-wav', 'pdb' => 'chemical/x-pdb', 'xyz' => 'chemical/x-xyz', 'bmp' => 'image/bmp', 'gif' => 'image/gif', 'ief' => 'image/ief', 'jpeg' => 'image/jpeg', 'jpg' => 'image/jpeg', 'jpe' => 'image/jpeg', 'png' => 'image/png', 'tiff' => 'image/tiff', 'tif' => 'image/tiff', 'djvu' => 'image/vnd.djvu', 'djv' => 'image/vnd.djvu', 'wbmp' => 'image/vnd.wap.wbmp', 'ras' => 'image/x-cmu-raster', 'pnm' => 'image/x-portable-anymap', 'pbm' => 'image/x-portable-bitmap', 'pgm' => 'image/x-portable-graymap', 'ppm' => 'image/x-portable-pixmap', 'rgb' => 'image/x-rgb', 'xbm' => 'image/x-xbitmap', 'xpm' => 'image/x-xpixmap', 'xwd' => 'image/x-xwindowdump', 'igs' => 'model/iges', 'iges' => 'model/iges', 'msh' => 'model/mesh', 'mesh' => 'model/mesh', 'silo' => 'model/mesh', 'wrl' => 'model/vrml', 'vrml' => 'model/vrml', 'css' => 'text/css', 'html' => 'text/html', 'htm' => 'text/html', 'asc' => 'text/plain', 'txt' => 'text/plain', 'rtx' => 'text/richtext', 'rtf' => 'text/rtf', 'sgml' => 'text/sgml', 'sgm' => 'text/sgml', 'tsv' => 'text/tab-separated-values', 'wml' => 'text/vnd.wap.wml', 'wmls' => 'text/vnd.wap.wmlscript', 'etx' => 'text/x-setext', 'xsl' => 'text/xml', 'xml' => 'text/xml', 'mpeg' => 'video/mpeg', 'mpg' => 'video/mpeg', 'mpe' => 'video/mpeg', 'qt' => 'video/quicktime', 'mov' => 'video/quicktime', 'mxu' => 'video/vnd.mpegurl', 'avi' => 'video/x-msvideo', 'movie' => 'video/x-sgi-movie', 'ice' => 'x-conference/x-cooltalk'