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