<rt id="bn8ez"></rt>
<label id="bn8ez"></label>

  • <span id="bn8ez"></span>

    <label id="bn8ez"><meter id="bn8ez"></meter></label>

    自寫自看

    commons-fileupload用戶指南(轉(zhuǎn))

    根據(jù)你的應(yīng)用需求,fileupload可以有許多不同的使用方式。在最簡(jiǎn)單的情況下,你可以調(diào)用一個(gè)簡(jiǎn)單的方法來(lái)解析servlet請(qǐng)求,然后在他們提交到你的應(yīng)用時(shí)處理表單列表。在其它規(guī)模的終端上,你也可能決定將fileupload進(jìn)行自定義,以完全控制個(gè)別表單項(xiàng)存儲(chǔ)的方法。比如,你或許會(huì)將內(nèi)容流化來(lái)保存到數(shù)據(jù)中。
    在這里。我們將要描述fileupload的基本使用方法,然后解釋一些更簡(jiǎn)單的,以及最常用的使用模式。fileupload的個(gè)性化在這里得到了描述。

    它怎么工作

    一個(gè)文件上傳請(qǐng)求由有序表單項(xiàng)的列表組成,這些表單是根據(jù)RFC1867來(lái)編碼的,是在html中基于表單的文件上傳。fileupload能解析這樣一個(gè)請(qǐng)求然后向你的應(yīng)用提供一個(gè)單獨(dú)的上傳表單項(xiàng)的列表。每一個(gè)這樣的表單項(xiàng)實(shí)現(xiàn)了FileItem接口,而不需要考慮它潛在的實(shí)現(xiàn)方式。每個(gè)文件的表單項(xiàng)擁有一系列可能對(duì)你的應(yīng)用有用的屬性,比如,每個(gè)項(xiàng)目都有一個(gè)名字和文件類型,你就可以提供一個(gè)InputStream來(lái)取它的數(shù)據(jù)。從另一方面說(shuō),你可能需要對(duì)這些選項(xiàng)進(jìn)行不同的處理,這個(gè)可以根據(jù)對(duì)這個(gè)選項(xiàng)是不是一個(gè)規(guī)則的表單項(xiàng)來(lái)判斷,即可以根據(jù)這個(gè)數(shù)據(jù)是否來(lái)源于普通的文本框或者一個(gè)簡(jiǎn)單的html表單域,還是一個(gè)能被上傳的文件。FileItem接口提供了多種方法來(lái)判斷它是否是一個(gè)可上傳的文件,然后你就可以用最合適的方式來(lái)處理這些數(shù)據(jù)了。FileUpload使用FileItemFactory來(lái)創(chuàng)建新的文件項(xiàng)目。這正是給FileUpload帶來(lái)靈活性的原因。這個(gè)工廠最終控制每個(gè)項(xiàng)目的創(chuàng)建。默認(rèn)的工廠在內(nèi)存或者磁盤上保存了項(xiàng)目的數(shù)據(jù),這個(gè)可以根據(jù)項(xiàng)目的大小來(lái)定(例如,字節(jié)數(shù)據(jù))。當(dāng)然,這個(gè)動(dòng)作可以通過自定義來(lái)滿足你應(yīng)用的需要。

    解析請(qǐng)求

    在你對(duì)要上傳的選項(xiàng)處理之前,很顯然的你得先解析這些請(qǐng)求本身。很直接的就是要確保這個(gè)請(qǐng)求是不是一個(gè)要上傳的文件,然而FileUpload使這一點(diǎn)簡(jiǎn)單化了,你只需提供一個(gè)靜態(tài)的方法來(lái)做到這一點(diǎn)。

    //檢查是否是一個(gè)文件上傳請(qǐng)求
    boolean isMultipart = FileUpload.isMultipartContent(request);


    現(xiàn)在我們就可以準(zhǔn)備解析這個(gè)請(qǐng)求到一個(gè)備選的選項(xiàng)了。解析的結(jié)果是一個(gè)文件選項(xiàng)的List,每個(gè)這樣的選項(xiàng)都實(shí)現(xiàn)了FileItem接口,處理這些選項(xiàng)將在下面得到討論。

    最簡(jiǎn)單的情況

    最簡(jiǎn)單的使用場(chǎng)景可以參照下面:

    • 被上傳得選項(xiàng)必須以適度的大小駐留在內(nèi)存中;
    • 比較大的文件上傳選項(xiàng)必須寫入到磁盤的臨時(shí)文件中去;
    • 大文件上傳請(qǐng)求必須不被允許;
    • 默認(rèn)的駐留內(nèi)存的選項(xiàng)的最大大小,最大允許的上傳文件請(qǐng)求,和臨時(shí)文件的存儲(chǔ)地方是可以接受的;

    在這種情景下處理這樣一個(gè)請(qǐng)求并不是很簡(jiǎn)單的:


    //創(chuàng)建一個(gè)新的文件上傳句柄
    DiskFileUpload upload = new DiskFileUpload();
    //解析請(qǐng)求
    List /* FileItem */ items = upload.parseRequest(request);


    這就是所有我們需要做的,真的!
    解析的結(jié)果是一個(gè)文件項(xiàng)目的List,每一個(gè)都實(shí)現(xiàn)了FileItem接口。處理這些項(xiàng)目將在下面討論。

    練習(xí)更多的控制

    如果你的使用情景非常接近最簡(jiǎn)單的使用方式,在上文中可以看到,但是你需要更多的控制臨界的大小和臨時(shí)文件的駐留地址,你可以使用DiskFileUpload類的方法來(lái)自定義這些動(dòng)作,就像這樣:


    //創(chuàng)建一個(gè)新的文件上傳句柄
    DiskFileUpload upload = new DiskFileUpload();
    //設(shè)置上傳參數(shù)
    upload.setSizeThrehold(最大內(nèi)存大小);
    upload.setSizeMax(最大請(qǐng)求大小);
    upload.setRepositoryPath(臨時(shí)目錄);
    //解析請(qǐng)求
    List /* FileItem */ items = upload.parseRequest(request);


    當(dāng)然,每個(gè)配置方法都是獨(dú)立于其它的,但是如果你想一次就配置它們,你可以使用可選的parseRequest()方法,像這樣:


    // 建立一個(gè)新的文件上傳句柄
    DiskFileUpload upload = new DiskFileUpload();
    // 解析請(qǐng)求
    List /* FileItem */ items = upload.parseRequest(request,
    ??????? 內(nèi)存大小, 允許上傳的最大文件, 臨時(shí)目錄);


    如果你想更多地控制請(qǐng)求的解析,比如把上傳選項(xiàng)存儲(chǔ)到其它地方,例如,存到數(shù)據(jù)庫(kù)中-你可以參照自定義FileUpload。

    處理上傳選項(xiàng)

    一旦解析過程完畢,你就可以獲得一個(gè)文件選項(xiàng)的List,以便進(jìn)一步處理。在大多數(shù)情況下,你將會(huì)根據(jù)規(guī)則的表單域來(lái)不同地處理文件的上傳。所以你可能以這樣的方式來(lái)處理:


    // 處理上傳的選項(xiàng)
    Iterator iter = items.iterator();
    while (iter.hasNext()) {
    ??? FileItem item = (FileItem) iter.next();

    ??? if (item.isFormField()) {
    ??????? processFormField(item);
    ??? } else {
    ??????? processUploadedFile(item);
    ??? }
    }


    對(duì)于一個(gè)規(guī)則的表單域來(lái)說(shuō),你對(duì)它感興趣的可能就只有它的名字以及它的字符串值。你也會(huì)想到,處理它們是簡(jiǎn)單的:


    //處理一個(gè)規(guī)則表單域
    if (item.isFormField()) {
    ??? String name = item.getFieldName();
    ??? String value = item.getString();
    ??? ...
    }


    而對(duì)于一個(gè)文件的上傳,在你處理它的內(nèi)容之前,可以有好多令你想知道的不同的東西,這里有一個(gè)采用了一些你可能感興趣的方法的例子


    // 處理一個(gè)文件上傳
    if (!item.isFormField()) {
    ??? String fieldName = item.getFieldName();
    ??? String fileName = item.getName();
    ??? String contentType = item.getContentType();
    ??? boolean isInMemory = item.isInMemory();
    ??? long sizeInBytes = item.getSize();
    ??? ...
    }


    對(duì)于這些上傳的文件,你一般不想通過內(nèi)存來(lái)存取它們,除非它們很小,或者你沒有其它好的方法,更進(jìn)一步,你想將內(nèi)容當(dāng)作文件流來(lái)處理,或者將整個(gè)文件寫到最終的地址。FileUpload提供了簡(jiǎn)單的方法來(lái)完成這些 操作。


    // 處理一個(gè)文件上傳的情況
    if (writeToFile) {
    ??? File uploadedFile = new File(...);
    ??? item.write(uploadedFile);
    } else {
    ??? InputStream uploadedStream = item.getInputStream();
    ??? ...
    ??? uploadedStream.close();
    }


    注意到,在默認(rèn)的FileUpload的實(shí)現(xiàn)中,write()方法將嘗試把文件改名以將它保存到特定的地點(diǎn),如果數(shù)據(jù)已經(jīng)在臨時(shí)文件中了,如果重命名失敗,實(shí)際的復(fù)制文件就完成了(?),在其它原因看來(lái),或者數(shù)據(jù)已經(jīng)在內(nèi)存中了。如果你的確需要在內(nèi)存中取上傳的數(shù)據(jù),你只需簡(jiǎn)單的調(diào)用get()方法來(lái)把它當(dāng)作一個(gè)字符數(shù)組來(lái)獲得。



    // 在內(nèi)存中處理一個(gè)上傳的文件
    byte[] data = item.get();
    ...



    和殺毒軟件的相互作用

    當(dāng)web容器在運(yùn)行時(shí),而殺毒軟件又同時(shí)運(yùn)行在同樣的系統(tǒng)上,這種情況下在應(yīng)用中使用FileUpload容易導(dǎo)致一些很難預(yù)料的事情.這部分將描述一些你可能要遇到的情況,我們會(huì)提供一些方法來(lái)處理它們。默認(rèn)的FileUpload實(shí)現(xiàn)將會(huì)使超過它在內(nèi)存中大小的上傳的選項(xiàng)寫入到磁盤。而當(dāng)這樣的文件關(guān)閉后,任何系統(tǒng)中的殺毒軟件都會(huì)被喚醒,然后去檢查它,然后會(huì)潛在地隔離這個(gè)文件--就是說(shuō),將它移動(dòng)到一個(gè)不產(chǎn)生問題的特定地方。這樣一來(lái),對(duì)開發(fā)者來(lái)說(shuō)當(dāng)然是一個(gè)意外,因?yàn)閯倓偵蟼鞯奈募⒉荒鼙惶幚砹?。從另一方面?lái)說(shuō),小于設(shè)定的內(nèi)存大小的那些上傳的文件將被保持在內(nèi)存中,這樣一來(lái),將不會(huì)被殺毒軟件所檢測(cè)到,這樣就有可能使病毒以某種方式駐留在了系統(tǒng)中了(雖然如果一旦它被寫入到磁盤,殺毒軟件就會(huì)定位并檢測(cè)到它)。一個(gè)通用的解決方法是在系統(tǒng)中專門設(shè)置一個(gè)目錄來(lái)存放這些上傳的文件,然后配置殺毒軟件忽略這個(gè)目錄。這樣將確保上傳的文件在系統(tǒng)中不被隔離,但是這樣就把掃描病毒的責(zé)任交給了應(yīng)用程序的開發(fā)者了。掃描這些上傳的文件的任務(wù)可以在外部的處理中實(shí)現(xiàn)。這樣可以將干凈的文件移動(dòng)到一個(gè)“改進(jìn)”過的地方,或者也可以把殺毒集成到應(yīng)用中去。至于怎么將外部處理或集成病毒掃描到一個(gè)
    應(yīng)用,這個(gè)已經(jīng)超出了本文檔的討論范圍。

    下一步是什么

    希望這個(gè)頁(yè)面能提供給你一個(gè)好的意見,讓你在你自己的應(yīng)用中能使用FileUpload。更多關(guān)于這里介紹的方法,以及其它可用的方法,你可以參照api文檔。這里介紹的用法已經(jīng)可以滿足大多數(shù)的文件上傳的需要了,當(dāng)然,如果你還有更多的復(fù)雜的需求,使用它的靈活的自定義配置的能力,F(xiàn)ileUpload一定可以能夠幫助你。

    另一個(gè)實(shí)例:


    commons.fileupload實(shí)現(xiàn)文件的上傳,代碼如下:
    <%!
    ?//服務(wù)器端保存上傳文件的路徑
    ??? String saveDirectory = "g:\\upload\\";
    ??? // 臨時(shí)路徑 一旦文件大小超過getSizeThreshold()的值時(shí)數(shù)據(jù)存放在硬盤的目錄
    ??? String tmpDirectory = "g:\\upload\\tmp\\";
    ??? // 最多只允許在內(nèi)存中存儲(chǔ)的數(shù)據(jù)大小,單位:字節(jié)
    ??? int maxPostSize = 1024 * 1024;
    %>
    <%
    ??? // 文件內(nèi)容?
    ??? String FileDescription = null;
    ??? // 文件名(包括路徑)
    ??? String FileName = null;
    ??? // 文件大小
    ??? long FileSize = 0;
    ??? // 文件類型
    ??? String ContentType = null;

    %>

    <%
    ?? DiskFileUpload fu = new DiskFileUpload();
    ??? // 設(shè)置允許用戶上傳文件大小,單位:字節(jié)
    ?? fu.setSizeMax(200*1024*1024);
    ??? // 設(shè)置最多只允許在內(nèi)存中存儲(chǔ)的數(shù)據(jù),單位:字節(jié)
    ?? fu.setSizeThreshold(maxPostSize);
    ??? // 設(shè)置一旦文件大小超過getSizeThreshold()的值時(shí)數(shù)據(jù)存放在硬盤的目錄
    ?? fu.setRepositoryPath("g:\\upload\\tmp\\");
    ??? //開始讀取上傳信息 得到所有文件
    ?? try{
    ????? List fileItems = fu.parseRequest(request);
    ???? }catch(FileUploadException e){
    ???????? //這里異常產(chǎn)生的原因可能是用戶上傳文件超過限制、不明類型的文件等
    ???????? //自己處理的代碼
    ???? }
    %>
    <%
    ?? // 依次處理每個(gè)上傳的文件
    ?? Iterator iter = fileItems.iterator();
    ?? while (iter.hasNext()) {
    ???? FileItem item = (FileItem) iter.next();
    ?????? //忽略其他不是文件域的所有表單信息
    ???? if (!item.isFormField()) {
    ?????? String name = item.getName();
    ?????? long size = item.getSize();
    ?????? String? contentType = item.getContentType();
    ???? if((name==null||name.equals("")) && size==0)
    ?????? continue;
    %>
    <%
    ?? //保存上傳的文件到指定的目錄
    ? String[] names=StringUtils.split(name,"\\");? //對(duì)原來(lái)帶路徑的文件名進(jìn)行分割
    ?? name = names[names.length-1];
    ?? item.write(new File(saveDirectory+ name));
    ? }
    }
    %>
    ?下面是其簡(jiǎn)單的使用場(chǎng)景:
    ?A、上傳項(xiàng)目只要足夠小,就應(yīng)該保留在內(nèi)存里。
    ?B、較大的項(xiàng)目應(yīng)該被寫在硬盤的臨時(shí)文件上。
    ?C、非常大的上傳請(qǐng)求應(yīng)該避免。
    ?D、限制項(xiàng)目在內(nèi)存中所占的空間,限制最大的上傳請(qǐng)求,并且設(shè)定臨時(shí)文件的位置。
    ?
    ?可以根據(jù)具體使用用servlet來(lái)重寫,具體參數(shù)配置可以統(tǒng)一放置到一配置文件
    ?



    ?文件的下載用servlet實(shí)現(xiàn)
    ????? public void doGet(HttpServletRequest request,
    ?????????????????????? HttpServletResponse response)
    ???? {
    ??????? ?String aFilePath = null;??? //要下載的文件路徑
    ???????? String aFileName = null;??? //要下載的文件名
    ???????? FileInputStream in = null;? //輸入流
    ???????? ServletOutputStream out = null;? //輸出流

    ???????? try
    ???{
    ???????? ?
    ???????????? aFilePath = getFilePath(request);
    ???????????? aFileName = getFileName(request);

    ???????????? response.setContentType(getContentType(aFileName) + "; charset=UTF-8");
    ???????????? response.setHeader("Content-disposition", "attachment; filename=" + aFileName);

    ???????????? in = new? FileInputStream(aFilePath + aFileName); //讀入文件
    ??????????? out = response.getOutputStream();
    ??????????? out.flush();
    ?????????? ?int aRead = 0;
    ?????????? while((aRead = in.read()) != -1 & in != null)
    ?????? ?{
    ???????????? out.write(aRead);
    ???????? }
    ?????????? out.flush();
    ????? }
    ?????? catch(Throwable e)
    ???? {
    ???? log.error("FileDownload doGet() IO error!",e);
    ????? }
    ???????? finally
    ???????? {
    ???????????? try
    ???????????? {
    ???????????????? in.close();
    ???????????????? out.close();
    ???????????? }
    ???????????? catch(Throwable e)
    ???????????? {
    ???????????? ?log.error("FileDownload doGet() IO close error!",e);
    ???????????? }
    ???????? }
    ???? }




    posted on 2006-11-03 20:51 昨夜人生 閱讀(640) 評(píng)論(0)  編輯  收藏


    只有注冊(cè)用戶登錄后才能發(fā)表評(píng)論。


    網(wǎng)站導(dǎo)航:
     
    主站蜘蛛池模板: 久久av无码专区亚洲av桃花岛| 亚洲色偷偷综合亚洲av78 | 亚洲国产成人久久综合碰碰动漫3d | 无码日韩精品一区二区免费| 亚洲精品日韩一区二区小说| 亚洲中文字幕日产乱码高清app| 57pao国产成视频免费播放| 国产精品亚洲精品爽爽| 久久久久久亚洲av成人无码国产| 毛片视频免费观看| 国产免费高清69式视频在线观看| 亚洲最大在线视频| 亚洲中文字幕丝袜制服一区| 亚洲成人免费电影| 一级特黄录像视频免费| 色在线亚洲视频www| 亚洲日韩中文无码久久| 日韩一级免费视频| 一级毛片免费观看不卡视频| 美女尿口扒开图片免费| 亚洲国产午夜电影在线入口| 自拍偷自拍亚洲精品情侣| 嫩草影院免费观看| 日本一卡精品视频免费| 人人爽人人爽人人片av免费 | 亚洲精品成人图区| 亚洲日本在线观看视频| 69成人免费视频无码专区| A片在线免费观看| 九一在线完整视频免费观看| 久久亚洲国产最新网站| 久久精品国产精品亚洲艾 | 亚洲国产成+人+综合| 亚洲最大激情中文字幕| 性做久久久久免费看| 在线观看av永久免费| 99在线观看视频免费| 97无码人妻福利免费公开在线视频 | 国产成人亚洲合集青青草原精品| 亚洲成av人在线视| 国产精品亚洲综合专区片高清久久久|