java实现大文件分片上传

Java大文件上传(秒传、分片上传、断点续传) 秒传就是不传,实现逻辑就是看数据库或者缓存里是否已经有这个文件了,有了,直接从已有的文件去拿就可以了(返回文件地址)。 这里判断是否是相同文件,要用到信息摘要算法,详情可以参考:一文读懂当前常用的加密技术体系。 信息摘要算法常常被用来保证信息的完整性,防止信息在传输过程中被篡改(无法确定信息是否被监听)。常用的就是MD5算法。分片上传,就相当于把一个大文件,拆成很多个小份,就想hls文件一样,一片一片的,上传完成后组合起来形成一个完整的文件。 一般和断点续传一起使用。分片上传过程中,会话失效、网络问题、系统 阅读详情

java实现大文件分片上传

在项目中用到了大文件上传功能,最初从网上参考了一些代码来实现,但是最终的上传效果不是很好,速度比较慢。

之前的上传思路是:

  1. 前端利用webUploader分片大文件
  2. 后端接收各个分片后的小文件
  3. 接收完一个大文件的所有分片文件后,合并这些文件为大文件

现在的思路是:

  1. 前端利用webUploader分片大文件

  2. 后端接收各个分片后的小文件

  3. 将接收到的小文件直接存到目标文件夹

  4. 需要注意的是,一定要按分片顺序来存储小文件,不然最后生成的

    文件和原文件不一样,会被损坏

代码实现:

后端:

MediaUploadInfoController.java

/**
 * Copyright &copy; 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 &copy; 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
java大文件分片上传示例 java大文件分片上传示例,java大文件分片上传示例,java大文件分片上传示例,欢迎大家下载!! 立即下载

相关推荐

Deep Reinforcement Learning - 1. DDPG原理和算法

Deep Reinforcement Learning - 1. DDPG原理和算法 背景描述 DDPG的定义和应用场景 DDPG算法相关基本概念定义 DDPG实现框架和算法 DDPG对于DPG的关键改进 下一篇 以下用RL作为Reinforcement Learning 的简称。背景描述概括来说,RL要解决的问

kenneth_yu的博客 14万+

从零配置EtherCAT IGH主站:手把手教你处理内核版本与实时性优化的那些坑

本文详细指导如何从零配置EtherCAT IGH主站,涵盖内核版本适配、实时性优化及常见问题解决方案。通过精确匹配内核头文件、应用实时补丁和优化网卡驱动,帮助开发者实现微秒级响应,适用于工业自动化、机器人控制等高精度场景。

weixin_30790841的博客 382

FreeSWITCH彩铃与回铃音区别详解:从183/180信令到mod_da2检测模块

本文深入解析FreeSWITCH中彩铃与回铃音的技术差异,从183/180信令机制到mod_da2智能检测模块的实现原理。通过对比SIP协议中的早期媒体传输、回铃音补偿技术及实战案例,帮助开发者掌握VoIP系统中的关键音频处理技术,提升呼叫系统稳定性和用户体验。

tree8的博客 348

Unity实战篇 | 教你怎样将Unity的启动Logo 设置成 自己制作的 帧动画

上一篇文章我们讲了怎样在不购买专业版的情况下自定义Unity的启动Logo。 那本篇文章就来介绍一下,怎样在去除默认Logo的前提下制作自己的启动动画!

努力前行,总会成为自己心中的那道光 6万+

基于ESP32的智能无线广播系统开发博客

通过本项目的开发,我们成功地实现了基于ESP32的智能无线广播系统。该系统不仅具备传统广播的功能,还实现了通过Wi-Fi无线传输音频、实时广播和智能控制等多种先进功能。未来,随着技术的进一步发展,我们还可以扩展更多功能,如智能推荐广播内容、支持语音识别和控制等。希望本项目能够为嵌入式开发人员提供一些思路和参考,帮助大家在实际开发中更好地应用ESP32平台,开发出更加智能和实用的无线广播系统。

2201_76125393的博客 423

11、iOS设备逻辑数据分析全解析

本文深入解析iOS设备中的逻辑数据,涵盖图像相关数据库(Photos.sqlite和PhotosAux.sqlite)、录音文件、iPhoto照片存储结构、多媒体文件、第三方应用程序、社交网络应用(如Twitter、Skype、Facebook等)以及苹果相关应用(如Google Mobile、Bing)的数据存储结构和取证方法。此外,还介绍了文档类应用(如Pages、Numbers、Documents To Go)的文件存储结构及恢复方法。适用于iOS取证、数据挖掘和数字调查领域。

rain6的博客 226

超级全的PCB LAYOUT高速信号走线指南——简化应用版

在PCB Layout中,几乎涵盖了所有的高速信号走线指南。包括了TF/SD、HDMI、LVDS、DVP、eDP、MIPI、USB2.0、USB3.0、MAC、BT.1120、PCIE高速信号等等。此版本为简化版。

bhxc809751502的博客 8547

OpenHarmony RK3568 从 32 位切换到 64 位用户空间指南

修改了编译参数(如修复 Q5 后),但 ThinLTO 缓存中保留了旧参数编译的 bitcode。这是一种节省内存的设计(32 位指针占 4 字节 vs 64 位占 8 字节),但在某些场景下需要切换为纯 64 位。切换到 64 位用户空间后,CPU 全程运行在 AArch64 状态,不再需要 AArch32 兼容模式。内核本身已经是 64 位(aarch64),切换用户空间位数不影响内核。(32 位兼容层)在纯 64 位系统中不再需要,可以关闭以减小内核体积。这两个参数对 64 位编译毫无意义,配合。

程小二的博客 689

最新的sdio 4.0 spec 协议标准 带书签 高清完整PDF版

Part-E1-SDIO-Specification-Ver4.00-Final-120220.pdf:最新的sdio 4.0 spec 协议标准 带书签 高清完整PDF版,包括SDIO 接口的外设,SDIO 接口官方协议等。

IEM模型,地表粗糙度模拟

利用微波反演土壤水分时候,利用IEM模型可以实现对随机地表的模拟

Devexpress16.2.6破解工具

Devexpress16.2.6破解工具Devexpress16.2.6破解工具Devexpress16.2.6破解工具Devexpress16.2.6破解工具

上一篇: import Eclipse项目到IDEA项目
下一篇: Java中关于httpClient的用法总结
Absosba
博客等级 码龄11年 20粉丝 20原创
评论 8
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值