struts2 文件上傳與下載原理 (轉載)

文件上傳的原理: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'

相關文章
相關標籤/搜索