>  기사  >  Java  >  Java와 WebUploader의 조합을 이용한 파일 업로드 기능 코드에 대한 자세한 설명

Java와 WebUploader의 조합을 이용한 파일 업로드 기능 코드에 대한 자세한 설명

黄舟
黄舟원래의
2017-03-30 10:11:322395검색

이 글에서는 파일업로드기능도 간단하고 이해하기 쉽고, 아주 좋고, 참고할만한 가치가 있어요. 필요한 친구들이 참고하면 좋아요

저도 예전에 작은 프로젝트를 작성할 때 파일 업로드 문제에 직면했습니다. , 그리고 좋은 것을 찾지 못했습니다. 온라인에서 다양한 솔루션을 검색할 때 WebUploader를 보았지만 이번에는 더 자세히 설명하지 않았습니다.

단순 파일 및 일반 데이터 업로드 및 저장

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>

서블릿:

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 구성 요소를 사용하여 업로드

샤딩, 동시성, 미리 보기, 압축, 폴더 추가를 위한 다양한 방법(다중 파일 선택) , 드래그 앤 드롭 드래그 등), Miaozhuan

페이지 스타일은

<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.创建页面元素 -->
 <p id="upload">
  <p id="filePicker">文件上传</p>
 </p>
 <!-- 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>

  • 를 사용하여 파일 이름 목록을 생성하고 업로드 진행 상황을 표시합니다.

    썸네일 표시

  • 파일 목록 p 추가,

    09c7ae7da5f5fe001584157ce3c54d1f94b3e26ee717c64999d7867364b1b4a3

  • 썸네일 생성 및 업로드 진행 상황 표시

  • // 生成缩略图和上传进度
    uploader.on("fileQueued", function(file) {
      // 把文件信息追加到fileList的p中
      $("#fileList").append("<p id=&#39;" + file.id + "&#39;><img/><span>" + file.name + "</span><p><span class=&#39;percentage&#39;><span></p></p>")
      // 制作缩略图
      // error:不是图片,则有error
      // src:代表生成缩略图的地址
      uploader.makeThumb(file, function(error, src) {
       if (error) {
        $("#" + file.id).find("img").replaceWith("<span>无法预览 </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>  
    <!-- 创建用于拖拽的区域 -->
    <p id="dndArea"></p>
  • 기본 구성에 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 string 을 백그라운드로 전송해야 하는 파일을 기준으로 백그라운드는 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 문자열을 얻을 수 있습니다. 백그라운드에서 청크된 파일을 저장하기 위한 디렉토리 이름으로 이 메소드에서 파일의 전송

    전송: 이 메소드는 각 부분 파일이 업로드되기 전에 호출됩니다(각 부분 업로드 전에 호출됨) ).
  • 이 방법으로 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() {
      }
     }
    );
  • 상태 태그 추가
$("#fileList").append("<p id=&#39;" + file.id + "&#39;>
<img/>
<span>" + file.name + "</span>
<p>
<span class=&#39;state&#39;>
</span>
</p>
<p>
<span class=&#39;percentage&#39;>
</span>
</p>
</p>");

파일 저장

// 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();
      }

    인증 추가 실행 중
  • 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}");
        }
      }

위 내용은 Java와 WebUploader의 조합을 이용한 파일 업로드 기능 코드에 대한 자세한 설명의 상세 내용입니다. 자세한 내용은 PHP 중국어 웹사이트의 기타 관련 기사를 참조하세요!

성명:
본 글의 내용은 네티즌들의 자발적인 기여로 작성되었으며, 저작권은 원저작자에게 있습니다. 본 사이트는 이에 상응하는 법적 책임을 지지 않습니다. 표절이나 침해가 의심되는 콘텐츠를 발견한 경우 admin@php.cn으로 문의하세요.