日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

大数据WE阶段(十七)文件上传

發布時間:2024/4/30 编程问答 39 豆豆
生活随笔 收集整理的這篇文章主要介紹了 大数据WE阶段(十七)文件上传 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

文件上傳

一、概述

  • 在web開發中經常需要從客戶端向服務端上傳文件 , 如: 照片 、 文件 , 這些通常都需要web開發中的文件上傳技術實現。
  • 二、 文件上傳開發步驟

  • 提供一個帶有文件上傳項的表單
  • 文件上傳的輸入框必須有name屬性才能被上傳
  • 文件上傳的表單必須是Post提交 , 因為Get請求對參數的格式有種種限制如:限制大小為4kb , 只能傳輸簡單字符。。。
  • 文件上傳的表單必須設置enctype=mulipart/form-data
  • 在servlet中處理文件上傳相關的邏輯方案
  • 方式一 : 可以通過JavaEE原生的API來獲取請求中使體內容的流
  • 獲取到流中的數據在進行解析處理
  • 但是過于繁瑣 , 不推薦使用
  • 方式二: 使用開源工具實現
  • 使用開源工具實現 Apache提供的文件上傳包 – Commons-fileupload
  • 相關邏輯的開發

  • 下載并導入對應的包
  • Commons-fileupload
  • Commons-io
  • 擴展: POI Java代碼操作office的開源組件
  • 相關類詳解

  • 文件上傳工廠DiskFileItemFactory
  • public DiskFileItemFactory(int sizeThreshold , java.io.File repository)
  • sizeTHreshold :指定內存緩沖區大小
  • repository :指定臨時文件存放位置
  • 注意:
  • 文件上傳時需要將請求的實體內容全部讀取后才做處理
  • 此時需要將實體內容緩沖起來。 內存緩沖快 , 但是內存本身就不大 , 容易導致系統崩潰 。 文件緩沖慢 , 但是可以緩沖大量數據 。
  • 所以此處提供了兩個選項 ,用sizeTHreshold設置內存允許緩沖的最大 數據量 。 如果數據量大于sizeThreshold ,則使用文件緩沖 , 在repository指定的目錄下創建臨時文件來緩沖 。 如果數據小于sizeThreshold , 則使用內存緩沖
  • 文件上傳的核心類ServletFileUpload
  • ServletFileUpload sfl = new ServletFileUpload(factory);
  • boolean isMultipartContent(HttpRequest request)判斷當前上傳的表單是否是enctype=mulipart/form-data格式
  • setHeaderEncoding(String encodeing): 指定文件處理時使用的編碼
  • setFileSizeMax(long filesizemax):控制單個文件上傳的最大大小值
  • setSizeMax(long sizeMax):控制總的文件上傳的最大值
  • List parseRequest(HttpServeltRequest request):解析request對象 獲取FileItem集合
  • setProgressListener設置上傳文件的監聽
  • 文件上傳項 FileItem

    List<FileItem> parseRequest(HttpServeltRequest request)
  • 遍歷Item分別做處理
  • 判斷下一個Item是不是一個普通字段
  • isFormField():如果返回true , 則是普通字段
  • getFieldName()獲取字段名
  • getString(String encoding):獲取字段的值 , 可以再獲取字段值得時候設置字段值的編碼集
  • 如果是文件上傳項
  • getName():獲取文件名
  • getInputStream()獲取文件流
  • delete():遍歷完之后 記得刪除臨時文件
  • 三、文件上傳時需要注意的點

  • ie兼容

  • 當用戶使用ie瀏覽器上傳文件時 , 通過getName()獲取的是該文件在客戶端主機 里的絕對路徑 , 而其他瀏覽器使用getName()時獲取的僅僅是文件名 , 在創建目錄時我們需要在真實的文件名前添加服務器文件存放的路徑 ,所以ie瀏覽器上傳的文件如果不對文件名做處理則會服務器爆出路徑無效異常
  • 處理:

    if(name.contians("\\")){name = name.subString(name.lastIndexOf("\\")); }
  • 文件上傳保存位置問題
  • 文件上傳保存位置一定不能被 外界隨意訪問 , 防止用戶用瀏覽器直接訪問下載服務器資源 或者執行惡意代碼。
  • WEB-INF目錄時不能被外界直接訪問的 , 文件上傳之后要么保存在WEB-INF目錄下 , 要目放置在本地磁盤的其他位置 , 保證瀏覽無法直接訪問 。
  • 文件上傳重名問題
  • 在同一路徑下操作系統不允許文件重名 , 如果有文件重名 ,注入后來的文件會直接覆蓋原有的文件 。
  • 在文件保存時在文件名之前拼接UUID來確保文件名絕對唯一
  • 擴展:UUID是基于系統時間、CPU時鐘等參數使用哈希算法得出的值 , 是永遠不會重復的 。
  • 上傳文件保存目錄保存文件過多時系統處理困難導致無法讀取的情況
  • 一個文件夾下保存的文件過多時 , 會造成訪問緩慢 , 甚至可能造成無法訪問的情況 , 所以要想辦法將上傳的文件分目錄存儲
  • 利用hash算法的散列特性
  • 將帶有UUID的文件名根據散列算法得出一個32位的二進制字符串后轉為16進制的8位字符
  • 將得到的8位字符的字符串的每一位截取出來都作為一級路徑
  • 最終文件存放在8級的hash目錄下, 一共可能有16^8(42億多一點)個文件夾分目錄來存放文件 , 從而保證了每一個目錄都不會存放過多的文件
  • 示例:

    public class UploadServlet extends HttpServlet {public void doGet(final HttpServletRequest request, HttpServletResponse response)throws ServletException, IOException {try {response.setCharacterEncoding("utf-8");response.setContentType("text/html;charset=utf-8");//1.創建文件上傳工廠DiskFileItemFactory factory = new DiskFileItemFactory(100, new File(this.getServletContext().getRealPath("WEB-INF/temp")));//2.創建文件上傳的核心類ServletFileUpload fileUpload = new ServletFileUpload(factory);//--判斷當前文件上傳的表單是否滿足enctype=multipart/form-dataif(!fileUpload.isMultipartContent(request)){throw new RuntimeException("請使用正確的文件上傳表單上傳數據!");}//--設置文件名解析時采用的編碼fileUpload.setHeaderEncoding("utf-8");//--單個文件不能超過1MB//fileUpload.setFileSizeMax(1024 * 1024);//--總大小不能超過10MB//fileUpload.setSizeMax(10 * 1024 * 1024);//--設置上傳文件的監聽fileUpload.setProgressListener(new ProgressListener(){long begin = System.currentTimeMillis();public void update(long pBytesRead, long pContentLength,int pItems) { // System.out.print("正在讀取第"+pItems+"個上傳項。。"); // System.out.print("共"+pContentLength+"字節。。"); // System.out.print("已經讀取了"+pBytesRead+"字節。。");long leftBytes = pContentLength - pBytesRead; // System.out.print("剩余"+leftBytes+"字節。。");long now = System.currentTimeMillis();long usetime = (now - begin)/1000 ; // System.out.print("已經用時" + usetime+"秒。。");long speed = usetime == 0 ? 0 : pBytesRead / usetime / 1024; // System.out.print("上傳速度" + speed+"KB/s。。");double per = Math.round(pBytesRead * 10000.0 / pContentLength)/100.0;System.out.println("上傳百分比" + per + "%。。");long lefttime = speed == 0 ? 0 : leftBytes /1024 / speed; // System.out.println("大致剩余時間"+lefttime+"秒");request.getSession().setAttribute("progress", per);}});//--解析request得到FileItem的集合List<FileItem> items = fileUpload.parseRequest(request);//--遍歷每個item分別做處理for(FileItem item : items){if(item.isFormField()){//普通字段項String name = item.getFieldName();String value = item.getString("utf-8");System.out.println(name+"~"+value);}else{//文件上傳項String fname = item.getName();//--處理ie文件名bugif(fname.contains("\\")){fname = fname.substring(fname.lastIndexOf("\\")+1);}//--處理文件名 使其不會重復String savename = UUID.randomUUID().toString()+"_"+fname;//--文件分目錄處理//----獲取文件名的hash 轉換為16進制字符串表現形式 由于文件名隨機 所以 hash值也是散列的String hash = Integer.toHexString(savename.hashCode());//----如果hash不足8位則在前面拼接足夠8位的0while(hash.length()<8){hash += "0";}//----遍歷hash值字符串的每一個字符作為一級目錄拼接String savepath = "/WEB-INF/upload/";for(int i = 0;i<hash.length();i++){savepath += (hash.charAt(i)+"/");}//----創建出該目錄new File(this.getServletContext().getRealPath(savepath)).mkdirs();//----得到輸入流InputStream in = item.getInputStream();//----得到輸出流 路徑就是上面 hash拼接出的路徑+文件名OutputStream out = new FileOutputStream(this.getServletContext().getRealPath(savepath + "/" +savename));//----輸出數據到文件byte [] data = new byte[1024];int n = -1;while((n = in.read(data))!=-1){out.write(data,0,n);}//----關閉流in.close();out.close();//----刪除緩存文件item.delete();}}} catch (FileSizeLimitExceededException e) {response.getWriter().write("文件大小超過限制!!");} catch (Exception e) {throw new RuntimeException(e);}}public void doPost(HttpServletRequest request, HttpServletResponse response)throws ServletException, IOException {doGet(request, response);}}
  • 四、文件上傳進度條的實現

  • 在Upload.jsp頁面中 ,為表單提交時間增加函數觸發,增加定時器 , 每隔一段時間通過Ajax向服務器發送請求獲取最新的上傳進度
  • 在UploadServlet中為文件上傳注冊監聽器 , 計算各種指標 , 存入session中
  • 在UploadProgressServlet中從session中獲取上傳進度信息 , 作為響應發回給Ajax后設置進度條長度。
  • 總結

    以上是生活随笔為你收集整理的大数据WE阶段(十七)文件上传的全部內容,希望文章能夠幫你解決所遇到的問題。

    如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。