欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

java文件上傳技術(shù)深入剖析

 更新時(shí)間:2016年10月11日 08:51:16   作者:xanlv  
這篇文章主要為大家詳細(xì)介紹了java文件上傳技術(shù)深入剖析,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下

本文實(shí)例為大家分享了java文件上傳技術(shù),供大家參考,具體內(nèi)容如下

這里寫圖片描述

表單:
客戶端發(fā)送HTTP必須使用multipart/form-data數(shù)據(jù)類型,表示復(fù)合數(shù)據(jù)類型。即:
在表單中使用html標(biāo)簽。

需要的包:
        Commons-fileupload.jar,核心上傳文件工具都在這個(gè)包中。
        commons-io.jar – 上傳文件所需要的包

上傳文件類詳解:
DiskFileItemFactory-創(chuàng)建監(jiān)時(shí)文件目錄,指是緩存區(qū)大小
ServletFileUpload用于解析HttpServletRequest。返回一組文件對(duì)象。
FileItem – 表示用戶上傳的每一個(gè)文件對(duì)像。

<%@ page language="java" import="java.util.*" pageEncoding="UTF-8"%>

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
 <head>

  <title>文件上傳演示</title>
 </head>

 <body>
  <font color="red" size="6">過渡板--了解底層</font>
  <!-- multipart/form-data:多部分(不但有文件,也有部分) -->
  <form action="<%=request.getContextPath()%>/upload0" method="post" enctype="multipart/form-data">
    文件:<input type="file" name="file"/>
    <input type="submit" value="上傳"/> 
    <!-- 上傳的文件名不能為中文,否則獲取的文件名是亂碼,不過下面的例子可以解決這個(gè)問題 -->  
  </form>
  <br/>


  <font color="red" size="6">使用apache文件上傳工具實(shí)現(xiàn)文件上傳</font>
  <!-- application/x-www-form-urlencoded -->
  <form action="<%=request.getContextPath()%>/upload" method="post" enctype="multipart/form-data">
    文件:<input type="file" name="file"/>
    <input type="submit" value="上傳"/>  
  </form>


  <font color="red" size="6">使用apache文件上傳工具實(shí)現(xiàn)文件上傳2(解決文件名亂碼)</font>
  <p>
  POST1(普通表單):enctype=application/x-www-form-urlencoded(默認(rèn)值)
  </p>
  <p>
  POST2(上傳文件表單):enctype=multipart/form-data:多部分(不但有文件,也有部分)
  </p>
  <form action="<%=request.getContextPath()%>/upload2" method="post" enctype="multipart/form-data">
    文件:<input type="file" name="file"/><!-- POST2(上傳文件表單) --><br/>
    文件說明:<input type="text" name="desc"/><!-- POST1(普通表單) --><br/><br/>
    文件2:<input type="file" name="file"/><br/>
    文件說明2:<input type="text" name="desc"/>
    <input type="submit" value="上傳"/>  
  </form>
  <font color="red" size="6">使用apache文件上傳工具實(shí)現(xiàn)文件上傳3(文件打散)</font>
  <!-- POST1(普通表單):enctype=application/x-www-form-urlencoded(默認(rèn)值) -->
  <!-- POST2(上傳文件表單):enctype=multipart/form-data:多部分(不但有文件,也有部分) -->
  <form action="<%=request.getContextPath()%>/upload3" method="post" enctype="multipart/form-data">
    文件:<input type="file" name="file"/><!-- POST2(上傳文件表單) --><br/>
    文件說明:<input type="text" name="desc"/><!-- POST1(普通表單) --><br/><br/>
    文件2:<input type="file" name="file"/><br/>
    文件說明2:<input type="text" name="desc"/>
    <input type="submit" value="上傳"/>  
  </form>
 </body>
</html>

這里寫圖片描述

過渡板–了解底層

package cn.hncu.servlet;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.PrintWriter;

import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

public class Upload0Servlet extends HttpServlet {


  public void doPost(HttpServletRequest request, HttpServletResponse response)
      throws ServletException, IOException {

    InputStream in=request.getInputStream();
    BufferedReader br=new BufferedReader(new InputStreamReader(in));
    String line;
    while((line=br.readLine())!=null){
      System.out.println(line);
    }
  }

}

這里寫圖片描述

這里寫圖片描述

使用apache文件上傳工具實(shí)現(xiàn)文件上傳

package cn.hncu.servlet;

import java.io.File;
import java.io.IOException;
import java.io.PrintWriter;
import java.util.List;
import java.util.UUID;

import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.apache.commons.fileupload.FileItem;
import org.apache.commons.fileupload.FileUploadException;
import org.apache.commons.fileupload.disk.DiskFileItemFactory;
import org.apache.commons.fileupload.servlet.ServletFileUpload;
import org.apache.commons.io.FileUtils;

public class UploadServlet extends HttpServlet {

  public void doGet(HttpServletRequest request, HttpServletResponse response)
      throws ServletException, IOException {

    response.setContentType("text/html");
    PrintWriter out = response.getWriter();
    out.println("<!DOCTYPE HTML PUBLIC \"-//W3C//DTD HTML 4.01 Transitional//EN\">");
    out.println("<HTML>");
    out.println(" <HEAD><TITLE>A Servlet</TITLE></HEAD>");
    out.println(" <BODY>");
    out.print("不支持Get方式上傳。。。。。。");
    out.println(" </BODY>");
    out.println("</HTML>");
    out.flush();
    out.close();
  }

  public void doPost(HttpServletRequest request, HttpServletResponse response)
      throws ServletException, IOException {

        //在服務(wù)器上,為所有上傳文件指定一個(gè)存放目錄
    String path=getServletContext().getRealPath("/upload");
    System.out.println("path:"+path);
    File dir=new File(path);
    if(!dir.exists()){
      dir.mkdirs();
    }

    //創(chuàng)建一個(gè)基于硬盤的工廠
    //DiskFileItemFactory disk = new DiskFileItemFactory();
    //設(shè)置臨時(shí)目錄(建議設(shè)計(jì)臨時(shí)目錄,否則會(huì)使用系統(tǒng)臨時(shí)目錄。)
    //disk.setRepository(new File(“d:/a”));
    //3、 設(shè)置向硬盤寫數(shù)據(jù)的緩沖區(qū)大小
disk.setSizeThreshold(1024*4);//當(dāng)文件大于此設(shè)置時(shí),將會(huì)在臨時(shí)目錄下形成臨時(shí)文件


    //設(shè)置臨時(shí)文件緩沖區(qū)大小--8K緩沖,臨時(shí)文件地址
    DiskFileItemFactory f=new DiskFileItemFactory(1024*8, new File("d:/a"));
    //上傳工具--創(chuàng)建用于解析的對(duì)像
    ServletFileUpload upload=new ServletFileUpload(f);
    upload.setFileSizeMax(1024*1024*5);//設(shè)置上傳的單個(gè)文件最大為5M
    //設(shè)置上傳文件的最大大小,如果是多個(gè)文件,則為多個(gè)文件的和最大8M
    upload.setSizeMax(1024*1024*8);//設(shè)置所有上傳的文件大小之和最大為8M
    //使用解析工具解析
    try {
      List<FileItem> list=upload.parseRequest(request);
      for(FileItem fI:list){
        System.out.println("文件內(nèi)容類型:"+fI.getContentType());//文件內(nèi)容類型:text/plain
        System.out.println("文件名:"+fI.getName());//文件名:C:\Users\adl1\Desktop\a.txt
        String ext=fI.getName().substring(fI.getName().lastIndexOf("."));//.txt
        String uuid=UUID.randomUUID().toString().replace("-", "");
        String fileName=uuid+ext;
//       FileUtils.copyInputStreamToFile(fI.getInputStream(), new File("d:/a/d/a.txt"));//寫死了
        //fI.getInputStream()是真正文件信息
        FileUtils.copyInputStreamToFile(fI.getInputStream(), new File(path+"/"+fileName));//寫活了
      }
    } catch (FileUploadException e) {
      e.printStackTrace();
    }


  }

}

在這個(gè)地方存儲(chǔ)上傳的文件

這里寫圖片描述

上傳信息:

這里寫圖片描述

上傳結(jié)果:

這里寫圖片描述

使用apache文件上傳工具實(shí)現(xiàn)文件上傳2(解決文件名亂碼)

package cn.hncu.servlet;

import java.io.File;
import java.io.IOException;
import java.io.PrintWriter;
import java.util.List;
import java.util.UUID;

import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.apache.commons.fileupload.FileItem;
import org.apache.commons.fileupload.FileUploadException;
import org.apache.commons.fileupload.disk.DiskFileItemFactory;
import org.apache.commons.fileupload.servlet.ServletFileUpload;
import org.apache.commons.io.FileUtils;

public class Upload2Servlet extends HttpServlet {

  public void doGet(HttpServletRequest request, HttpServletResponse response)
      throws ServletException, IOException {


    response.setContentType("text/html");
    //如果是含上傳文件的表單(POST2),該劇只能設(shè)置所上傳文件的文件名中的編碼(解決他的中文亂碼)
    //但不能解決在POST2方式下的普通表單組件的中文亂碼
    PrintWriter out = response.getWriter();
    out.println("<!DOCTYPE HTML PUBLIC \"-//W3C//DTD HTML 4.01 Transitional//EN\">");
    out.println("<HTML>");
    out.println(" <HEAD><TITLE>A Servlet</TITLE></HEAD>");
    out.println(" <BODY>");
    out.print("不支持Get方式上傳。。。。。。");
    out.println(" </BODY>");
    out.println("</HTML>");
    out.flush();
    out.close();
  }

  public void doPost(HttpServletRequest request, HttpServletResponse response)
      throws ServletException, IOException {

    //第一步
    //普通的form表單(POST1),下面這句可以設(shè)置普通表單組件內(nèi)容的編碼(能夠解決它們的中文亂碼問題)
    request.setCharacterEncoding("utf-8");
    //如果是含上傳文件的表單(POST2),該句只能設(shè)置所上傳文件的文件名中的編碼(解決它的中文亂碼)。但不能解決普通表單組件的亂碼(不能設(shè)它編碼)


    //在服務(wù)器上,為所有上傳文件指定一個(gè)存放目錄
    String path=getServletContext().getRealPath("/upload");
    System.out.println("path:"+path);
    File dir=new File(path);
    if(!dir.exists()){
      dir.mkdirs();
    }


    //設(shè)置臨時(shí)文件緩沖區(qū)大小--8K緩沖,臨時(shí)文件地址
    DiskFileItemFactory f=new DiskFileItemFactory(1024*8, new File("d:/a"));
    //上傳工具
    ServletFileUpload upload=new ServletFileUpload(f);
    upload.setFileSizeMax(1024*1024*5);//設(shè)置上傳的單個(gè)文件最大為5M
    upload.setSizeMax(1024*1024*8);//設(shè)置所有上傳的文件大小之和最大為8M
    //使用解析工具解析
    try {
      List<FileItem> list=upload.parseRequest(request);
      for(FileItem fI:list){
        if((fI.isFormField())){//如果是普通表單組件:checkbox,radio,password...
//         String desc=fI.getString();
          System.out.println("fI.getString():"+fI.getString());
          //第二步
          String desc=fI.getString("utf-8");
          //該句設(shè)置普通表單組件內(nèi)容編碼
          System.out.println("編碼后:"+desc);
        }else{
          String ext=fI.getName().substring(fI.getName().lastIndexOf("."));//.txt
          String uuid=UUID.randomUUID().toString().replace("-", "");
          String fileName=uuid+ext;
          //fI.getInputStream()是真正文件信息
          FileUtils.copyInputStreamToFile(fI.getInputStream(), new File(path+"/"+fileName));//寫活了
        }
      }
    } catch (FileUploadException e) {
      e.printStackTrace();
    }
  }
}

上傳信息:

這里寫圖片描述

上傳結(jié)果:
這里寫圖片描述 

使用apache文件上傳工具實(shí)現(xiàn)文件上傳3(文件打散)

用Hash目錄優(yōu)化文件存儲(chǔ):
Hash目錄是一種優(yōu)化文件存儲(chǔ)性能的方法。無論是Windows還是Linux,無論是NTFS還是ext3,每個(gè)目錄下所能容納的項(xiàng)目數(shù)是有限的。
并不是不能保存,而是當(dāng)項(xiàng)目數(shù)量過大的時(shí)候,會(huì)降低文件索引速度,
所以權(quán)衡一個(gè)目錄下應(yīng)該保存多少文件是很必要的。保存得多了會(huì)影響性能,保存得少了會(huì)造成目錄太多和空間浪費(fèi)。所以當(dāng)保存大批文件的時(shí)候,
需要有一種算法能將文件比較均勻地“打散”在不同的子目錄下以提高每一級(jí)的索引速度,這種算法就是 Hash。通常用的MD5、sha1等都可以用來做Hash目錄,我的Session里也同樣使用了MD5,取得sessionID的第一位和第九位,這就構(gòu)成了兩級(jí)Hash路徑,也就是說,系統(tǒng)把所有的Session文件分散到了16×16=256個(gè)子目錄下。假設(shè)Linux每個(gè)目錄下保存1000個(gè)文件可以獲得最好的空間性能比,那么系統(tǒng)在理想情況下可以同時(shí)有256000個(gè)session文件在被使用。

package cn.hncu.servlet;

import java.io.File;
import java.io.IOException;
import java.io.PrintWriter;
import java.util.List;
import java.util.UUID;

import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.apache.commons.fileupload.FileItem;
import org.apache.commons.fileupload.FileUploadException;
import org.apache.commons.fileupload.ProgressListener;
import org.apache.commons.fileupload.disk.DiskFileItemFactory;
import org.apache.commons.fileupload.servlet.ServletFileUpload;
import org.apache.commons.io.FileUtils;

public class Upload3Servlet extends HttpServlet {

  public void doGet(HttpServletRequest request, HttpServletResponse response)
      throws ServletException, IOException {


    response.setContentType("text/html");
    //如果是含上傳文件的表單(POST2),該劇只能設(shè)置所上傳文件的文件名中的編碼(解決他的中文亂碼)
    //但不能解決在POST2方式下的普通表單組件的中文亂碼
    PrintWriter out = response.getWriter();
    out.println("<!DOCTYPE HTML PUBLIC \"-//W3C//DTD HTML 4.01 Transitional//EN\">");
    out.println("<HTML>");
    out.println(" <HEAD><TITLE>A Servlet</TITLE></HEAD>");
    out.println(" <BODY>");
    //獲取GET方式的url中“?”號(hào)后面的部分
    //http://localhost:8080/servletDemo3/upload?name=Jack&sex=male
    String qStr = request.getQueryString();
    System.out.println("qStr: "+qStr);//qStr: name=Jack&sex=male
    out.print("不支持Get方式上傳。。。。。。");
    out.println(" </BODY>");
    out.println("</HTML>");
    out.flush();
    out.close();
  }

  public void doPost(HttpServletRequest request, HttpServletResponse response)
      throws ServletException, IOException {

    response.setContentType("text/html;charset=utf-8");
    PrintWriter out = response.getWriter();
    //1防黑: 防護(hù)前端采用POST1方式提交
    //法1
    /*
    String type=request.getContentType();
    if(!type.contains("multipart/form-data")){
      out.println("不支持普通表單提交");
      return;
    }*/
    //法2
    boolean boo = ServletFileUpload.isMultipartContent(request);
    if(!boo){
      out.println("不支持普通表單提交");
      return;
    }

    //第一步
    //普通的form表單(POST1),下面這句可以設(shè)置普通表單組件內(nèi)容的編碼(能夠解決它們的中文亂碼問題)
    request.setCharacterEncoding("utf-8");
    //如果是含上傳文件的表單(POST2),該句只能設(shè)置所上傳文件的文件名中的編碼(解決它的中文亂碼)。但不能解決普通表單組件的亂碼(不能設(shè)它編碼)


    //在服務(wù)器上,為所有上傳文件指定一個(gè)存放目錄
    String path=getServletContext().getRealPath("/upload");
    System.out.println("path:"+path);
    File dir=new File(path);
    if(!dir.exists()){
      dir.mkdirs();
    }


    //設(shè)置臨時(shí)文件緩沖區(qū)大小--8K緩沖,臨時(shí)文件地址
    DiskFileItemFactory f=new DiskFileItemFactory(1024*8, new File("d:/a"));
    //上傳工具
    ServletFileUpload upload=new ServletFileUpload(f);
    upload.setFileSizeMax(1024*1024*5);//設(shè)置上傳的單個(gè)文件最大為5M
    upload.setSizeMax(1024*1024*8);//設(shè)置所有上傳的文件大小之和最大為8M

    //▲4上傳進(jìn)度監(jiān)聽
    upload.setProgressListener(new ProgressListener(){
      private double pre=0D;
      @Override//參數(shù)1:已上傳多少字節(jié) 參數(shù)2:一共多少字節(jié)  參數(shù)3:第幾個(gè)文件(序號(hào)從1開始)
      public void update(long pByteRead, long pContentLength, int pItems) {
        double d = 1.0*pByteRead/pContentLength*100;
        System.out.println(d+"%");
            if(pre!=d){
              System.out.println(d+"%");
              pre=d;
            }
      }
    });


    //使用解析工具解析
    try {
      List<FileItem> list=upload.parseRequest(request);
      for(FileItem fI:list){
        if((fI.isFormField())){//如果是普通表單組件:checkbox,radio,password...
//         String desc=fI.getString();
          System.out.println("fI.getString():"+fI.getString());
          //第二步
          String desc=fI.getString("utf-8");
          //該句設(shè)置普通表單組件內(nèi)容編碼
          System.out.println("編碼后:"+desc);
        }else{
          //防護(hù):過濾掉沒選擇文件的空文件組件
          if(fI.getSize()<=0){
            continue;//讀下一個(gè)文件
          }

          System.out.println("文件內(nèi)容類型:"+fI.getContentType());//文件內(nèi)容類型:text/plain
          System.out.println("文件名:"+fI.getName());//文件名:C:\Users\adl1\Desktop\a.txt

          String ext=fI.getName().substring(fI.getName().lastIndexOf("."));//.txt
          String uuid=UUID.randomUUID().toString().replace("-", "");
          String fileName=uuid+ext;

          //文件目錄打散技術(shù)
          String dir1=Integer.toHexString(uuid.hashCode()&0x0f);
          String dir2=Integer.toHexString((uuid.hashCode()&0xf0)>>4);


          //fI.getInputStream()是真正文件信息
          FileUtils.copyInputStreamToFile(fI.getInputStream(), new File(path+"/"+dir1+"/"+dir2+"/"+fileName));//寫活了
        }
      }
    } catch (FileUploadException e) {
      e.printStackTrace();
    }
  }
}

打散信息:

這里寫圖片描述

打散結(jié)果:

文件1:

這里寫圖片描述 

文件2:

這里寫圖片描述

演示上傳進(jìn)度原理

這里寫圖片描述

以上就是本文的全部?jī)?nèi)容,希望對(duì)大家的學(xué)習(xí)有所幫助,也希望大家多多支持腳本之家。

相關(guān)文章

  • 實(shí)戰(zhàn)SpringBoot集成JWT實(shí)現(xiàn)token驗(yàn)證

    實(shí)戰(zhàn)SpringBoot集成JWT實(shí)現(xiàn)token驗(yàn)證

    本文詳細(xì)講解了SpringBoot集成JWT實(shí)現(xiàn)token驗(yàn)證,文中通過示例代碼介紹的非常詳細(xì)。對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下
    2021-12-12
  • spring boot使用WebClient調(diào)用HTTP服務(wù)代碼示例

    spring boot使用WebClient調(diào)用HTTP服務(wù)代碼示例

    這篇文章主要介紹了spring boot使用WebClient調(diào)用HTTP服務(wù)代碼示例,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下
    2019-12-12
  • 詳解Spring Security中權(quán)限注解的使用

    詳解Spring Security中權(quán)限注解的使用

    這篇文章主要為大家詳細(xì)介紹一下Spring Security中權(quán)限注解的使用方法,文中的示例代碼講解詳細(xì),對(duì)我們學(xué)習(xí)或工作有一定參考價(jià)值,需要的可以參考一下
    2022-05-05
  • Java關(guān)鍵字synchronized原理與鎖的狀態(tài)詳解

    Java關(guān)鍵字synchronized原理與鎖的狀態(tài)詳解

    在Java當(dāng)中synchronized關(guān)鍵字通常是用來標(biāo)記一個(gè)方法或者代碼塊。本文將通過示例為大家詳細(xì)介紹一下Synchronized的各種使用方法,需要的可以參考一下
    2022-08-08
  • Java實(shí)現(xiàn)的質(zhì)因數(shù)分解操作示例【基于遞歸算法】

    Java實(shí)現(xiàn)的質(zhì)因數(shù)分解操作示例【基于遞歸算法】

    這篇文章主要介紹了Java實(shí)現(xiàn)的質(zhì)因數(shù)分解操作,結(jié)合實(shí)例形式較為詳細(xì)的分析了Java基于遞歸算法實(shí)現(xiàn)針對(duì)整數(shù)的質(zhì)因數(shù)分解相關(guān)操作技巧,需要的朋友可以參考下
    2018-03-03
  • Java正則表達(dá)式處理特殊字符轉(zhuǎn)義的方法

    Java正則表達(dá)式處理特殊字符轉(zhuǎn)義的方法

    由于正則表達(dá)式定了一些特殊字符,而有時(shí)候需要對(duì)這些特殊字符進(jìn)行匹配的話就需要進(jìn)行轉(zhuǎn)義了,下面這篇文章主要給大家介紹了Java正則表達(dá)式處理特殊字符轉(zhuǎn)義的方法,需要的朋友可以參考借鑒,下面來一起看看吧。
    2017-01-01
  • Java數(shù)據(jù)結(jié)構(gòu)之加權(quán)無向圖的設(shè)計(jì)實(shí)現(xiàn)

    Java數(shù)據(jù)結(jié)構(gòu)之加權(quán)無向圖的設(shè)計(jì)實(shí)現(xiàn)

    加權(quán)無向圖是一種為每條邊關(guān)聯(lián)一個(gè)權(quán)重值或是成本的圖模型。這種圖能夠自然地表示許多應(yīng)用。這篇文章主要介紹了加權(quán)無向圖的設(shè)計(jì)與實(shí)現(xiàn),感興趣的可以了解一下
    2022-11-11
  • 淺談Arrays.asList()方法的使用

    淺談Arrays.asList()方法的使用

    本文主要介紹了Arrays.asList()方法的使用。具有很好的參考價(jià)值,下面跟著小編一起來看下吧
    2017-02-02
  • 詳解 Java繼承關(guān)系下的構(gòu)造方法調(diào)用

    詳解 Java繼承關(guān)系下的構(gòu)造方法調(diào)用

    這篇文章主要介紹了詳解 Java繼承關(guān)系下的構(gòu)造方法調(diào)用的相關(guān)資料,希望通過本文能幫助到大家,讓大家理解掌握這部分內(nèi)容,需要的朋友可以參考下
    2017-10-10
  • Java中Socket用法詳解

    Java中Socket用法詳解

    本文詳細(xì)講解了Java中Socket的用法,文中通過示例代碼介紹的非常詳細(xì)。對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2021-12-12

最新評(píng)論