springboot使用WebUploader实现大文件分片上传

前段时间做了个网盘,所以添加了一个大文件上传接口,这里记录一下

直接给出代码:

前端页面:




	
   	
   	
   
   	
   	
	
	
	


   	
 
	
选择文件

上传所用时间: 0s

后端代码:

先在application.yml中添加配置:

spring:
  http:
    encoding:
      force: true
      charset: utf-8
    multipart:
      max-file-size: 100MB
      max-request-size: 100MB
package com.hm.pan.controller;

import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.sql.Timestamp;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.Random;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;

import org.apache.commons.io.FileUtils;
import org.apache.tomcat.util.http.fileupload.servlet.ServletFileUpload;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.multipart.MultipartFile;

import com.hm.pan.annotation.CheckLogin;
import com.hm.pan.model.FileInfo;
import com.hm.pan.model.ResultObj;
import com.hm.pan.model.User;
import com.hm.pan.model.UserFile;
import com.hm.pan.service.FileUploadService;
import com.hm.pan.service.UserFileService;

@RestController
@RequestMapping("bigFile")
@CheckLogin
public class BigFileUploadController {

	@Resource
	private FileUploadService fileUploadService;
	@Resource
	private UserFileService userFileService;
	@Value("${upload-path}")
	private String uploadPath;
	
	// 通过MD5查找文件信息,如果有的话,就不用上传文件,只要向用户文件里插入文件信息就行
	@GetMapping("findResourceFileExistsByMd5")
	public Object findMd5(String md5value, String fileName, String caozuoPath, HttpSession session)
			throws Exception {
		Timestamp uploadTime = new Timestamp(System.currentTimeMillis());
		UserFile oneFileByPath2 = userFileService.getOneFileByPath(caozuoPath);// 通过前端传过来的操作路径找到该用户文件对象
		Long fatherId2 = oneFileByPath2.getUserfileId();
//		log.info("================"+md5);
		User user = (User) session.getAttribute("user"); // 通过session拿到前端用户信息
//		log.info("-----------------"+user);
		Long userId = user.getUserId(); // 获取前端传过来的用户id
//		log.info("+++++++++++++++++"+userId);

		String newName = getName(fileName);

		Object filemd5 = fileUploadService.findMd5(md5value);
		// 如果数据里有MD5,就不用上传,但是用户文件需要插入。
		if (filemd5 != null) {
			Object fileInfo = fileUploadService.findByNameFatherId(fileName, fatherId2);
			if (fileInfo != null) {
				fileUploadService.insertUserFile(uploadTime, newName, md5value, fatherId2, userId);
			} else {
				fileUploadService.insertUserFile(uploadTime, fileName, md5value, fatherId2, userId);
			}
			return new ResultObj(200, fileInfo);
		} else {
			return new ResultObj(400, filemd5);
		}

	}
	
    //这里通过文件编号guid和分片数chunk来检查分片文件,其实严格一点还需要检查分片文件的偏移位置和文件大小,以防止分片文件上传失败的情况,这里表示一下就行,需要自己改改
	@GetMapping("findResourceChunkExists")
    public ResultObj findResourceChunkExists(String guid,Integer chunk){
		// 临时目录用来存放所有分片文件  
        String tempFileDir = uploadPath+ "/bigFileTemp/" + guid;  
        File parentFileDir = new File(tempFileDir); 
		File tempPartFile = new File(parentFileDir, guid + "_" + chunk + ".part"); 
		if(tempPartFile.exists()) {
			return new ResultObj(200, "存在"); 
		}else {
			return new ResultObj(404, "不存在"); 
		}
    }

	// 如果前面的MD5没有找到文件信息的话,就会返回一个400到前端,前端再根据判断,把文件给上传。
	@PostMapping("saveFileInfo")
	public ResultObj aa(String guid, String md5value, Long fileSize, String fileName,
			String caozuoPath, HttpSession session, HttpServletRequest req) throws Exception {
		Timestamp uploadTime = new Timestamp(System.currentTimeMillis());
		System.out.println("saveFileInfo:");
		System.out.println("------------guid:"+guid);
		System.out.println("------------md5value:"+md5value);
		System.out.println("------------fileSize:"+fileSize);
		System.out.println("------------fileName:"+fileName);
		System.out.println("------------caozuoPath:"+caozuoPath);
		String newName = getName(fileName);

		// 将文件存到指定项目文件下,没有的话就创建
//		File realpath = ResourceUtils.getFile("");
//		String realpath = req.getServletContext().getRealPath("/upload");
		// String filePath = realpath+fileName;
		File dest = mergeFile(guid, fileName);
//		log.info("<<<<<<<<<<<<<<<< "+file2.getAbsolutePath());
		FileInfo fileInfo = new FileInfo();
		fileInfo.setFilePath(dest.getPath()); // 获取文件的相对路径
		fileInfo.setFileMd5(md5value);
		fileInfo.setFileSize(fileSize);

		User user = (User) session.getAttribute("user"); // 通过session拿到前端用户信息
//		log.info("-----------------"+user);
		Long userId = user.getUserId(); // 获取前端传过来的用户id
//		log.info("+++++++++++++++++"+userId);
		Object fileinfo = fileUploadService.insertFileInfo(fileInfo);

		UserFile oneFileByPath = userFileService.getOneFileByPath(caozuoPath); // 通过操作路径找到fatherId

		if (oneFileByPath != null && fileinfo != null) {
			Long fatherId = oneFileByPath.getUserfileId();
			Object findByName = fileUploadService.findByNameFatherId(fileName, fatherId);
			if (findByName != null) {
				fileUploadService.insertUserFile(uploadTime, newName, md5value, fatherId, userId);
			} else {
				fileUploadService.insertUserFile(uploadTime, fileName, md5value, fatherId, userId);
			}
			return new ResultObj(200, fileinfo);
		}

		return new ResultObj(400, fileinfo);
	}

	// 获取不同的文件名
	public String getName(String fileName) {
		// 解决文件名重名,以时间戳+随机数
		// 获得当前时间

		SimpleDateFormat format = new SimpleDateFormat("yyyyMMddHHmmss");
		// 转换为字符串
		String formDate = format.format(new Date());
		// 随机生成文件编号
		int random = new Random().nextInt(1000);
		String[] split = fileName.split("\\.");

		// 1.2.3.4.cc
		// mm
		StringBuffer sb = new StringBuffer(split[0]);
		for (int i = 1; i < split.length - 1; i++) {
			sb.append('.').append(split[i]);
		}

		sb.append('_').append(formDate).append(random);

		if (fileName.indexOf(".") != -1) {
			sb.append('.').append(split[split.length - 1]);
		}

		String name = sb.toString();

		return name;
	}

	
	/**
	    * 上传文件
	    * @param request
	    * @param response
	    * @param guid
	    * @param chunk
	    * @param file
	    * @param chunks
	    */
	   @RequestMapping("upload")
	   public void bigFile(HttpServletRequest request, HttpServletResponse response,String guid,Integer chunk, MultipartFile file,Integer chunks){
	      try {  
	            boolean isMultipart = ServletFileUpload.isMultipartContent(request);  
	            if (isMultipart) {  
	                // 临时目录用来存放所有分片文件  
	                String tempFileDir = uploadPath+ "/bigFileTemp/" + guid;  
	                File parentFileDir = new File(tempFileDir);  
	                if (!parentFileDir.exists()) {  
	                    parentFileDir.mkdirs();  
	                }  
	                // 分片处理时,前台会多次调用上传接口,每次都会上传文件的一部分到后台  
	                File tempPartFile = new File(parentFileDir, guid + "_" + chunk + ".part");  
	                FileUtils.copyInputStreamToFile(file.getInputStream(), tempPartFile);  
	            }  
	        } catch (Exception e) {  
	           e.printStackTrace();
	        }  
	   }
	   
	   /**
	    * 合并文件
	    * @param guid
	    * @param fileName
	    * @throws Exception
	    */
	   public File mergeFile(String guid,String fileName){
	       // 得到 destTempFile 就是最终的文件  
	      try {
	         File parentFileDir = new File(uploadPath+ "/bigFileTemp/" + guid);
	         if(parentFileDir.isDirectory()){
//	            File destTempFile = new File(uploadPath+ "/bigFileTemp/merge/", fileName);
	            SimpleDateFormat format = new SimpleDateFormat("yyyy/MM/dd");
	    		// 转换为字符串
	    		String formDate = format.format(new Date());
	    		File destTempFile = new File(uploadPath+"/"+formDate, fileName);
	            System.out.println(destTempFile.getPath());
	            
	            if(!destTempFile.exists()){
	               //先得到文件的上级目录,并创建上级目录,在创建文件,
	               destTempFile.getParentFile().mkdirs();
	               try {
	                  //创建文件
	                  destTempFile.createNewFile(); //上级目录没有创建,这里会报错
	               } catch (IOException e) {
	                  e.printStackTrace();
	               }
	            }
	            System.out.println(parentFileDir.listFiles().length);
	              for (int i = 0; i < parentFileDir.listFiles().length; i++) {  
	                  File partFile = new File(parentFileDir, guid + "_" + i + ".part");
	                  FileOutputStream destTempfos = new FileOutputStream(destTempFile, true);
	                  //遍历"所有分片文件"到"最终文件"中  
	                  FileUtils.copyFile(partFile, destTempfos);  
	                  destTempfos.close();  
	              }  
	              // 删除临时目录中的分片文件  
	              FileUtils.deleteDirectory(parentFileDir);
	              return destTempFile;
	         }
	      } catch (Exception e) {
	         e.printStackTrace();
	         return null;
	      }
	      return null;
	   }
	 
}

 

你可能感兴趣的:(web开发备注,WebUploader,大文件上传,文件分片上传,springboot)