자바 파일 업로드 전면 분석

17454 단어 Java파일 업로드
파일 업로드 란 무엇 입 니까?
파일 업로드 란 사용자 의 정 보 를 저장 하 는 것 이다.
파일 업로드 가 왜 필요 합 니까?
사용자 가 등록 할 때 사진 을 제출 해 야 할 수도 있 습 니 다.그럼 이 사진 은 저장 해 야 지.
업로드 구성 요소(도구)는 왜 우리 가 업로드 도 구 를 사용 해 야 합 니까?
왜 우 리 는 구성 요 소 를 올 려 야 합 니까?클 라 이언 트 의 데 이 터 를 가 져 오 려 면 getParameter()방법 으로 가 져 옵 니 다.
파일 데 이 터 를 업로드 하 는 것 은 MIME 프로 토 콜 을 통 해 분할 되 었 고 폼 은 바 이 너 리 패키지 가 되 었 습 니 다.즉,getParameter()는 업로드 파일 의 데 이 터 를 가 져 올 수 없습니다.
우선 파일 업로드 http 가 어떻게 데 이 터 를 가 져 갔 는 지 살 펴 보 겠 습 니 다.
jsp 페이지,폼 은 enctype:multipart/form-data 를 지정 해 야 합 니 다.

<form action="${pageContext.request.contextPath }/servlet/UploadServlet1" enctype="multipart/form-data" method="post">
        :<input type="text" name="username"><br/>
        1:<input type="file" name="file1"><br/>
        2:<input type="file" name="file2"><br/>
    <input type="submit" value="  ">
  </form>
http 패키지

Servlet 에서 getParameter()를 사용 하여 데 이 터 를 가 져 오 려 고 시도 합 니 다.

String ss = request.getParameter("username");
System.out.println(ss);
getParameter 를 직접 사용 하면 데 이 터 를 얻 을 수 없습니다.

그럼 우리 어 떡 하지???request 대상 은 ServletInputStream 흐름 을 제공 하여 데 이 터 를 읽 어 줍 니 다.
우 리 는 파일 을 읽 어 보 았 다.

ServletInputStream inputStream = request.getInputStream();

    byte[] bytes = new byte[1024];
    int len = 0;

    while ((len = inputStream.read(bytes)) > 0) {
      System.out.println(new String(bytes, 0, len));
    }
jsp 페이지 에 input 컨트롤 을 하나 더 추가 합 니 다.

<input type="text" name="password">
내 가 업로드 한 텍스트 파일 의 내용 은 111111 입 니 다.읽 기 효 과 는 다음 과 같 습 니 다.

이제 우 리 는 파일 을 업로드 한 데 이 터 를 읽 을 수 있 습 니 다.그러나 지금 문 제 는 또 왔 습 니 다.어떻게 파일 을 업로드 하여 서버 에 전송 하 는 데이터 와 분리 합 니까?위 에서 그림 에서 우 리 는 이미 보 았 다.그들 은 한데 섞 인 것 이다.
우리 의 일반적인 방법 으로 는 분리 하기 어렵 기 때문에 구성 요 소 를 업로드 해 야 합 니 다.
업로드 구성 요 소 는 두 가지 FileUpload[조작 이 복잡 합 니 다]SamrtUpload[조작 이 간단 합 니 다]FileUpload
FileUpload 구성 요 소 를 사용 하려 면 jar 패키지 두 개 를 가 져 와 야 합 니 다.
commons-io Commons-fileupload 개발 절차 생 성 해상도 기 공장 대상[DiskFileItemFactory]해상도 기 공장 생 성 해상도 기[ServletFileUpload]호출 해상도 기 방법 으로 request 대상 을 분석 하고 모든 업로드 내용[list]을 얻어 list 를 옮 겨 다 니 며 각 대상 이 업로드 파일 인지 여 부 를 판단 합 니 다.일반 폼 필드 라면,필드 이름과 필드 값 을 가 져 옵 니 다.파일 을 업로드 하 는 경우 InputSteam 방법 으로 입력 흐름 을 가 져 와 업 로드 된 데 이 터 를 읽 고 빠르게 입문 합 니 다.

try{
    
      //1.       
      DiskFileItemFactory factory = new DiskFileItemFactory();
      
      //2.     
      ServletFileUpload upload = new ServletFileUpload(factory);
      
      //3.         
      if(!upload.isMultipartContent(request)){
        //         ,             
        return;
      }
      
      //     ,            
      List<FileItem> list = upload.parseRequest(request); //FileItem
      
      //  list,                fileItem  
      for(FileItem item : list){
        
        if(item.isFormField()){
          //         
          String name = item.getFieldName(); //        
          String value = item.getString();
          System.out.println(name + "=" + value);
        }else{
          //       
          String filename = item.getName(); //        C:\Documents and Settings\ThinkPad\  \1.txt
          filename = filename.substring(filename.lastIndexOf("\\")+1);
          InputStream in = item.getInputStream();  //      
          int len = 0;
          byte buffer[]= new byte[1024];
          
          
          String savepath = this.getServletContext().getRealPath("/upload");
          FileOutputStream out = new FileOutputStream(savepath + "\\" + filename); // upload       
          while((len=in.read(buffer))>0){
            out.write(buffer, 0, len);
          }
          
          in.close();
          out.close();
        }
      }
    
    }catch (Exception e) {
      e.printStackTrace();
    }
테스트 일반 필드 와 업로드 한 파일 을 모두 읽 을 수 있 습 니 다!

SmartUpload
SmartUpload 구성 요 소 를 사용 하려 면 smartupload.jar 개발 패 키 지 를 가 져 와 야 합 니 다.
쾌속 입문

//     
    SmartUpload smartUpload = new SmartUpload();

    //       
    smartUpload.initialize(this.getServletConfig(), request, response);


    try {

      //    
      smartUpload.upload();

      //      ,   request              。      smartUpload
      String password = smartUpload.getRequest().getParameter("password");
      System.out.println(password);

      //   uploadFile    
      smartUpload.save("uploadFile");


    } catch (SmartUploadException e) {
      e.printStackTrace();
    }
테스트
마찬가지 로,우 리 는 파일 을 uploadFile 폴 더 에 업로드 할 수 있다.코드 양도 확실히 많이 줄 었 어!
일반 필드 의 인자 도 가 져 올 수 있 습 니 다.

파일 이름 의 중국어 난 코드 와 데 이 터 를 업로드 하 는 중국어 난 코드 를 중국어 로 바 꾸 면 난 코드 가 됩 니 다.

양식 에 제출 된 중국어 데이터 도 엉망 이 되 었 다.

위 에서 이미 말 했 듯 이 파일 의 데 이 터 를 업로드 하 는 폼 은 바 이 너 리 패 키 징 을 했 기 때문에 request 를 사용 하여 데이터 인 코딩 을 하면 폼 이 제출 한 데이터 에 효과 가 없습니다!
FileUpload 난 코드 해결
FileUpload 를 사용 하여 어 지 러 운 문 제 를 해결 하 는 것 은 매우 간단 하 다.
중국어 파일 이름 난 장 판 을 해결 하고 해석 기 를 받 은 후 해석 기의 인 코딩 을 UTF-8 로 직접 설정 하면 됩 니 다!

//  upload   
fileUpload.setHeaderEncoding("UTF-8");
폼 데이터 의 난 장 판 을 해결 하고 폼 값 을 가 져 올 때 UTF-8 인 코딩 에 따라 가 져 옵 니 다.

String value = fileItem.getString("UTF-8");
효과:

SmartUpload 난 코드 해결
이 구성 요 소 는 어 지 러 운 문 제 를 해결 하 는 데 좀 번 거 로 워 서 인터넷 에서 여러 가지 방법 을 찾 았 지만 간단 한 것 을 찾 지 못 했다.
따라서 데이터 가 중국어 와 관련 되 지 않 으 면 SmartUpload 구성 요 소 를 사용 하고 중국어 데이터 와 관련 되면 FileUpload 구성 요 소 를 사용 하 세 요!
여러 파일 업로드,동적 업로드 컨트롤 추가
내 가 지금 업로드 할 파일 이 여러 개 있 고 업로드 할 갯 수 는 확실 하지 않다 고 가정 하 자.그럼 우리 어 떡 하지??
우 리 는 파일 을 업로드 하 는 컨트롤 을 페이지 에 많이 표시 할 수 없습니다.이렇게 하면 아름 답지 않 습 니 다.사용자 가 그렇게 많은 컨트롤 을 사용 하지 못 한다 면 낭비 할 것 입 니 다.
따라서 파일 을 업로드 하 는 컨트롤 을 동적 으로 추가 하려 면 사용자 가 파일 을 업로드 하려 면 동적 으로 컨트롤 을 생 성하 면 됩 니 다!
분석 하 다.
페이지 에 컨트롤 을 동적 으로 생 성 하려 면 자바 스 크 립 트 코드 를 사용 하 는 것 이 아 닙 니 다.
그럼 우 리 는 어떻게 해 야 되 지?
이렇게 하 세 요:사용자 가 파일 을 업로드 하려 고 할 때 단 추 를 누 르 고 이벤트 바 인 딩 을 누 르 면 파일 업로드 컨트롤 을 생 성 합 니 다.
더욱 완벽 하 게 하기 위해 파일 업로드 컨트롤 이 생 성 될 때마다 삭제 단 추 를 제공 하여 이 컨트롤 을 삭제 합 니 다!
우 리 는 div 를 사용 하여 우리 가 생 성 할 컨트롤 과 삭제 단 추 를 불 러 와 야 합 니 다.사용자 가 삭 제 를 클릭 할 때 삭제 단추 와 파일 업로드 컨트롤 을 함께 숨겨 야 합 니 다.그래서 내장 div 를 사용 하 는 것 이 좋 습 니 다!
코드 페이지 코드:

<table>
  <tr>
    <td>    :</td>
    <td><input type="text" name="username"></td>
  </tr>
  <tr>
    <td>      </td>
    <td><input type="button" value="      "> </td>
  </tr>
  <tr>
    <td>
      <div>
      </div>
    </td>
  </tr>
</table>
javaScript 코드

<script type="text/javascript">
    function addUploadFile() {
      //        
      var input = document.createElement("input");
      input.type = 'file';
      input.name = 'fileName';
      //      
      var del = document.createElement("input");
      del.type = 'button';
      del.value = '  ';
      //     div
      var innerDiv = document.createElement("div");
      //          div 
      innerDiv.appendChild(input);
      innerDiv.appendChild(del);
      //    div  ,    div     div 
      var outterDiv = document.getElementById("file");
      outterDiv.appendChild(innerDiv);
      //         
      del.onclick = function dele() {
        //    div remove      div  
        this.parentNode.parentNode.removeChild(this.parentNode);
      }
    }
  </script>
파일 업로드 세부 사항 은 업로드 파일 의 크기 가 우리 가 설정 한 파일 의 크기 보다 크 면 업로드 할 때 임시 파일 로 업로드 데 이 터 를 저장 합 니 다.업로드 가 끝 난 후에 우 리 는 임시 파일 업로드 파일 의 위 치 를 삭제 해 야 합 니 다.WEB 서버 관리 하에 서 는 안 됩 니 다.그렇지 않 으 면 안전 문제 가 발생 할 수 있 습 니 다.[다른 사람들 은 수단 을 통 해 업로드 파일 을 수정 할 수 있 습 니 다]업로드 파일 이름 이 같 으 면 원래 의 업로드 파일 을 덮어 씁 니 다.우 리 는 하나 밖 에 없 는 파일 이름 을 만들어 야 한다.사용자 수가 많 으 면 파일 을 많이 업로드 합 니 다.그러면 우 리 는 한 디 렉 터 리 에 모든 업로드 파일 을 저장 해 서 는 안 된다.그러면 디스크 가 무 너 질 수 있다.그래서 우 리 는 올 린 파일 을 다른 디 렉 터 리 로 흩 어 뜨 려 야 한다.분석 하 다.
임시 파일 문 제 를 삭제 하 는 것 은 매우 간단 합 니 다.모든 작업 이 끝 난 후에 FileItem 의 delete()방법 을 사용 하면 됩 니 다.
업로드 파일 의 위 치 를 WEB 서버 관리 하에 있 지 못 하 게 합 니 다.업로드 파일 의 위 치 를 WEB-INF/디 렉 터 리 에 두 면 됩 니 다!
파일 이름 이 같은 문 제 는 UUID+사용자 가 업로드 한 파일 이름 으로 업로드 파일 이름 을 저장 할 수 있 습 니 다.이런 파일 이름 은 유일무이한 것 이다.
올 린 파일 을 분산 시 키 려 면 HashCode 알고리즘 을 사용 하여 분산 시 켜 야 합 니 다.
낮은 4 비트 1 급 디 렉 터 리 생 성 5-8 비트 2 급 디 렉 터 리 코드 생 성
다음은 저희 가 비교적 완벽 한 업로드 파일 코드 를 쓰 겠 습 니 다.
hashCode 알고리즘 으로 저 장 된 디 렉 터 리 를 분산 시 킵 니 다.

private String makeDirPath(String fileName, String path) {

    //                 
    int hashCode = fileName.hashCode();
    int dir1 = hashCode & 0xf;
    int dir2 = (hashCode & 0xf0) >> 4;

    String dir = path + "\\" + dir1 + "\\" + dir2;

    //        ,     
    File file = new File(dir);
    if (!file.exists()) {

      file.mkdirs();
    }
    //     
    return dir;

  }
유일한 파일 이름 만 들 기

private String makeFileName(String fileName) {

    //      UUID        ,           。
    return UUID.randomUUID().toString() + "_"+ fileName;

  }
업로드 코드

//    
    DiskFileItemFactory factory = new DiskFileItemFactory();

    //         
    ServletFileUpload fileUpload = new ServletFileUpload(factory);

    //  upload   
    fileUpload.setHeaderEncoding("UTF-8");

    //         
    if(!fileUpload.isMultipartContent(request)){
      //         ,             
      return;
    }

    try {

      //  request  ,  List【          】
      List<FileItem> list = fileUpload.parseRequest(request);

      //  List,                  
      for (FileItem fileItem : list) {

        //        
        if (fileItem.isFormField()) {

          //          
          String name = fileItem.getFieldName();
          String value = fileItem.getString("UTF-8");

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

          //       

          //      【     】
          String fileName = fileItem.getName();

          //     
          fileName = fileName.substring(fileName.lastIndexOf("\\") + 1);

          //          
          fileName = makeFileName(fileName);

          InputStream inputStream = fileItem.getInputStream();

          //       ,          
          String path = this.getServletContext().getRealPath("/WEB-INF/uploadFile");

          //          
          String realPath = makeDirPath(fileName, path);

          FileOutputStream outputStream = new FileOutputStream(realPath + "\\" + fileName);

          byte[] bytes = new byte[1024];
          int len = 0;
          while ((len = inputStream.read(bytes)) > 0) {
            outputStream.write(bytes, 0, len);
          }

          inputStream.close();
          outputStream.close();

          //         
          fileItem.delete();

        }
      }

    } catch (FileUploadException e) {
      e.printStackTrace();
    }
효과:디 렉 터 리 를 분산 시 키 는 데 성 공 했 고 파일 이름 도 유일무이 합 니 다.

업로드 디 렉 터 리 에 있 는 파일 을 보 여 줍 니 다.다운 로드 를 제공 합 니 다.
respose 대상 을 설명 할 때 이미 파일 다운 로드 를 설명 했다.이번에 우 리 는 직접 작은 사례 를 써 서 파일 다운 로드 를 공 고 히 할 것 이다.
디 렉 터 리 에 있 는 파일 업로드 3 개

분석 하 다.
우선 디 렉 터 리 에 있 는 파일 을 모두 열거 해 야 한다.뒤에 파일 이름 에 따라 파일 을 다운로드 해 야 하기 때문에 우 리 는 맵 집합 으로 모든 파일 을 저장 합 니 다.
파일 다운로드 부분도 간단 하 다.파일 이름과 업로드 파일 위치 에 따라 해당 하 는 파일 을 찾 아 읽 기와 쓰 기 를 한 다음 메시지 헤드 를 수정 해 다운로드 하면 된다.
업로드 파일 을 불 러 오 는 경 로 를 얻 고 재 귀 를 통 해 모든 파일 을 찾 습 니 다.사용자 가 코드 를 다운로드 할 수 있 도록 WEB-INF/디 렉 터 리 에 저 장 된 파일 을 모두 Map 집합 에 저장 합 니 다.

protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
    //         
    String filePath = this.getServletContext().getRealPath("/WEB-INF/uploadFile");
    Map map = new HashMap();
    //            ,    Map   
    getAllFiles(new File(filePath), map);
    request.setAttribute("map", map);
    request.getRequestDispatcher("/listFile.jsp").forward(request, response);
  }
  private void getAllFiles(File filePath, Map map) {
    //      ,        
    if (!filePath.isFile()) {

      //           (     ,      )
      File[] files = filePath.listFiles();
      for (File file : files) {

        //     (      )       
        getAllFiles(file, map);
      }
    } else {
      //   else   ,      

      //     
      String fileName = filePath.getName().substring(filePath.getName().lastIndexOf("_") + 1);

      //         key,     value   map   
      map.put(filePath.getName(), fileName);

    }

  }
JSP 페이지 에 다운로드 가능 한 파일 보이 기

<c:forEach items="${map}" var="me">

  <c:url var="url" value="/DownFileServlet">
    <c:param name="fileName" value="${me.key}"></c:param>
  </c:url>
  ${me.value}<a href="${url}" rel="external nofollow" >  !</a><br>

</c:forEach>
다운로드 가능 한 Servlet

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

    //       
    String fileName = request.getParameter("fileName");

    //       ,    。
    fileName = new String(fileName.getBytes("ISO8859-1"), "utf-8");

    //         
    String path = this.getServletContext().getRealPath("/WEB-INF/uploadFile");

    //          hashCode     ,             
    String fileRealPath = makeFilePath(fileName, path);
    System.out.println(fileRealPath);

    //        
    File file = new File(fileRealPath);
    if (!file.exists()) {
      request.setAttribute("message", "           !");
      request.getRequestDispatcher("/message.jsp").forward(request, response);
      return ;
    }
    //  
    //              
    FileInputStream inputStream = new FileInputStream(fileRealPath);
    byte[] bytes = new byte[1024];
    int len = 0;
    while ((len = inputStream.read(bytes)) > 0) {
      response.getOutputStream().write(bytes, 0, len);
    }
    inputStream.close();
    //     ,     ,       
    String name = fileName.substring(fileName.lastIndexOf("_") + 1);
    response.setHeader("content-disposition","attachment;filename=" + URLEncoder.encode(name, "UTF-8"));

  }
  private String makeFilePath(String fileName, String path) {
    int hashCode = fileName.hashCode();
    int dir1 = hashCode & 0xf;
    int dir2 = (hashCode & 0xf0) >> 4;
    String dir = path + "\\" + dir1 + "\\" + dir2 +"\\"+ fileName;
    return dir;
  }
효과.

글 에 잘못된 부분 이 있 으 면 지적 을 환영 하고 서로 교류 합 니 다.우리 에 대한 여러분 의 지지 에 감사 드 립 니 다.

좋은 웹페이지 즐겨찾기