Jive
提供了強(qiáng)大的論壇功能,但是有些功能離實(shí)際需求還是有一定的距離,例如論壇是用于信息交流討論的場(chǎng)所。而信息不只是文字,有時(shí)還包括圖片或一些
PDF
等類(lèi)型的文件,那么如何在
Jive
中實(shí)現(xiàn)這樣的功能呢?
在
HTML
中,使用表單
Form
主要是用來(lái)向服務(wù)器提交數(shù)據(jù),格式如下:
<
FORM ACTION="URL"
METHOD="GET|POST"
ENCTYPE="…" TARGET="..."
>
. . .
<
/FORM
>
enctype
指定了表單提交給服務(wù)器時(shí)的內(nèi)容形式(
Content-Type
),默認(rèn)值是
"application/x-www-form-urlencoded"
,這時(shí),表單信息一般采用
URL
編碼制。
但是,當(dāng)向服務(wù)器傳送圖片或文件這樣包含非
ASCII
字符或二進(jìn)制數(shù)的數(shù)據(jù)時(shí),根據(jù)
RFC1867
規(guī)定,就必須使用“
multipart/form-data
”內(nèi)容類(lèi)型。
其實(shí)無(wú)論是默認(rèn)表單信息,還是圖片文件,這些內(nèi)容都是裝載在
HTTP
協(xié)議的正文內(nèi)容部分,都可以看成
HTTP
協(xié)議攜帶的對(duì)象,只是兩種正文內(nèi)容形式不一樣。前者是
String
字符串類(lèi)型,而后者則是一個(gè)通用的數(shù)據(jù)對(duì)象類(lèi)型(
Object
)。在以后章節(jié)中將專(zhuān)門(mén)討論
HTTP
協(xié)議裝載數(shù)據(jù)對(duì)象的底層細(xì)節(jié)。
使用“
multipart/form-data
”上傳文件的格式寫(xiě)法如下:
<
FORM ACTION="URL" METHOD="GET|POST" ENCTYPE=" multipart/form-data "
>
? <INPUT TYPE
=
FILE NAME
=
file1>
<
/FORM
>
文件通過(guò)
HTTP
協(xié)議傳送到服務(wù)器端后,需要在服務(wù)器端對(duì)該文件進(jìn)行專(zhuān)門(mén)的接受。
HttpServletRequest
沒(méi)有提供直接獲取文件數(shù)據(jù)的方法,因此需要開(kāi)發(fā)專(zhuān)門(mén)的服務(wù)器文件處理組件。
目前有兩種上傳文件處理組件:一種是基于完全
JSP
結(jié)構(gòu)的,使用
JSP
來(lái)處理上傳的文件,以
SmartUpload
(
http://www.jspsmart.com
)最常用;還有一種是完全的
JavaBeans
組件:
Cos
文件上傳組件包(
http://www.servlets.com/cos/index.html
),
Cos
可以使用在
JSP
中,也可以使用在
Servlet
或
Servlet Filter
中。
由于在實(shí)際應(yīng)用中,文件上傳功能往往和其他正常表單參數(shù)一起混合使用,而不是獨(dú)立使用的。因此,可以設(shè)定一個(gè)
Servlet
專(zhuān)門(mén)用來(lái)處理這類(lèi)混合表單的請(qǐng)求,在將文件接受處理后,自動(dòng)導(dǎo)向到處理表單正常參數(shù)的
JSP/Servlet
去處理。
表單調(diào)用示例如下:
<form action="<%=request.getContextPath()%>/multipartformserv"
???? method="post" enctype="multipart/form-data">
?? <input type="hidden" name="FORWARDNAME" value="login.jsp" >?
?? <input type="file" name="file1" >
?? <input type="hidden" name="maxwidth" value="120" >
?? <input type="hidden" name="maxheight" value="60" >
?? <input type="text" name="username" >
?? <input type="text" name="password" >
</form>
在這個(gè)表單中,既有文件提交,也有
username
這樣正常的參數(shù)需要提交,提交的
Servlet
名為
multipartformserv
。由
multipartformserv
來(lái)處理上傳的文件,然后再自動(dòng)轉(zhuǎn)交到
FORWARDNAME
的值
login.jsp
進(jìn)行
username
等正常參數(shù)的處理。
在表單中,如果設(shè)定
maxwidth
和
maxiheight
,那么表示如果上傳的圖片超過(guò)這個(gè)尺寸,服務(wù)器將縮小圖片到這個(gè)尺寸。
編制一個(gè)專(zhuān)門(mén)用來(lái)統(tǒng)一處理
Jive
系統(tǒng)中所有文件處理的
Servlet
,這樣有利于簡(jiǎn)化系統(tǒng)。編制
MultipartFormServ
如下:
public class MultipartFormServ extends HttpServlet {
? static final private String CONTENT_TYPE = "text/html";
? //
文件上傳處理
? private static MultipartFormHandle mf = MultipartFormHandle.getInstance();
? //
文件上傳后存放的臨時(shí)目錄
? private String dirName;
? private ServletContext context;
? public void init() throws ServletException {
??? //
從
web.xml
中讀取上傳目錄參數(shù)
??? dirName = mf.getUploaddir();
??? if (dirName == null) {
????? throw new ServletException("Please supply uploadDir parameter");
??? }
? }
?
? //
處理帶有文件內(nèi)容的請(qǐng)求
? public void doPost(HttpServletRequest request, HttpServletResponse response)
???????? throws ServletException, IOException {
??? try {
?????? mf.init(dirName,request); //
調(diào)用文件上傳處理器處理
?????? //
得到
FORWARDNAME
參數(shù)值
?????? String forward=mf.getForwardProgram();
????? if (forward.equals(""))
?????? {
???????? errorMessage("no forward program", response);
???????? return;
????? }
????? String param=mf.getForwardProgramParam();
????? mf.clear();
?????? //
引導(dǎo)分流到
forward
參數(shù)值進(jìn)行其他文本參數(shù)處理
????? getServletConfig().getServletContext().
?????????? getRequestDispatcher("/"+forward+"?"+param).forward(request, response);
?
??? }catch (Exception Ex) {
????????? throw new ServletException(Ex.getMessage());
??? }
? }
圖
3-8?
上傳文件處理框架
|
}
MultipartFormHandler
主要調(diào)用
Cos
組件處理上傳文件,對(duì)上傳文件圖形大小進(jìn)行處理,然后將圖形搬遷到指定的目錄;同時(shí)也將請(qǐng)求信號(hào)中的正常參數(shù)提取出來(lái),以作為轉(zhuǎn)發(fā)使用。
這樣一個(gè)圖形或文件上傳系統(tǒng)已經(jīng)形成了一個(gè)框架結(jié)構(gòu),可以重復(fù)使用在任何需要圖片或文件上傳處理的系統(tǒng)中,如圖
3-8
所示。
圖
3-8
中上傳文件處理額
Servlet
相當(dāng)于請(qǐng)求信號(hào)
Request
的一個(gè)過(guò)濾器,既然正常的
Request
處理機(jī)制不能從
Request
提取攜帶的文件,那么,使用一個(gè)過(guò)濾器先將文件提取出來(lái),剩余的再通過(guò)正常
Request
處理機(jī)制去處理。
6.2?
服務(wù)器端圖形處理
Java
最初是以
Applet
等客戶(hù)端圖形處理為技術(shù)起點(diǎn)的,而本節(jié)討論的是如何在
Servlet/JSP
中實(shí)現(xiàn)圖形處理。
在
Jive
中,圖片可以用來(lái)顯示用戶(hù)的頭像,用戶(hù)在上傳自己頭像圖片時(shí),該圖片的大小可能不一,但是由于版面原因,顯示的頭像圖片又有大小限制,那么就需要在用戶(hù)上傳圖片時(shí)對(duì)圖片大小做一個(gè)檢查。如果超過(guò)規(guī)定大小,就進(jìn)行一定的縮放處理。
縮放處理有兩種方式:是在
HTML
顯示時(shí),使用
image
語(yǔ)法的
width
和
height
來(lái)
限制大小,但是這樣做只是解決了表面問(wèn)題,無(wú)法解決大字節(jié)圖片傳送到客戶(hù)端帶來(lái)的性能影響,這個(gè)圖片因?yàn)槭怯脩?hù)發(fā)言的頭像,將會(huì)在每個(gè)帖子里面顯示。如果
頭像都是巨大圖片,對(duì)帖子顯示速度的影響是很大,因此必須在服務(wù)器端進(jìn)行縮小后,再傳送到客戶(hù)端,這樣提高了論壇系統(tǒng)性能。
服務(wù)器端的圖形處理需要使用到
Java
的圖形處理技術(shù),而且圖形處理是在服務(wù)器端的
Web
容器中進(jìn)行的。和以往
Java
在客戶(hù)端進(jìn)行圖形處理稍微有所不同,相同的是都要使用計(jì)算機(jī)的底層圖形支持資源。
J2SE 1.4
提供新的增強(qiáng)的圖形處理功能,
JDK1.4
中最新的
javax.imageio.ImageIO
對(duì)圖片進(jìn)行讀寫(xiě)操作,而使用
java.awt.geom.AffineTransform
對(duì)圖片進(jìn)行尺寸縮放處理。
import java.io.File;
import java.awt.image.BufferedImage;
import java.awt.Image;
import java.awt.image.AffineTransformOp;
import javax.imageio.ImageIO;
import java.awt.geom.AffineTransform;
?
public class UploadImg{
???? /**
??? ?*
參數(shù)設(shè)置
???? * @param fromdir
圖片的原始目錄
???? * @param todir
處理后的圖片存放目錄
???? * @param imgfile
原始圖片
???? * @param sysimgfile
處理后的圖片文件名前綴
???? */
???????? ? public void init(String fromdir,String todir,String imgfile,String sysimgfile)
???????? ? {
????????????????? this.fromdir=fromdir;
????????????????? this.todir=todir;
????????????????? this.imgfile=imgfile;
????????????????? this.sysimgfile=sysimgfile;
???????? ??? }
??? …
??? public boolean CreateThumbnail() throws Exception
??? {
??????? //ext
是圖片的格式
gif
、
JPG
或
png
??????? String ext=""
??????? double Ratio=0.0;
??????? File oldFile = new File(fromdir,imgfile);
??????? if (!F.isFile())? //
檢查是否存在此圖片文件
???????????? throw new Exception(F+" is not image file error in CreateThumbnail!");
?
???????? //
首先判斷上傳的圖片是
gif
還是
JPG ImageIO
,只能將
gif
轉(zhuǎn)換為
png
???????? if (isJpg(imgfile)){
??????????? ext="jpg";
?????? ?}else{
?????????? ext="png";
??????? }
??????? File newFile = new File(todir,sysimgfile+"."+ext);
?
??????? BufferedImage Bi = ImageIO.read(oldFile);? //
讀取原始圖片
??????? if ((Bi.getHeight()>120) || (Bi.getWidth()>120)){
??????????? if (Bi.getHeight()>Bi.getWidth())
????????????? Ratio = 120.0/Bi.getHeight();
??????????? else
????????????? Ratio = 120.0/Bi.getWidth();
?????? }
?????? //
進(jìn)行圖片轉(zhuǎn)換
?????? AffineTransformOp op =
????????? new AffineTransformOp(AffineTransform.getScaleInstance(Ratio, Ratio), null);
?????? Image itemp = op.filter(Bi, null);
?
?????? try { //
寫(xiě)入轉(zhuǎn)換后的圖片
?????????? ImageIO.write((BufferedImage) itemp, ext, newFile);
?????? }catch (Exception ex) {
??????????? throw new Exception(ex.getMessage());
?????? }
?????? return (true);
?? }
}
該類(lèi)中由于使用到了
Java
的
AWT
,雖然沒(méi)有實(shí)際顯示,但
Linux
系統(tǒng)下需要
X11 Windows
的支持(安裝
Linux
時(shí)需安裝
XFree86
,
Linux
完全安裝方式包括安裝
XFree86
)。
該縮放功能是在圖片上傳到服務(wù)器后再進(jìn)行的處理,可以對(duì)
JPG
進(jìn)行縮小放大;對(duì)上傳是
GIF
的圖片,縮放后變成
PNG
圖片格式文件。