Java와 WebUploader를 결합하여 파일 업로드 기능(인스턴스 코드)

이전에 자신이 작은 프로젝트를 쓸 때도 파일 업로드 문제에 부딪혀 좋은 해결 방안을 찾지 못했다.그동안 인터넷에서 각종 해결 방안을 찾았을 때도 웹 Uploader를 보았지만 더 깊이 연구하지 못했다.이번에 좀 깊이 이해했으니 여기도 작은 매듭을 짓자.
간단한 파일 및 일반 데이터 업로드 및 저장
jsp 페이지:

<%@ page language="java" contentType="text/html; charset=UTF-8"
 pageEncoding="UTF-8"%>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>Insert title here</title>
</head>
<body>
 <form action="${pageContext.request.contextPath }/FileUploadServlet" method="post" enctype="multipart/form-data">
   :<input type="file" value=" " name="file" /> <br/>
   :<input type="text" name="info" /> <br/>
  <input type="submit" value=" " />
 </form>
</body>
</html>
servlet:

package com.yihengliu.web.action;
import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.util.List;
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.disk.DiskFileItemFactory;
import org.apache.commons.fileupload.servlet.ServletFileUpload;
import org.apache.commons.io.FileUtils;
/**
 * Servlet user to accept file upload
 */
public class FileUploadServlet extends HttpServlet {
 private static final long serialVersionUID = 1L;
 private String serverPath = "e:/";
 protected void doGet(HttpServletRequest request, HttpServletResponse response)
   throws ServletException, IOException {
  response.getWriter().append("Served at: ").append(request.getContextPath());
  System.out.println(" ...");
  // 1. DiskFileItemFactory , 
  DiskFileItemFactory diskFileItemFactory = new DiskFileItemFactory();
  // 2.   ServletFileUpload 
  ServletFileUpload servletFileUpload = new ServletFileUpload(diskFileItemFactory);
  // 3.  
  servletFileUpload.setHeaderEncoding("utf-8");
  // 4.  
  try {
   List<FileItem> items = servletFileUpload.parseRequest(request);
   for (FileItem fileItem : items) {
    if (fileItem.isFormField()) { // >>  
     String info = fileItem.getString("utf-8");
     System.out.println("info:" + info);
    } else { // >>  
     // 1.  
     String name = fileItem.getName();
     // 2.  
     InputStream is = fileItem.getInputStream();
     // 3.  
     FileUtils.copyInputStreamToFile(is, new File(serverPath + "/" + name));
    }
   }
  } catch (Exception e) {
   e.printStackTrace();
  }
 }
 protected void doPost(HttpServletRequest request, HttpServletResponse response)
   throws ServletException, IOException {
  doGet(request, response);
 }
}
WebUploader 구성 요소를 사용하여 업로드
분할, 병발, 미리보기, 압축, 다중 경로 추가 폴더(파일 다중 선택, 드래그 등), 묘전
페이지 스타일 사용

<html>
<title> webuploader </title>
<!-- 1.  -->
<link rel="stylesheet" type="text/css" href="${pageContext.request.contextPath }/js/webuploader.css" rel="external nofollow" >
<script type="text/javascript" src="${pageContext.request.contextPath }/js/jquery-2.1.4.min.js"></script>
<script type="text/javascript" src="${pageContext.request.contextPath }/js/webuploader.js"></script>
</head>
<body>
 <!-- 2.  -->
 <div id="upload">
  <div id="filePicker"> </div>
 </div>
 <!-- 3. js  -->
 <script type="text/javascript">
  var uploader = WebUploader.create(
   {
    swf:"${pageContext.request.contextPath }/js/Uploader.swf",
    server:"${pageContext.request.contextPath }/FileUploadServlet",
    pick:"#filePicker",
    auto:true
   }  
  );
 </script>
</body>
</html>
  • 파일 이름 목록 생성, 업로드 진행률 실시간 표시, 축소 이미지 표시
  • 파일 목록 div 추가, <div id="fileList"></div>
  • 축소 이미지 생성 및 업로드 진도 표시
  • 
    //  
    uploader.on("fileQueued", function(file) {
      //  fileList div 
      $("#fileList").append("<div id='" + file.id + "'><img/><span>" + file.name + "</span><div><span class='percentage'><span></div></div>")
      //  
      // error: , error
      // src: 
      uploader.makeThumb(file, function(error, src) {
       if (error) {
        $("#" + file.id).find("img").replaceWith("<span> &nbsp;</span>");
       } else {
        $("#" + file.id).find("img").attr("src", src);
       }
      });
     }
    );
    //  
    // percentage: 
    uploader.on("uploadProgress", function(file, percentage) {
     $("#" + file.id).find("span.percentage").text(Math.round(percentage * 100) + "%");
    });
  • 드래그 업로드, 붙여넣기 업로드
  • 드래그 영역 생성 및 스타일 설정:
  • 
    <style type="text/css">
     #dndArea {
      width: 200px;
      height: 100px;
      border-color: red;
      border-style: dashed;
     }
    </style>  
    <!--   -->
    <div id="dndArea"></div>
  • 기본 설정에 dnd 영역 설정 추가(드래그 열기)
  • 드래그 영역 밖의 응답 차단
    붙여넣기 기능 켜기
    
    var uploader = WebUploader.create(
     {  swf:"${pageContext.request.contextPath }/js/Uploader.swf",
    server:"${pageContext.request.contextPath }/FileUploadServlet",
      pick:"#filePicker",
      auto:true,
      //  
      dnd:"#dndArea",
      //  
      disableGlobalDnd:true,
      // 
     }  
    );
  • 파일의 블록 업로드
  • 전단은 보내야 할 파일에 따라md5 문자열을 백엔드에 생성하고, 백엔드는 이md5 문자열로 명명된 폴더를 생성합니다.프런트엔드에서 블록을 나누어 파일을 보내고 블록 번호를 백그라운드에 보내며 백그라운드에서 파일을 받은 후 번호 이름으로 저장합니다.프런트엔드 발송이 완료되면 백그라운드 병합 파일을 알립니다.
  • 프런트엔드 구성, 블록 분할 여부, 블록 크기, 스레드 개수 등 켜기
  • 
    //  
    var uploader = WebUploader.create(
    {
     swf:"${pageContext.request.contextPath }/js/Uploader.swf",
     server:"${pageContext.request.contextPath }/FileUploadServlet",
     pick:"#filePicker",
     auto:true,
     dnd:"#dndArea",
     disableGlobalDnd:true,
     paste:"#uploader",
    
     //  
     //  
     chunked:true,
     //  ( 5M)
     chunkSize:5*1024*1024,
     //  ( 3 )
     threads:3,
     //  , 
     prepareNextFile:true
    }  
    );
  • 전면 감청 블록
  • 세 가지 시점으로 나눌 수 있습니다.
  • before-send-file: 이 방법은 파일이 업로드되기 전에 호출됩니다. (한 파일이 업로드되기 전에만 호출됩니다.)
  • 이 방법에서 파일을 가져올 수 있는md5 문자열은 블록 파일을 백그라운드로 저장하는 디렉터리 이름입니다
  • before-send: 이 방법은 블록 파일이 업로드되기 전에 호출됩니다. (블록이 업로드되기 전에 호출됩니다.)
  • 이 방법에서md5 문자열을 백엔드로 보낼 수 있으며, 백엔드에서 블록이 분리되어 전송 여부를 결정하여 인터럽트 리셋 기능에 도달했는지 판단할 수 있습니다
  • after-send-file: 이 방법은 모든 파일을 업로드하는 데 오류가 없으면 호출합니다.
  • 이 방법에서 백그라운드에 모든 블록을 병합할 것을 알릴 수 있다
  • 전단에서 파일md5 문자열을 가져와 각 블록을 보낼 때 백그라운드로 보내고 백그라운드에서 폴더가 없는 폴더를 수신하면 블록이 보낸 파일을 저장합니다
  • 
     //  , 
    var fileMd5;
    WebUploader.Uploader.register({
     "before-send-file":"beforeSendFile",
     "before-send":"beforeSend",
     "after-send-file":"afterSendFile"
     },{
      beforeSendFile:function(file) {
       //  deffered, 
       var deferred = WebUploader.Deferred();
       //  , 
       (new WebUploader.Uploader()).md5File(file, 0, 5*1024*1024)
        .progress(function(percentage){
         $("#"+file.id).find("span.state").text(" ...");
        })
        .then(function(val) {
         fileMd5 = val;
         $("#" + file.id).find("span.state").text(" ");
         //  
         deferred.resolve();
        });
       //  
       return deferred.promise();
      },
      beforeSend:function() {
       var deferred = WebUploader.Deferred();
       //  md5 
       this.owner.options.formData.fileMd5 = fileMd5;
       deferred.resolve();
       return deferred.promise();
      },
      afterSendFile:function() {
      }
     }
    );
    state 태그 추가
    
    $("#fileList").append("<div id='" + file.id + "'><img/><span>" + file.name + "</span><div><span class='state'></span></div><div><span class='percentage'></span></div></div>");
    파일 저장
    
    // 4.  
    //  md5 
    String fileMd5 = null;
    //  
    String chunk = null;
    try {
      List<FileItem> items = servletFileUpload.parseRequest(request);
      for (FileItem fileItem : items) {
        if (fileItem.isFormField()) { // >>  
          String fieldName = fileItem.getFieldName();
          if ("info".equals(fieldName)) {
            String info = fileItem.getString("utf-8");
            System.out.println("info:" + info);
          }
          if ("fileMd5".equals(fieldName)) {
            fileMd5 = fileItem.getString("utf-8");
            System.out.println("fileMd5:" + fileMd5);
          }
          if ("chunk".equals(fieldName)) {
            chunk = fileItem.getString("utf-8");
            System.out.println("chunk:" + chunk);
          }
        } else { // >>  
          /*// 1.  
          String name = fileItem.getName();
          // 2.  
          InputStream is = fileItem.getInputStream();
          // 3.  
          FileUtils.copyInputStreamToFile(is, new File(serverPath + "/" + name));*/
          //  
          File file = new File(serverPath + "/" + fileMd5);
          if (!file.exists()) {
            file.mkdirs();
          }
          //  
          File chunkFile = new File(serverPath + "/" + fileMd5 + "/" + chunk);
          FileUtils.copyInputStreamToFile(fileItem.getInputStream(), chunkFile);
        }
      }
  • 파일 병합을 위한 프런트엔드 알림
  • 프런트엔드 증가:
    
    //  
    $.ajax(
      {
        type:"POST",
        url:"${pageContext.request.contextPath}/UploadActionServlet?action=mergeChunks",
        data:{
          fileMd5:fileMd5
        },
        success:function(response){
        }
      }
    );
    새 병합 작업:
    
    package com.yihengliu.web.action;
    import java.io.File;
    import java.io.FileFilter;
    import java.io.FileInputStream;
    import java.io.FileOutputStream;
    import java.io.IOException;
    import java.nio.channels.FileChannel;
    import java.util.ArrayList;
    import java.util.Arrays;
    import java.util.Collections;
    import java.util.Comparator;
    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;
    /**
     *  
     */
    public class UploadActionServlet extends HttpServlet {
      private static final long serialVersionUID = 1L;
      private String serverPath = "e:/";
      protected void doGet(HttpServletRequest request, HttpServletResponse response)
          throws ServletException, IOException {
        System.out.println(" ...");
        String action = request.getParameter("action");
        if ("mergeChunks".equals(action)) {
          //  
          String fileMd5 = request.getParameter("fileMd5");
          //  
          File f = new File(serverPath + "/" + fileMd5);
          File[] fileArray = f.listFiles(new FileFilter() {
            //  , 
            @Override
            public boolean accept(File pathname) {
              if (pathname.isDirectory()) {
                return false;
              }
              return true;
            }
          });
          //  , 
          List<File> fileList = new ArrayList<File>(Arrays.asList(fileArray));
          //  
          Collections.sort(fileList, new Comparator<File>() {
            @Override
            public int compare(File o1, File o2) {
              if (Integer.parseInt(o1.getName()) < Integer.parseInt(o2.getName())) {
                return -1;
              }
              return 1;
            }
          });
          //  
          File outputFile = new File(serverPath + "/" + UUID.randomUUID().toString() + ".zip");
          //  
          outputFile.createNewFile();
          //  
          FileOutputStream fileOutputStream = new FileOutputStream(outputFile);
          FileChannel outChannel = fileOutputStream.getChannel();
          //  
          FileChannel inChannel;
          for (File file : fileList) {
            inChannel = new FileInputStream(file).getChannel();
            inChannel.transferTo(0, inChannel.size(), outChannel);
            inChannel.close();
            //  
            file.delete();
          }
          //  
          fileOutputStream.close();
          outChannel.close();
          //  
          File tempFile = new File(serverPath + "/" + fileMd5);
          if (tempFile.isDirectory() && tempFile.exists()) {
            tempFile.delete();
          }
          System.out.println(" ");
        }
      }
      protected void doPost(HttpServletRequest request, HttpServletResponse response)
          throws ServletException, IOException {
        doGet(request, response);
      }
    }
  • 단점 속전
  • 프런트엔드 페이지를 보내기 전에 블록이 업로드되었는지 확인합니다.
    
    beforeSend:function(block) {
            var deferred = WebUploader.Deferred();
            //  , 
            $.ajax(
              {
                type:"POST",
                url:"${pageContext.request.contextPath}/UploadActionServlet?action=checkChunk",
                data:{
                  //                  
                  fileMd5:fileMd5,
                  //  
                  chunk:block.chunk,
                  //  
                  chunkSize:block.end-block.start
                },
                dataType:"json",
                success:function(response) {
                  if(response.ifExist) {
                    //  , 
                    deferred.reject();
                  } else {
                    //  , 
                    deferred.resolve();
                  }
                }
              }
            );
            //  md5 
            this.owner.options.formData.fileMd5 = fileMd5;
            return deferred.promise();
          }
  • action에서 검증 추가
  • 
    else if ("checkChunk".equals(action)) {
        //  
        //                  
        String fileMd5 = request.getParameter("fileMd5");
        //  
        String chunk = request.getParameter("chunk");
        //  
        String chunkSize = request.getParameter("chunkSize");
        //  
        File checkFile = new File(serverPath + "/" + fileMd5 + "/" + chunk);
        //  , 
        response.setContentType("text/html;charset=utf-8");
        if (checkFile.exists() && checkFile.length() == Integer.parseInt((chunkSize))) {
          response.getWriter().write("{\"ifExist\":1}");
        } else {
          response.getWriter().write("{\"ifExist\":0}");
        }
      }
    위에서 말한 것은 여러분에게 소개된 자바와 WebUploader를 결합하여 파일 업로드 기능(실례 코드)을 실현하는 것입니다. 여러분에게 도움이 되었으면 합니다. 만약에 궁금한 것이 있으면 저에게 메시지를 남겨 주십시오. 편집자는 제때에 여러분에게 회답할 것입니다.여기에서도 저희 사이트에 대한 지지에 감사드립니다!

    좋은 웹페이지 즐겨찾기