java实现大文件分片上传
在项目中用到了大文件上传功能,最初从网上参考了一些代码来实现,但是最终的上传效果不是很好,速度比较慢。
之前的上传思路是:
- 前端利用webUploader分片大文件
- 后端接收各个分片后的小文件
- 接收完一个大文件的所有分片文件后,合并这些文件为大文件
现在的思路是:
-
前端利用webUploader分片大文件
-
后端接收各个分片后的小文件
-
将接收到的小文件直接存到目标文件夹
-
需要注意的是,一定要按分片顺序来存储小文件,不然最后生成的
文件和原文件不一样,会被损坏
代码实现:
后端:
MediaUploadInfoController.java
/**
* Copyright © 2012-2016 <a href="https://github.com/thinkgem/jeesite">JeeSite</a> All rights reserved.
*/
package com.thinkgem.jeesite.modules.uploadfiles.web;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import com.thinkgem.jeesite.common.response.Code;
import com.thinkgem.jeesite.common.response.Result;
import com.thinkgem.jeesite.common.utils.IdGen;
import com.thinkgem.jeesite.modules.mediafileinfo.entity.MediaFileInfo;
import com.thinkgem.jeesite.modules.mediafileinfo.service.MediaFileInfoService;
import com.thinkgem.jeesite.modules.sys.entity.Company;
import com.thinkgem.jeesite.modules.sys.entity.MediaType;
import com.thinkgem.jeesite.modules.sys.entity.User;
import com.thinkgem.jeesite.modules.sys.service.MediaSysCompanyService;
import com.thinkgem.jeesite.modules.sys.service.TypeService;
import com.thinkgem.jeesite.modules.sys.utils.UserUtils;
import org.apache.shiro.authz.annotation.RequiresPermissions;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.ModelAttribute;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.multipart.MultipartFile;
import org.springframework.web.servlet.mvc.support.RedirectAttributes;
import com.thinkgem.jeesite.common.config.Global;
import com.thinkgem.jeesite.common.persistence.Page;
import com.thinkgem.jeesite.common.web.BaseController;
import com.thinkgem.jeesite.common.utils.StringUtils;
import com.thinkgem.jeesite.modules.uploadfiles.entity.MediaUploadInfo;
import com.thinkgem.jeesite.modules.uploadfiles.service.MediaUploadInfoService;
import java.util.Arrays;
import java.util.List;
import java.util.Map;
/**
* 上传文件信息Controller
* @author admin
* @version 2018-07-11
*/
@Controller
@RequestMapping(value = "${adminPath}/uploadfiles/mediaUploadInfo")
public class MediaUploadInfoController extends BaseController {
@Autowired
private MediaUploadInfoService mediaUploadInfoService;
@Autowired
private MediaSysCompanyService mediaSysCompanyService;
@Autowired
private TypeService typeService;
@Autowired
private MediaFileInfoService mediaFileInfoService;
@ModelAttribute
public MediaUploadInfo get(@RequestParam(required=false) String id) {
MediaUploadInfo entity = null;
if (StringUtils.isNotBlank(id) && !StringUtils.contains(id, "WU_FILE")){
entity = mediaUploadInfoService.get(id);
}
if (entity == null){
entity = new MediaUploadInfo();
}
return entity;
}
// @RequiresPermissions("uploadfiles:mediaUploadInfo:view")
@RequestMapping(value = {
"list", ""})
public String list(MediaUploadInfo mediaUploadInfo, HttpServletRequest request, HttpServletResponse response, Model model) {
//todo 获得用户
User user = UserUtils.getUser();
mediaUploadInfo.setCreateBy(user);
Page<MediaUploadInfo> page = mediaUploadInfoService.findPage(new Page<MediaUploadInfo>(request, response), mediaUploadInfo);
model.addAttribute("page", page);
return "modules/uploadfiles/mediaUploadInfoList";
}
// @RequiresPermissions("uploadfiles:mediaUploadInfo:view")
@RequestMapping(value = "form")
public String form(MediaUploadInfo mediaUploadInfo, Model model, @RequestParam(required = false) String rootId) {
User user = UserUtils.getUser();
String companyId = user.getCompany().getId();
Company company = mediaSysCompanyService.get(Integer.valueOf(companyId));
List<MediaType> typeList = typeService.getLastLevelTypes(rootId);
model.addAttribute("UUID", IdGen.uuid());
model.addAttribute("typeList", typeList);
model.addAttribute("company", company);
model.addAttribute("mediaUploadInfo", mediaUploadInfo);
if ("1".equals(rootId))
return "modules/uploadfiles/mediaUploadInfoForm";
else
return "modules/uploadfiles/vedioUploadInfoForm";
}
@RequiresPermissions("uploadfiles:mediaUploadInfo:edit")
@RequestMapping(value = "save")
public String save(MediaUploadInfo mediaUploadInfo, Model model, RedirectAttributes redirectAttributes) {
if (!beanValidator(model, mediaUploadInfo)){
return form(mediaUploadInfo, model, null);
}
mediaUploadInfoService.save(mediaUploadInfo);
addMessage(redirectAttributes, "保存文件成功");
return "redirect:"+Global.getAdminPath()+"/uploadfiles/mediaUploadInfo/?repage";
}
@RequiresPermissions("uploadfiles:mediaUploadInfo:edit")
@RequestMapping(value = "delete")
public String delete(MediaUploadInfo mediaUploadInfo, RedirectAttributes redirectAttributes) {
mediaUploadInfoService.delete(mediaUploadInfo);
addMessage(redirectAttributes, "删除文件成功");
return "redirect:"+Global.getAdminPath()+"/uploadfiles/mediaUploadInfo/?repage";
}
/**
* 分片上传文件
*
* @param mediaUploadInfo MediaUploadInfo实体
* @param mediaFileInfo MediaFileInfo实体
* @param uploadCounts 上传的文件总数量
* @param UUID 作为media_upload_info表中数据主键
* @param isCover 是否是封面,图片上传时用于判定封面图片
* @param isVideo 是否是视频文件
* @param chunks 文件总的分片数量
* @param chunk 当前分片
* @param name 名字
* @param request 请求
* @param file 文件
* @param md5Value 文件MD5值,用于多文件上传时,判定是不是相同文件
* @return json信息
*/
@RequestMapping("/sliceUploadFiles")
@ResponseBody
public Map<String, Object> sliceUploadFiles(MediaUploadInfo mediaUploadInfo,
MediaFileInfo mediaFileInfo,
int uploadCounts,
String UUID,
Boolean isCover,
Boolean isVideo,
String chunks,
String chunk,
String name,
HttpServletRequest request,
MultipartFile file,
String md5Value) {
try {
return mediaUploadInfoService.sliceUploadFiles(mediaUploadInfo, mediaFileInfo, uploadCounts, UUID, isCover, isVideo, chunks, chunk, name, request, file, md5Value);
} catch (Exception e) {
return Result.Error(Code.SYSTEM_ERROR);
}
}
/**
* 视频上传封面上传
*
* @param cover
* @param UUID
* @param mediaUploadInfo
* @return
*/
@RequestMapping("/coverUpload")
@ResponseBody
public Map<String, Object> coverUpload(HttpServletRequest request, MultipartFile file, String UUID, MediaUploadInfo mediaUploadInfo, String md5Value) {
return mediaUploadInfoService.coverUpload(request, file, UUID, mediaUploadInfo, md5Value);
}
/**
* 批量删除文件
*
* @param ids 多个文件ID,用“,”隔开
* @return
*/
@RequestMapping("/batchDelete")
@ResponseBody
@Transactional
public Map<String, Object> batchDelete(String ids){
String[] strings = ids != null ? ids.split(",") : null;
if (strings != null && strings.length > 0){
List<String> pkIds = Arrays.asList(strings);
//批量删除可以被删除的文件信息,审核通过的不能删除
Integer count = mediaUploadInfoService.batchDelete(pkIds);
Integer count1 = mediaFileInfoService.batchDelete(pkIds);
if (count == 0 && count1 == 0){
return Result.Success("您选择的文件因为已经审核通过,不能删除!");
}else {
return Result.Success("您选择的文件删除成功!");
}
}else {
return Result.Error(Code.PARAM_ERROR);
}
}
}
MediaUploadInfoService.java
/**
* Copyright © 2012-2016 <a href="https://github.com/thinkgem/jeesite">JeeSite</a> All rights reserved.
*/
package com.thinkgem.jeesite.modules.uploadfiles.service;
import com.google.common.base.Joiner;
import com.google.common.base.Splitter;
import com.thinkgem.jeesite.common.config.Global;
import com.thinkgem.jeesite.common.persistence.Page;
import com.thinkgem.jeesite.common.response.Code;
import com.thinkgem.jeesite.common.response.Result;
import com.thinkgem.jeesite.common.service.CrudService;
import com.thinkgem.jeesite.common.utils.FileUtils;
import com.thinkgem.jeesite.common.utils.IdGen;
import com.thinkgem.jeesite.common.utils.UploadFiles.OperatingFileUtil;
import com.thinkgem.jeesite.modules.mediafileinfo.entity.MediaFileInfo;
import com.thinkgem.jeesite.modules.mediafileinfo.service.MediaFileInfoService;
import com.thinkgem.jeesite.modules.sys.entity.MediaType;
import com.thinkgem.jeesite.modules.sys.entity.User;
import com.thinkgem.jeesite.modules.sys.service.TypeService;
import com.thinkgem.jeesite.modules.sys.utils.UserUtils;
import com.thinkgem.jeesite.modules.uploadfiles.dao.MediaUploadInfoDao;
import com.thinkgem.jeesite.modules.uploadfiles.entity.MediaUploadInfo;
import org.apache.commons.lang.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.multipart.MultipartFile;
import javax.imageio.ImageIO;
import javax.servlet.http.HttpServletRequest;
import java.awt.*;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.InputStream;
import java.sql.SQLException;
import java.text.SimpleDateFormat;
import java.util.*;
import java.util.<