程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 編程語言 >> 網頁編程 >> JSP編程 >> 關於JSP >> jsp 用戶上傳頭像、上傳圖片、郵件上傳附件代碼

jsp 用戶上傳頭像、上傳圖片、郵件上傳附件代碼

編輯:關於JSP

jsp教程 用戶上傳頭像、上傳圖片、郵件上傳附件代碼


2. 頁面表單的實現
    文件上傳表單和普通表單有兩個區別

    1) 需要文件上傳字段  <input type=”file” />

    2) form 表單的 enctype 屬性需要指定為 multipart/form-data

3. 服務器端解析request
    在 Servlet 中通過 request.getInputStream 獲得表單上傳數據,會發現數據是分段發送的

由於自己寫程序解析有難度,我們可以使用Apache 開發的開源組件Commons-fileupload

需要導入 jar 包Commons-fileupload 和Commons-io

4 . UploadServlet 中處理文件上傳程序
// 1. 創建工廠類

DiskFileItemFactory factory = new DiskFileItemFactory();

// 2. 創建FileUpload對象

ServletFileUpload upload = new ServletFileUpload(factory);

// 3. 判斷是否是上傳表單

boolean b = upload.isMultipartContent(request);

if(!b) {

    // 不是文件上傳

request.setAttribute("message", "對不起,不是文件上傳表單!");

request.getRequestDispatcher("/message.jsp").forward(request, response);

    return;

}

// 是文件上傳表單

// 4. 解析request,獲得FileItem項

List<FileItem> fileitems = upload.parseRequest(request);

// 5. 遍歷集合

for(FileItem item : fileitems) {

    // 判斷是不是普通字段

if(item.isFormField()) {

    String name = item.getFieldName();

    String value = item.getString();

    // 手工的轉換了

    value = new String(value.getBytes("iso-8859-1"),"utf-8");

    System.out.println(name + "=" + value);

} else {

    // 文件上傳字段

    // 獲得文件名

    String filename = item.getName();

    System.out.println(filename);

    filename = filename.substring(filename.lastIndexOf("")+1);

   

    System.out.println(filename);

    // 創建文件

    ServletContext context = getServletContext();

    String dir = context.getRealPath("WEN-INF/upload");

    File file = new File(dir, filename);

    file.createNewFile();

   

    // 獲得流,讀取數據寫入文件

    InputStream in = item.getInputStream();

    FileOutputStream fos = new FileOutputStream(file);

   

    int len;

    byte[] buffer = new byte[1024];

    while((len=in.read(buffer))>0)

       fos.write(buffer,0,len);

    fos.close();

    in.close();

    item.delete();    // 刪除臨時文件

}

二、 文件上傳處理細節
1. 中文亂碼問題
    1) 文件名中文亂碼問題,解決辦法: 告訴文件上傳組件以什麼編碼方式來解碼文件名

       ServletUpload.setCharacterEncoding(“utf-8”);

       request. setCharacterEncoding(“utf-8”);

    

    2) 普通字段中文亂碼問題

       fileitem.getString(“utf-8”);      

2.   臨時文件
    對於大文件不能緩存在內存,需要緩存到硬盤,為了方便管理,我們需要設置臨時文件存放目錄

    // 設置臨時文件的存放位置

factory.setRepository(new File("d:/temp"));

    文件上傳完畢需要刪除臨時文件,否則會導致服務器存在兩份上傳文件

// 注意,需要先將流進行關閉,否則會導致臨時文件無法刪除

out.close();

in.close();

// 刪除臨時文件

fileitem.delete();

3. 文件存放目錄
    1) 目錄需要隱藏,禁止外界直接訪問

    2) 文件名需要保證不重復

    3) 文件應該分目錄存放

三、上傳進度條
1. 實現進度監聽
    需要實現對文件上傳進度的監聽,需要給FileUpload 對象添加 ProgressListener

    在upload方法中對與進度相關的數據進行處理

    upload.setProgressListener(new ProgressListener() {

    long num = 0;

    public void update(long bytesRead, long contentLength, int items) {

      

            long progress = bytesRead*100/contentLength;

           if(progress==num)

               return;

           num = progress;

           System.out.println("上傳進度:" + progress + "%");

      

        //  request.getSession().setAttribute("progress", progress);

        }

    });

2. 在 jsp 頁面顯示進度
    實驗: 

    1) 使用 iframe 發送請求, 請求一個Servlet, 在Servlet 中返回響應,發送自增的num

       此時會發現 iframe 會不停第想Servlet發送請求

    2) 點擊文件上傳按鈕後,iframe立刻停止刷新,直至上傳完畢頁面跳轉至新頁面

    3)為了觀察實驗結果,將form 的 target 指定為 iframe, UploadServlet回送上傳完畢的結果

    4) 出現上述問題的原因,浏覽器不支持多線程同時訪問服務器只能同時發送一個請求,

       這樣的訪問方式為同步訪問

    5) 要在文件上傳的同時在iframe中實現進度訪問,就需要ie浏覽器與服務器進行異步交互

       此時就需要 XMLHttpRequest 對象

       在網頁特效中可以直接使用XMLHttpRequest 對象與服務器進行異步通信

       獲得XmlHttpRequest 對象的方式有兩種

       ie7以上版本

       var xhr = null;

       if(window.XMLHttpRequest)

           xhr = new XMLHttpRequest();

       ie7以下版本

       if(window.ActiveXObject)

           xhr = new ActiveXObject(“Microsoft.XMLHTTP”);

      

       獲得對象後需要調用open方法輸入請求地址

       注意請求方式, 地址的輸入, 並且需要設置為true 指定異步訪問該地址

       xhr.open(“get”,”/upload/servlet/UploadServlet”, false)

      

       // 調用send 方法發送請求,post方式需要發送消息體,get方式則不用直接傳入null值

       xhr.send(null);

      

       // 訪問 responseText 屬性獲得 Servlet 回送的數據

       document.write(xhr.responseText);

四、 api方法
1. DiskFileItemFactory 對象
    設置緩沖區大小,字節為單位,默認為10K,一般不用修改

    factory.setSizeThreshold(1000);

    設置臨時文件存放目錄

    factory.setRepository(file);

2. ServletFileUpload 對象
    判斷是否為文件上傳表單

    boolean b = upload.isMultipartContent(request);

   解析request對象

   List<FileItem> list = upload.parseRequest(request);

   設置上傳文件的最大值

    setFileSizeMax(long fileSizeMax)

    設置上傳文件總量的最大值

    setSizeMax(long sizeMax)

    設置編碼格式

    setHeaderEncoding(java.lang.String encoding)

    注冊進度監聽器

    setProgressListener(ProgressListener pListener)

3. FileItem 對象
    獲得表單字段的屬性名

    item.getFieldName();

    獲得普通字段的值

    item.getString(charsetName)

    獲得文件上傳字段的文件名

    item.getName()

    獲得文件上傳的流

    item.getInputStream()

  

 文件上傳時需要注意的問題:

1.如何設置上傳文件最大值,並實現超出最大值時給用戶一個友好提示
 upload.setFileSizeMax(1024*10);  //設置最大值
 實現超出最大值時給用戶一個友好提示:在程序中捕獲FileUploadBase.FileSizeLimitExceededException
 只要程序拋出這個異常,代表用戶上傳的文件超出最大值
 
 
2.上傳過程中的亂碼問題
 2.1 普通輸入項的亂碼
  item.getString("碼表 ")
 2.2 上傳文件名的亂碼
  ServletFileUpload.setHeaderEncoding("碼表")
 
3.上傳文件的安全性問題
 為防止用戶直接上傳文件,危害服務器安全,程序應禁止用戶直接訪問上傳文件(即把上傳文件保存在用戶無法直接訪問的目錄)
 
4.防止文件覆蓋(UUID)

5.文件打散存儲(一個目錄下面不能存超出1000個文件)
 用hash算法生成目錄保存
 
6.設置監聽器,監聽文件上傳進度

 upload.setProgressListener(new ProgressListener(){
   public void update(long arg0, long arg1, int arg2) {
    System.out.println("當前已上傳" + arg0 + ",當前處理的文件總大小" + arg1);
   }
  });

7.臨時文件的刪除問題
 處理完每一個文件上傳後,一定要記得調用Fileitem.delete方法,刪除臨時文件
 
8.限定上傳文件類型
 判斷上傳文件後綴名

 

  1. 上一頁:
  2. 下一頁:
Copyright © 程式師世界 All Rights Reserved