當前位置:首頁 » 操作系統 » jfinal源碼下載

jfinal源碼下載

發布時間: 2023-01-31 10:37:24

『壹』 jfinal 如何導出zip壓縮文件

官網介紹:JFinal 是基於 java 語言的極速 WEB + ORM 框架,其核心設計目標是開發迅速、代碼量少、學習簡單、功能強大、輕量級、易擴展、Restful。在擁有Java語言所有優勢的同時再擁有ruby、pythonphp等動態語言的開發效率!為您節約更多時間,去陪戀人、家人和朋友 :)

Jfinal做為後台,進行下載文件服務時,源碼中可看到:

Controller中已經提供了,方法:

/**
*Renderwithfile
*/
publicvoidrenderFile(StringfileName){
render=renderManager.getRenderFactory().getFileRender(fileName);
}

/**
*Renderwithfile,
*/
publicvoidrenderFile(StringfileName,StringdownloadFileName){
render=renderManager.getRenderFactory().getFileRender(fileName,downloadFileName);
}

/**
*Renderwithfile
*/
publicvoidrenderFile(Filefile){
render=renderManager.getRenderFactory().getFileRender(file);
}

/**
*Renderwithfile,
file=文件,downloadFileName=下載時客戶端顯示的文件名稱,很貼心
*/
publicvoidrenderFile(Filefile,StringdownloadFileName){
render=renderManager.getRenderFactory().getFileRender(file,downloadFileName);
}

大家可以看到源碼中 FileRender 是有處理各個瀏覽器的兼容問題,所以可以方便的使用

/**
*Copyright(c)2011-2017,JamesZhan詹波([email protected]).
*
*LicensendertheApacheLicense,Version2.0(the"License");
*.
*YoumayobtainaoftheLicenseat
*
*http://www.apache.org/licenses/LICENSE-2.0
*
*,software
*"ASIS"BASIS,
*,eitherexpressorimplied.
*
*limitationsundertheLicense.
*/

packagecom.jfinal.render;

importjava.io.BufferedInputStream;
importjava.io.File;
importjava.io.FileInputStream;
importjava.io.IOException;
importjava.io.InputStream;
importjava.io.OutputStream;
importjava.io.UnsupportedEncodingException;
importjava.net.URLEncoder;
importjavax.servlet.ServletContext;
importjavax.servlet.http.HttpServletRequest;
importjavax.servlet.http.HttpServletResponse;
importcom.jfinal.kit.LogKit;
importcom.jfinal.kit.StrKit;

/**
*FileRender.
*/
{

_CONTENT_TYPE="application/octet-stream";
;
;

protectedFilefile;
=null;

publicFileRender(Filefile){
if(file==null){
("filecannotbenull.");
}
this.file=file;
}

publicFileRender(Filefile,StringdownloadFileName){
this(file);

if(StrKit.isBlank(downloadFileName)){
("downloadFileNamecannotbeblank.");
}
this.downloadFileName=downloadFileName;
}

publicFileRender(StringfileName){
if(StrKit.isBlank(fileName)){
("fileNamecannotbeblank.");
}

StringfullFileName;
fileName=fileName.trim();
if(fileName.startsWith("/")||fileName.startsWith("\")){
if(baseDownloadPath.equals("/")){
fullFileName=fileName;
}else{
fullFileName=baseDownloadPath+fileName;
}
}else{
fullFileName=baseDownloadPath+File.separator+fileName;
}

this.file=newFile(fullFileName);
}

publicFileRender(StringfileName,StringdownloadFileName){
this(fileName);

if(StrKit.isBlank(downloadFileName)){
("downloadFileNamecannotbeblank.");
}
this.downloadFileName=downloadFileName;
}

staticvoidinit(StringbaseDownloadPath,ServletContextservletContext){
FileRender.baseDownloadPath=baseDownloadPath;
FileRender.servletContext=servletContext;
}

publicvoidrender(){
if(file==null||!file.isFile()){
RenderManager.me().getRenderFactory().getErrorRender(404).setContext(request,response).render();
return;
}

//---------
response.setHeader("Accept-Ranges","bytes");
Stringfn=downloadFileName==null?file.getName():downloadFileName;
response.setHeader("Content-disposition","attachment;"+encodeFileName(request,fn));
StringcontentType=servletContext.getMimeType(file.getName());
response.setContentType(contentType!=null?contentType:DEFAULT_CONTENT_TYPE);

//---------
if(StrKit.isBlank(request.getHeader("Range"))){
normalRender();
}else{
rangeRender();
}
}

protectedStringencodeFileName(StringfileName){
try{
//returnnewString(fileName.getBytes("GBK"),"ISO8859-1");
returnnewString(fileName.getBytes(getEncoding()),"ISO8859-1");
}catch(UnsupportedEncodingExceptione){
returnfileName;
}
}

/**
*依據瀏覽器判斷編碼規則
*/
publicStringencodeFileName(HttpServletRequestrequest,StringfileName){
StringuserAgent=request.getHeader("User-Agent");
try{
StringencodedFileName=URLEncoder.encode(fileName,"UTF8");
//如果沒有UA,則默認使用IE的方式進行編碼
if(userAgent==null){
return"filename=""+encodedFileName+""";
}

userAgent=userAgent.toLowerCase();
//IE瀏覽器,只能採用URLEncoder編碼
if(userAgent.indexOf("msie")!=-1){
return"filename=""+encodedFileName+""";
}

//Opera瀏覽器只能採用filename*
if(userAgent.indexOf("opera")!=-1){
return"filename*=UTF-8''"+encodedFileName;
}

//Safari瀏覽器,只能採用ISO編碼的中文輸出,Chrome瀏覽器,只能採用MimeUtility編碼或ISO編碼的中文輸出
if(userAgent.indexOf("safari")!=-1||userAgent.indexOf("applewebkit")!=-1||userAgent.indexOf("chrome")!=-1){
return"filename=""+newString(fileName.getBytes("UTF-8"),"ISO8859-1")+""";
}

//FireFox瀏覽器,可以使用MimeUtility或filename*或ISO編碼的中文輸出
if(userAgent.indexOf("mozilla")!=-1){
return"filename*=UTF-8''"+encodedFileName;
}

return"filename=""+encodedFileName+""";
}catch(UnsupportedEncodingExceptione){
thrownewRuntimeException(e);
}
}

protectedvoidnormalRender(){
response.setHeader("Content-Length",String.valueOf(file.length()));
InputStreaminputStream=null;
OutputStreamoutputStream=null;
try{
inputStream=newBufferedInputStream(newFileInputStream(file));
outputStream=response.getOutputStream();
byte[]buffer=newbyte[1024];
for(intlen=-1;(len=inputStream.read(buffer))!=-1;){
outputStream.write(buffer,0,len);
}
outputStream.flush();
outputStream.close();
}catch(IOExceptione){
Stringn=e.getClass().getSimpleName();
if(n.equals("ClientAbortException")||n.equals("EofException")){
}else{
thrownewRenderException(e);
}
}catch(Exceptione){
thrownewRenderException(e);
}finally{
if(inputStream!=null)
try{inputStream.close();}catch(IOExceptione){LogKit.error(e.getMessage(),e);}
}
}

protectedvoidrangeRender(){
Long[]range={null,null};
processRange(range);

StringcontentLength=String.valueOf(range[1].longValue()-range[0].longValue()+1);
response.setHeader("Content-Length",contentLength);
response.setStatus(HttpServletResponse.SC_PARTIAL_CONTENT);//status=206

//Content-Range:bytes0-499/10000
StringBuildercontentRange=newStringBuilder("bytes").append(String.valueOf(range[0])).append("-").append(String.valueOf(range[1])).append("/").append(String.valueOf(file.length()));
response.setHeader("Content-Range",contentRange.toString());

InputStreaminputStream=null;
OutputStreamoutputStream=null;
try{
longstart=range[0];
longend=range[1];
inputStream=newBufferedInputStream(newFileInputStream(file));
if(inputStream.skip(start)!=start)
thrownewRuntimeException("Fileskiperror");
outputStream=response.getOutputStream();
byte[]buffer=newbyte[1024];
longposition=start;
for(intlen;position<=end&&(len=inputStream.read(buffer))!=-1;){
if(position+len<=end){
outputStream.write(buffer,0,len);
position+=len;
}
else{
for(inti=0;i<len&&position<=end;i++){
outputStream.write(buffer[i]);
position++;
}
}
}
outputStream.flush();
outputStream.close();
}
catch(IOExceptione){
Stringn=e.getClass().getSimpleName();
if(n.equals("ClientAbortException")||n.equals("EofException")){
}else{
thrownewRenderException(e);
}
}
catch(Exceptione){
thrownewRenderException(e);
}
finally{
if(inputStream!=null)
try{inputStream.close();}catch(IOExceptione){LogKit.error(e.getMessage(),e);}
}
}

/**
*Examplesofbyte-ranges-specifiervalues(assuminganentity-bodyoflength10000):
*Thefirst500bytes(byteoffsets0-499,inclusive):bytes=0-499
*Thesecond500bytes(byteoffsets500-999,inclusive):bytes=500-999
*Thefinal500bytes(byteoffsets9500-9999,inclusive):bytes=-500
*Orbytes=9500-
*/
protectedvoidprocessRange(Long[]range){
StringrangeStr=request.getHeader("Range");
intindex=rangeStr.indexOf(',');
if(index!=-1)
rangeStr=rangeStr.substring(0,index);
rangeStr=rangeStr.replace("bytes=","");

String[]arr=rangeStr.split("-",2);
if(arr.length<2)
thrownewRuntimeException("Rangeerror");

longfileLength=file.length();
for(inti=0;i<range.length;i++){
if(StrKit.notBlank(arr[i])){
range[i]=Long.parseLong(arr[i].trim());
if(range[i]>=fileLength)
range[i]=fileLength-1;
}
}

//Rangeformatlike:9500-
if(range[0]!=null&&range[1]==null){
range[1]=fileLength-1;
}
//Rangeformatlike:-500
elseif(range[0]==null&&range[1]!=null){
range[0]=fileLength-range[1];
range[1]=fileLength-1;
}

//checkfinalrange
if(range[0]==null||range[1]==null||range[0].longValue()>range[1].longValue())
thrownewRuntimeException("Rangeerror");
}
}

『貳』 現在JFinal越來越火,它的發展趨勢怎麼樣

JFinal 採用微內核全方位擴展架構,全方位是指其擴展方式在空間上的表現形式。JFinal由Handler、Interceptor、Controller、Render、Plugin五大部分組成。

看過源碼的都知道, JFinal 是輕薄封裝, 原理還是javax.servlet.http.HttpServletRequest等, 所以學好原理, 是最靠譜的, JFinal是為我們快速開發業務實現用的, 新手最好先學會javax.servlet 再來上手JFinal ,
發展趨勢 ? 當做一個工具就好了, Java項目都可以放入JFinal , 小巧方便的, 招聘JFinal 也挺多的

『叄』 JFinal 集成kisso怎麼使用裡面的shiro

這個你需要看kisso的代碼了。

推薦一套完整的Shiro Demo,免費的。

推薦一套完整的ShiroDemo,免費的。
ShiroDemo:http://www.sojson.com/shiro
Demo已經部署到線上,地址是http://shiro.itboy.net

管理員帳號:admin,密碼:sojson.com如果密碼錯誤,請用sojson。PS:你可以注冊自己的帳號,然後用管理員賦許可權給你自己的帳號,但是,每20分鍾會把數據初始化一次。建議自己下載源碼,讓Demo跑起來,然後跑的更快。


管理員帳號:admin,密碼:sojson.com 如果密碼錯誤,請用sojson。PS:你可以注冊自己的帳號,然後用管理員賦許可權給你自己的帳號,但是,每20分鍾會把數據初始化一次。建議自己下載源碼,讓Demo跑起來,然後跑的更快。

『肆』 jfinal不兼容的瀏覽器有哪些

官網介紹:
JFinal 是基於 Java 語言的極速 WEB + ORM
框架,其核心設計目標是開發迅速、代碼量少、學習簡單、功能強大、輕量級、易擴展、Restful。在擁有Java語言所有優勢的同時再擁有ruby、python、php等動態語言的開發效率!為您節約更多時間,去陪戀人、家人和朋友
:)

Jfinal是JAVA框架, 不在瀏覽器上執行的, 是兩個方向。
如果你說的是Jfinal做為後台,進行下載文件服務時,是否有瀏覽器兼容問題,在Jfinal3.0之後的版已經全面兼容了

3.3版的源碼中可看到已經有處理:

/**
*Copyright(c)2011-2017,JamesZhan詹波([email protected]).
*
*LicensendertheApacheLicense,Version2.0(the"License");
*.
*YoumayobtainaoftheLicenseat
*
*http://www.apache.org/licenses/LICENSE-2.0
*
*,software
*"ASIS"BASIS,
*,eitherexpressorimplied.
*
*limitationsundertheLicense.
*/

packagecom.jfinal.render;

importjava.io.BufferedInputStream;
importjava.io.File;
importjava.io.FileInputStream;
importjava.io.IOException;
importjava.io.InputStream;
importjava.io.OutputStream;
importjava.io.UnsupportedEncodingException;
importjava.net.URLEncoder;
importjavax.servlet.ServletContext;
importjavax.servlet.http.HttpServletRequest;
importjavax.servlet.http.HttpServletResponse;
importcom.jfinal.kit.LogKit;
importcom.jfinal.kit.StrKit;

/**
*FileRender.
*/
{

_CONTENT_TYPE="application/octet-stream";
;
;

protectedFilefile;
=null;

publicFileRender(Filefile){
if(file==null){
("filecannotbenull.");
}
this.file=file;
}

publicFileRender(Filefile,StringdownloadFileName){
this(file);

if(StrKit.isBlank(downloadFileName)){
("downloadFileNamecannotbeblank.");
}
this.downloadFileName=downloadFileName;
}

publicFileRender(StringfileName){
if(StrKit.isBlank(fileName)){
("fileNamecannotbeblank.");
}

StringfullFileName;
fileName=fileName.trim();
if(fileName.startsWith("/")||fileName.startsWith("\")){
if(baseDownloadPath.equals("/")){
fullFileName=fileName;
}else{
fullFileName=baseDownloadPath+fileName;
}
}else{
fullFileName=baseDownloadPath+File.separator+fileName;
}

this.file=newFile(fullFileName);
}

publicFileRender(StringfileName,StringdownloadFileName){
this(fileName);

if(StrKit.isBlank(downloadFileName)){
("downloadFileNamecannotbeblank.");
}
this.downloadFileName=downloadFileName;
}

staticvoidinit(StringbaseDownloadPath,ServletContextservletContext){
FileRender.baseDownloadPath=baseDownloadPath;
FileRender.servletContext=servletContext;
}

publicvoidrender(){
if(file==null||!file.isFile()){
RenderManager.me().getRenderFactory().getErrorRender(404).setContext(request,response).render();
return;
}

//---------
response.setHeader("Accept-Ranges","bytes");
Stringfn=downloadFileName==null?file.getName():downloadFileName;
response.setHeader("Content-disposition","attachment;"+encodeFileName(request,fn));
StringcontentType=servletContext.getMimeType(file.getName());
response.setContentType(contentType!=null?contentType:DEFAULT_CONTENT_TYPE);

//---------
if(StrKit.isBlank(request.getHeader("Range"))){
normalRender();
}else{
rangeRender();
}
}

protectedStringencodeFileName(StringfileName){
try{
//returnnewString(fileName.getBytes("GBK"),"ISO8859-1");
returnnewString(fileName.getBytes(getEncoding()),"ISO8859-1");
}catch(UnsupportedEncodingExceptione){
returnfileName;
}
}

/**
*依據瀏覽器判斷編碼規則
*/
publicStringencodeFileName(HttpServletRequestrequest,StringfileName){
StringuserAgent=request.getHeader("User-Agent");
try{
StringencodedFileName=URLEncoder.encode(fileName,"UTF8");
//如果沒有UA,則默認使用IE的方式進行編碼
if(userAgent==null){
return"filename=""+encodedFileName+""";
}

userAgent=userAgent.toLowerCase();
//IE瀏覽器,只能採用URLEncoder編碼
if(userAgent.indexOf("msie")!=-1){
return"filename=""+encodedFileName+""";
}

//Opera瀏覽器只能採用filename*
if(userAgent.indexOf("opera")!=-1){
return"filename*=UTF-8''"+encodedFileName;
}

//Safari瀏覽器,只能採用ISO編碼的中文輸出,Chrome瀏覽器,只能採用MimeUtility編碼或ISO編碼的中文輸出
if(userAgent.indexOf("safari")!=-1||userAgent.indexOf("applewebkit")!=-1||userAgent.indexOf("chrome")!=-1){
return"filename=""+newString(fileName.getBytes("UTF-8"),"ISO8859-1")+""";
}

//FireFox瀏覽器,可以使用MimeUtility或filename*或ISO編碼的中文輸出
if(userAgent.indexOf("mozilla")!=-1){
return"filename*=UTF-8''"+encodedFileName;
}

return"filename=""+encodedFileName+""";
}catch(UnsupportedEncodingExceptione){
thrownewRuntimeException(e);
}
}

protectedvoidnormalRender(){
response.setHeader("Content-Length",String.valueOf(file.length()));
InputStreaminputStream=null;
OutputStreamoutputStream=null;
try{
inputStream=newBufferedInputStream(newFileInputStream(file));
outputStream=response.getOutputStream();
byte[]buffer=newbyte[1024];
for(intlen=-1;(len=inputStream.read(buffer))!=-1;){
outputStream.write(buffer,0,len);
}
outputStream.flush();
outputStream.close();
}catch(IOExceptione){
Stringn=e.getClass().getSimpleName();
if(n.equals("ClientAbortException")||n.equals("EofException")){
}else{
thrownewRenderException(e);
}
}catch(Exceptione){
thrownewRenderException(e);
}finally{
if(inputStream!=null)
try{inputStream.close();}catch(IOExceptione){LogKit.error(e.getMessage(),e);}
}
}

protectedvoidrangeRender(){
Long[]range={null,null};
processRange(range);

StringcontentLength=String.valueOf(range[1].longValue()-range[0].longValue()+1);
response.setHeader("Content-Length",contentLength);
response.setStatus(HttpServletResponse.SC_PARTIAL_CONTENT);//status=206

//Content-Range:bytes0-499/10000
StringBuildercontentRange=newStringBuilder("bytes").append(String.valueOf(range[0])).append("-").append(String.valueOf(range[1])).append("/").append(String.valueOf(file.length()));
response.setHeader("Content-Range",contentRange.toString());

InputStreaminputStream=null;
OutputStreamoutputStream=null;
try{
longstart=range[0];
longend=range[1];
inputStream=newBufferedInputStream(newFileInputStream(file));
if(inputStream.skip(start)!=start)
thrownewRuntimeException("Fileskiperror");
outputStream=response.getOutputStream();
byte[]buffer=newbyte[1024];
longposition=start;
for(intlen;position<=end&&(len=inputStream.read(buffer))!=-1;){
if(position+len<=end){
outputStream.write(buffer,0,len);
position+=len;
}
else{
for(inti=0;i<len&&position<=end;i++){
outputStream.write(buffer[i]);
position++;
}
}
}
outputStream.flush();
outputStream.close();
}
catch(IOExceptione){
Stringn=e.getClass().getSimpleName();
if(n.equals("ClientAbortException")||n.equals("EofException")){
}else{
thrownewRenderException(e);
}
}
catch(Exceptione){
thrownewRenderException(e);
}
finally{
if(inputStream!=null)
try{inputStream.close();}catch(IOExceptione){LogKit.error(e.getMessage(),e);}
}
}

/**
*Examplesofbyte-ranges-specifiervalues(assuminganentity-bodyoflength10000):
*Thefirst500bytes(byteoffsets0-499,inclusive):bytes=0-499
*Thesecond500bytes(byteoffsets500-999,inclusive):bytes=500-999
*Thefinal500bytes(byteoffsets9500-9999,inclusive):bytes=-500
*Orbytes=9500-
*/
protectedvoidprocessRange(Long[]range){
StringrangeStr=request.getHeader("Range");
intindex=rangeStr.indexOf(',');
if(index!=-1)
rangeStr=rangeStr.substring(0,index);
rangeStr=rangeStr.replace("bytes=","");

String[]arr=rangeStr.split("-",2);
if(arr.length<2)
thrownewRuntimeException("Rangeerror");

longfileLength=file.length();
for(inti=0;i<range.length;i++){
if(StrKit.notBlank(arr[i])){
range[i]=Long.parseLong(arr[i].trim());
if(range[i]>=fileLength)
range[i]=fileLength-1;
}
}

//Rangeformatlike:9500-
if(range[0]!=null&&range[1]==null){
range[1]=fileLength-1;
}
//Rangeformatlike:-500
elseif(range[0]==null&&range[1]!=null){
range[0]=fileLength-range[1];
range[1]=fileLength-1;
}

//checkfinalrange
if(range[0]==null||range[1]==null||range[0].longValue()>range[1].longValue())
thrownewRuntimeException("Rangeerror");
}
}

『伍』 如何評價Jfinal,Jpress

首先,我是從qbasic開始編程,經歷了qb到vb,vb到asp(不帶.net),asp到jsp,jsp到php,再回頭學習j2ee。這個過程可能導致我的觀點可能跟主流觀點不同,希望各位理解。

j2ee並不等於spring struts hibernate,還有各種其他的選擇,ssh不是唯一甚至不是最好的選擇,這里按下不表。

先問一個問題,什麼是jsp/servlet不能做,而ssh能做的?沒有ssh之前,就沒有web應用了么?

有人會覺得servlet傻,可是你看看struts的核心入口Dispatcher,不就是一個Servlet么。你覺得jdbc難用,hibernate的功能最後還是用jdbc實現的,而且不少批量處理的情況,還是原生sql好用,以至於hibernate不得不提供原生sql介面,mybatis正是從這里挖走不少用戶。

在很多情況下,ssh做的,只不過是把java/jsp/servlet/jdbc本來就具有的功能,封裝成不一樣的API,把原先用Java編寫的代碼變成用XML編寫,然後在用java寫的解釋器在jvm裡面去運行這些XML。所以,我覺得ssh其實就是面向web開發這個領域創造出來的一組DSL(領域特定語言)。而這套語言以XML開始,現在轉移到java的註解annotation,慢慢的又回歸java語言本身。

不太全面的說,struts就是給不熟悉html/css/js的web程序員擺脫它們寫業務邏輯用的,hibernate就是給不熟悉SQL的程序員擺脫SQL寫資料庫程序用的,spring就是給不熟悉java的介面、反射的程序員擺脫介面反射寫AOP用的。而上面被代替的這些,恰恰是相關領域的原生DSL,這裡面多少有一點諷刺的意味,對么?

如果struts的開發者沒有在jsp混雜java片段的各種<%="'"+xx.yy()+"'"%>嵌套括弧引號海裡面摸爬滾打過來,你覺得他們會想到要做struts么?
如果hibernate的開發者沒有在SQL的join鏈中繞暈過,他們會搞hibernate?
如果spring的開發者沒有對java反射的異常數量吐過槽,會有spring?

如果你只想做一個平庸的碼農,去學ssh能讓你找到一份不錯的入門工作。
如果你希望能深入的理解系統、語言、框架,去學習語言本身提供的功能,去學習servlet、jdbc、java,去看看如何用他們構造通用的復雜的系統,也許未來5-10年,人們再提起j2ee,說的就是你創造的框架的名字,而不再是什麼spring struts hibernate。

我們總是希望高內聚低耦合,但兩者通常是矛盾的;如果你願意放棄其中的一個,就可以在另一個上面走的更遠。

『陸』 jfinal .findById 與.find誰的效率高

findById :是按照主鍵查詢,肯定只能查詢一條或者0條記錄,一般資料庫默認主鍵為索引,使用索引速度肯定快的
find:按照你的sql語句的where條件查詢,查詢0-N條。
按照你的需求,如果要按照主鍵查詢建議用findById,如果查詢多條只能用find。
如果要查詢1條記錄,硬是要比較速度,還是findById比較快,看源碼find要進行很多list的實例化。

熱點內容
哇哇賺錢腳本 發布:2024-03-29 20:23:53 瀏覽:996
兩氣體壓縮 發布:2024-03-29 20:18:09 瀏覽:993
易語言教程解壓 發布:2024-03-29 20:18:00 瀏覽:785
我老爸的密碼是什麼 發布:2024-03-29 20:03:50 瀏覽:247
資料庫定義實驗 發布:2024-03-29 19:52:20 瀏覽:578
如何除去安卓手機的馬賽克 發布:2024-03-29 19:52:16 瀏覽:584
網站緩存設置 發布:2024-03-29 19:47:20 瀏覽:798
在jsp中使用資料庫 發布:2024-03-29 19:29:01 瀏覽:786
dns伺服器江川區ip地址 發布:2024-03-29 18:47:53 瀏覽:328
sql統計百分比 發布:2024-03-29 18:47:14 瀏覽:692