当前位置:首页 » 文件管理 » 分片并发上传

分片并发上传

发布时间: 2022-11-15 23:41:47

㈠ 求jsp文件分片上传,断点续传的方法

无组件断点续传.gif
1. 组件简介
webuploader:是一个以HTML5为主, Flash为辅的文件上传组件,采用大文件分片/并发上传的方式,极大地提高了文件上传的效率,同时兼容多种浏览器版本;
2. 项目背景简介
本篇文章的背景,是在上一篇文章(《无组件实现大文件分片上传,断点续传》)的项目背景下进行的一次尝试,所以本篇文章还是基于上一篇文章的背景,但是不会介绍视频基本信息(视频标题、简介、播出时间等)的操作,主要介绍文件的上传。因为项目的特殊需求,这种使用插进的方式最终没有被采用,因为一些控件无法做到定制化。
上一篇文章(《无组件实现大文件分片上传,断点续传》)中介绍的文件上传方式,在前端主要采用纯javaScript来进行文件切分、验证,后台主要采用了NIO的方式进行分片的追加。而在这篇文章中,将介绍前端采用webuploader,后台采用临时目录+传统I/O方式进行分片合并的方式。
3. 技术实现
3.1 组件引入
在webuploader官网下载必要的文件,放入项目中。在页面中进行引入;

0_组件引入.png

<!-- webuploader文件上传 -->
<script src="static/webuploader/webuploader.nolog.min.js"></script>
<link href="static/webuploader/webuploader.css" rel="stylesheet" type="text/css" />

3.2 前端页面实现
在前端页面中,可以不用关心css样式,但需要注意标签的id/nama属性,这些将在后面的JavaScript中使用到。

㈡ iOS大文件的分片上传和断点上传

由于最近比较忙,所以一直没有写博客,现在分享一些大文件的上传的问题!断点续传和分片上传。因为文件过大(比如1G以上),必须要考虑上传过程网络中断的情况。http的网络请求中本身就已经具备了分片上传功能,当传输的文件比较大时,http协议自动会将文件切片(分块),但这不是我们现在说的重点,我们要做的事是保证在网络中断后1G的文件已上传的那部分在下次网络连接时不必再重传。所以我们本地在上传的时候,要将大文件进行分片,比如分成1024*1024B,即将大文件分成1M的片进行上传,服务器在接收后,再将这些片合并成原始文件,这就是分片的基本原理。断点续传要求本地要记录每一片的上传的状态,我通过三个状态进行了标记(wait loading finish),当网络中断,再次连接后,从断点处进行上传。服务器通过文件名、总片数判断该文件是否已全部上传完成。

下面来说细节:

1、首先获取文件(音视频、图片)

分两种情况,一种是在相册库里直接获取,一种是调用相机。如果是通过UIImagePickerView来获取(细节不详述,网上一大堆),我们会发现当你选定一个视频的时候,会出现图1的压缩页面,最后我们的app获取的视频就是这个经过压缩后的视频(不是视频库里的原始视频,这里有个注意点,操作完该压缩视频后记得释放,系统不会帮你释放的,需要你手动来操作,下面会说到),然后通过UIImagePickerView的协议方法中的- (void)imagePickerController:(UIImagePickerController*)picker didFinishPickingMediaWithInfo:(NSDictionary*)info获取视频的Info

fileInfo = {

= "public.movie";

= "file:///private/var/mobile/Containers/Data/Application/2AAE9E44-0E6D-4499-9AC3-93D44D8342EA/tmp/trim.F36EC46C-4219-43C8-96A7-FA7141AB64D2.MOV";

= "assets-library://asset/asset.MOV?id=DEDA9406-3223-4F87-ABB2-98FB5F5EB9C4&ext=MOV";

}

是选取文件的类型,如KUTTypeImage,KUTTypeMovie。这里注意一下movie和video的区别,一个是有声音的视频文件,一个是没有声音的视频文件,当然还有Audio是只有声音没有视频。是视频的URL(如果是相机拍摄的,那么这个就是原始拍摄得到的视频;如果是在相册库里选择的,那就是压缩之后生成的视频),注意这个URL不指向相册库,通过这个URL你可以操作这个视频如删除,拷贝等,可以获取压缩后的视频的大小。是一个指向相册的URL,官方的解释是an NSURL that references an asset in the AssetsLibrary framework,通过这个URL,你可以获取视频的所有信息,包括文件名,缩略图,时长等(通过ALAssetsLibrary里的assetsLibraryassetForURL:referenceURLresultBlock:)。

如果是相机拍摄的,注意两个保存方法:图片保存到相册:UIImageJPEGRepresentation([infovalueForKey:],(CGFloat)1.0)metadata:nilcompletionBlock: failureBlock:

高保真压缩图片的方法NSData * UIImageJPEGRepresentation ( UIImage *image, CGFloat compressionQuality)

视频保存到相册::MediaURL completionBlock:failureBlock:

到这里,我们就获取了所有需要的文件以及文件信息。下面要做的就是将文件分片。

2、将获取到的文件分片

首先,我将获取到的文件保存在这这样一个类中

@interface CNFile :NSObject

@property(nonatomic,)NSString* fileType;//image or movie

@property(nonatomic,)NSString* filePath;//文件在app中路径

@property(nonatomic,)NSString* fileName;//文件名

@property(nonatomic,assign)NSIntegerfileSize;//文件大小

@property (nonatomic,assign)NSIntegertrunks;//总片数

@property(nonatomic,)NSString* fileInfo;

@property(nonatomic,strong)UIImage* fileImage;//文件缩略图

@property(nonatomic,strong) NSMutableArray* fileArr;//标记每片的上传状态

@end

这样我们就可以对每一个CNFile对象进行操作了。

-(void)readDataWithChunk:(NSInteger)chunk file:(CNFile*)file{

总片数的获取方法:

intoffset =1024*1024;(每一片的大小是1M)

NSIntegerchunks = (file.fileSize%1024==0)?((int)(file.fileSize/1024*1024)):((int)(file.fileSize/(1024*1024) +1));

NSLog(@"chunks = %ld",(long)chunks);

将文件分片,读取每一片的数据:

NSData* data;

NSFileHandle*readHandle = [:file.filePath];

[readHandleseekToFileOffset:offset * chunk];

data = [readHandlereadDataOfLength:offset];

}

这样我们就获取了每一片要上传的数据,然后询问服务器,该片是否已经存在

(方法-(void)ifHaveData:(NSData*)data WithChunk:(NSInteger)chunk file:(CNFile*)file)

,如果存在,令chunk+1,重复上面的方法读取下一片,直到服务器不存在该片,那么上传该片数据。在这个方法中注意设置该chunk的上传状态(wait loading finish),这将关系到本地判断该文件是否已全部上传完成。

下一步就是上传的过程:

-(void)uploadData:(NSData*) data WithChunk:(NSInteger) chunk file:(CNFile*)file;

在服务器返回该片上传成功后,我们要做的事有很多:

1)先将已经成功上传的本片的flag置finish

[file.fileArrreplaceObjectAtIndex:chunk withObject:@“finish"];

2)查看是否所有片的flag都已经置finish,如果都已经finishi,说明该文件上传完成,那么删除该文件,上传下一个文件或者结束。

for(NSIntegerj =0; j

if(j == chunks || ((j == chunks -1)&&([file.fileArr[j]isEqualToString:@"finish"])))

[medeleteFile:file.filePath];

[mereadNextFile];

}

3)如果没有都finish,那么看本地下一chunk对用的flag是否是wait

NSLog(@"查看第%ld片的状态",chunk+1);

for(NSIntegeri = chunk+1;i < chunks;i++)

{

NSString* flag = [file.fileArrobjectAtIndex:i];

if([flagisEqualToString:@"wait"]) {

[mereadDataWithChunk:ifileName:fileNamefile:file];

break;

}

}

在第2、3步之间可以有一个 2.5)判断是否暂停上传

if(me.isPause ==YES)

{

//将目前读到了第几个文件的第几片保存到本地

[selfsaveProgressWithChunk:chunk file:file];

return;

}

这个操作实际上和上传过程中断网是一样的,为了断点续传,在断网或者暂停的时候,我们要将目前的进度保存起来,以便下次上传时略过前面已置finish的片。

然后还有一个问题,如果我们就这样线性的一片一片上传,实际上失去了分片上传的意义,应该结合多线程,使分片上传过程并发执行,同时上传多片,这样就提高了上传效率,并充分利用了网络带宽。

dispatch_async(dispatch_queue_t queue, ^{

[mereadDataWithChunk: chunk];

})

最后注意一下,每上传完一个视频,去设置里看看你的app占用的存储空间有没有增大哦,如果你没有处理那个生成的压缩视频,你会发现你的app的空间占用量是很大的。

站在大牛的肩膀上开发。

㈢ 断点续传

1、文件过大会导致带宽资源紧张,请求速度下降 ;
2、如果上传过程中服务中断、网络中断 、页面崩溃,可能会导致文件重新开始上传。

前端选择文件后上传,后端在处理文件过程中,首先会将文件加载到 运行内存中 ,之后再调用相应的API进行 写入硬盘 内存的操作,完成整个文件的上传。

但这样直接上传文件,可能会因为某个环节出了问题导致整个流程的雪崩,所以大文件直接上传是不可取的。

解决问题最好办法是 分片断点续传 ,该方式主要是针对 大文件(比如100M以上的文件)

顾名思义就是 断点 续传

在文件上传过程中,将一个要上传的文件 分成N块 ,然后使用 多线程并发多块上传 ,因为某种原因导致上传被中断或暂停,此时中断或暂停的位置就成为 断点

前端每上传一片,将会被加载到 运行内存中 ,加载完毕后再写入硬盘,此时运行内存的临时变量会被释放,然后此临时变量会被下一片占用,再进行写入,释放...

意思是指从中断的位置继续上传剩下的部分文件,而不是从头开始上传。

上传完毕后,在服务端进行合并(合并的操作是在后端进行的,前端只是调用接口,合并的方式是由后端决定的,到底是上传一片就合并一片,或者是上传所有的之后整体进行合并)。

方式:
html5z之前的方式是 flash activeX
html5提供了文件二进制流进行分割的slice方法。

文件的分片,一般在2-5M之间。这一步得到了每一片文件的内容、每一块的序号、每一块的大小、总块数等数据。

这里提供了两个方法;一种是用SparkMD5.hashBinary( ) 直接将整个文件的二进制码传入直接返回文件的md5、这种方法对于小文件会比较有优势——简单并且速度快。
另一种方法是利用js中File对象的slice( )方法(File.prototype.slice( ))将文件分片后逐个传入spark.appendBinary( )方法来计算、最后通过spark.end( )方法输出结果,很明显,这种方法对于大型文件会非常有利——不容易出错,并且能够提供计算的进度信息

第一种方式:

第二种方式

㈣ 前端大文件分片上传(Vue)

list.vue

comUpload.js

前端git项目
后端git地址
链接地址

㈤ Android上大文件分片上传 具体怎么弄

正常情况下,一般都是在长传完成后,在服务器直接保存。

?

1
2
3
4
5
6
7

public void ProcessRequest(HttpContext context)
{
context.Response.ContentType = "text/plain";
//保存文件
context.Request.Files[0].SaveAs(context.Server.MapPath("~/1/" + context.Request.Files[0].FileName));
context.Response.Write("Hello World");
}

最近项目中用网络开源的上传组件webuploader,官方介绍webuploader支持分片上传。具体webuploader的使用方法见官网http://fex..com/webuploader/。

?

1
2
3
4
5
6
7
8
9
10
11
12

var uploader = WebUploader.create({
auto: true,
swf:'/webuploader/Uploader.swf',
// 文件接收服务端。
server: '/Uploader.ashx',
// 内部根据当前运行是创建,可能是input元素,也可能是flash.
pick: '#filePicker',
chunked: true,//开启分片上传
threads: 1,//上传并发数
//由于Http的无状态特征,在往服务器发送数据过程传递一个进入当前页面是生成的GUID作为标示
formData: {guid:"<%=Guid.NewGuid().ToString()%>"}
});

webuploader的分片上传是把文件分成若干份,然后向你定义的文件接收端post数据,如果上传的文件大于分片的尺寸,就会进行分片,然后会在post的数据中添加两个form元素chunk和chunks,前者标示当前分片在上传分片中的顺序(从0开始),后者代表总分片数。

㈥ 前端分片上传

需求描述: 前端获取文件md5码且实现分片上传

步骤:

一:获取文件md5

    1.插件spark-md5,还有另外一个插件(browser-md5-file)但是不兼容ie11,至于其他ie版本,未测

    2.以分片的方式获取文件MD5码,一下为封装的方法:

 /**

   * @param file 文件

   * @param chunkSize 分片大小

   * @returns Promise

   */

  const getFileMd5 = (file, chunkSize) => {

    return new Promise((resolve, reject) => {

      setSpin({

        spinning: true,

        tip: '正在努力导入应用数据,请耐心等待......',

      });

      let blobSlice = File.prototype.slice || File.prototype.mozSlice || File.prototype.webkitSlice;

      let chunks = Math.ceil(file.size / chunkSize); // 总分片数

      let currentChunk = 0; 

      let spark = new SparkMD5.ArrayBuffer();

      let fileReader = new FileReader();

      fileReader.onload = function(e) {

        spark.append(e.target.result);

        currentChunk++;

        if (currentChunk < chunks) {

          loadNext();

        } else {

          let md5 = spark.end(); // 结束时调用

          resolve(md5);

        }

      };

      fileReader.onerror = function(e) {

        reject(e);

      };

      // 文件分片

      function loadNext() {

        let start = currentChunk * chunkSize;

        let end = start + chunkSize;

        if (end > file.size) {

          end = file.size;

        }

        fileReader.readAsArrayBuffer(blobSlice.call(file, start, end));

      }

      loadNext();

    });

  }

二、文件分片调取接口

  /**

   *

   * @param {Object} file 文件

   * @param {Number} index 下标

   * @param {Number} chunkSize 分片数

   * @param {String} md5 md5码

   */

  const fileImport = (file, index, chunkSize, md5) => { // 获取MD5

    const chunks = Math.ceil(file.size / chunkSize); // 防止文件截取不完整 所以向上取整

    if (file) {

      let upSize = index * chunkSize;

      if (index > chunks - 1) {

        return;

      }

      let blob = file.slice(upSize, upSize + chunkSize); // 截取文件

      try {

        let formData = new FormData();

        formData.append('file', blob);

        formData.append('md5', md5);

        formData.append('chunk', index);

        formData.append('chunks', chunks);

        sliceImportVisualization(formData).then(async res => {

          if (res?.isSuccess) {

            await fileImport(file, ++index, chunkSize, md5); // 在上一片传输完成后再调用 切记 切记

            const { data = {} } = res;

            const { file_name } = data;

            if (file_name) {

              importVisualization({ file_name }).then(res => {

                setSpin({spinning: false});

              });

            }

          }

        });

      } catch (err) {

        console.log('分片上传错误...', err);

      }

    }

  };

㈦ js 大文件分片上传处理如何实现

推荐采用webuploader控件来解决。
关于WebUploader的功能说明:
大文件上传续传
支持超大文件上传(100G+)和续传,可以关闭浏览器,重启系统后仍然继续上传。
开源
提供ASP.NET,JSP,php示例和源代码,其中JSP提供MySQL,Oracle,SQL Server数据库的配置和示例代码。
分片、并发
分片与并发结合,将一个大文件分割成多块,并发上传,极大地提高大文件的上传速度。
当网络问题导致传输错误时,只需要重传出错分片,而不是整个文件。另外分片传输能够更加实时的跟踪上传进度。
预览、压缩
支持常用图片格式jpg,jpeg,gif,bmp,png预览与压缩,节省网络数据传输。
解析jpeg中的meta信息,对于各种orientation做了正确的处理,同时压缩后上传保留图片的所有原始meta数据。
多途径添加文件
支持文件多选,类型过滤,拖拽(文件&文件夹),图片粘贴功能。上传本地指定路径的文件,不需要通过点击按钮选择文件。
粘贴功能主要体现在当有图片数据在剪切板中时(截屏工具如QQ(Ctrl + ALT + A), 网页中右击图片点击复制),Ctrl + V便可添加此图片文件。
HTML5 & FLASH
兼容主流浏览器和低版本浏览器,接口一致,实现了两套运行时支持,用户无需关心内部用了什么内核。而且支持IE6,IE8浏览器。
同时Flash部分没有做任何UI相关的工作,方便不关心flash的用户扩展和自定义业务需求。
基于内存映射模式进行IO操作,充分发挥操作系统性能。
MD5秒传
当文件体积大、量比较多时,支持上传前做文件md5值验证,一致则可直接跳过。
如果服务端与前端统一修改算法,取段md5,可大大提升验证性能,耗时在20ms左右。
易扩展、可拆分
采用可拆分机制, 将各个功能独立成了小组件,可自由搭配。
采用AMD规范组织代码,清晰明了,方便高级玩家扩展。

㈧ PHP实现浏览器端大文件分片上传如何实现

分片上传的原理就是通过切割上传文件,然后在浏览器的头部通过etag来进行划分文件传输,服务器端接收到文件片段和分割起始符之后,进行拼接文件,最后合成一个大文件。

你可以自己通过php来获取浏览器头部传输标志来进行文件的拼接组装,也可以通过现有的大文件传输类来上传文件。

关键点

记住分割文件点,也就是分割文件的顺序,拼接文件需要通过etag按照顺序拼接,分片可以并发传输,这其实也是并发下载的原理。

㈨ web uploader的demo怎样导入css文件

WebUploader通过准备dom结构、初始化、显示用户选择、文件上传进度、提示信息实现导入JS, CSS, SWF资源。

WebUploader的demo导入css等资源的流程:

  1. WebUploader概述:WebUploader是由Bai WebFE(FEX)团队开发的一个简单的以HTML5为主,FLASH为辅的现代文件上传组件。WebUploader文件上传组件在现代的浏览器里面能充分发挥HTML5的优势,同时又不摒弃主流IE浏览器,沿用原来的FLASH运行时,兼容IE6+,iOS 6+, android 4+。两套运行时,同样的调用方式,可供用户任意选用。 采用大文件分片并发上传,极大的提高了文件上传效率。

  2. 功能介绍:

    A、分片、并发:分片与并发结合,将一个大文件分割成多块,并发上传,极大地提高大文件的上传速度。

    B、分片、并发:分片与并发结合,将一个大文件分割成多块,并发上传,极大地提高大文件的上传速度。

    当网络问题导致传输错误时,只需要重传出错分片,而不是整个文件。另外分片传输能够更加实时的跟踪上传进度。

    C、预览、压缩:支持常用图片格式jpg,jpeg,gif,bmp,png预览与压缩,节省网络数据传输。

    解析jpeg中的meta信息,对于各种orientation做了正确的处理,同时压缩后上传保留图片的所有原始meta数据。

    D、多途径添加文件:支持文件多选,类型过滤,拖拽(文件&文件夹),图片粘贴功能。

    粘贴功能主要体现在当有图片数据在剪切板中时,Ctrl + V便可添加此图片文件。

    E、HTML5 & FLASH:兼容主流浏览器,接口一致,实现了两套运行时支持,用户无需关心内部用了什么内核。

    同时Flash部分没有做任何UI相关的工作,方便不关心flash的用户扩展和自定义业务需求。

    F、MD5秒传:当文件体积大、量比较多时,支持上传前做文件md5值验证,一致则可直接跳过。

    如果服务端与前端统一修改算法,取段md5,可大大提升验证性能,耗时在20ms左右。

    G、易扩展、可拆分:采用可拆分机制, 将各个功能独立成了小组件,可自由搭配。

    采用AMD规范组织代码,清晰明了,方便高级玩家扩展。

    H、引入资源:使用Web Uploader文件上传需要引入三种资源:JS, CSS, SWF。

    <!--引入CSS-->
    <linkrel="stylesheet"type="text/css"href="webuploader文件夹/webuploader.css">
    <!--引入JS-->
    <scripttype="text/javascript"src="webuploader文件夹/webuploader.js"></script>
    <!--SWF在初始化的时候指定-->
  3. 文件上传:WebUploader只包含文件上传的底层实现,不包括UI部分。所以交互方面可以自由发挥。

    A、Html部分。首先准备dom结构,包含存放文件信息的容器、选择按钮和上传按钮三个部分。

    <divid="uploader"class="wu-example">
    <!--用来存放文件信息-->
    <divid="thelist"class="uploader-list"></div>
    <divclass="btns">
    <divid="picker">选择文件</div>
    <buttonid="ctlBtn"class="btnbtn-default">开始上传</button>
    </div>
    </div>

    B、初始化Web Uploader,具体说明,请看一下代码中的注释部分。

    varuploader=WebUploader.create({
    //swf文件路径
    swf:BASE_URL+'/js/Uploader.swf',
    //文件接收服务端。
    server:'Url/fileupload.php',
    //选择文件的按钮。可选。
    //内部根据当前运行是创建,可能是input元素,也可能是flash.
    pick:'#picker',
    //不压缩image,默认如果是jpeg,文件上传前会压缩一把再上传!
    resize:false
    });

    C、显示用户选择。由于webuploader不处理UI逻辑,所以需要去监听fileQueued事件来实现。

    D、文件上传进度。文件上传中,Web Uploader会对外派送uploadProgress事件,其中包含文件对象和该文件当前上传进度。

    E、文件成功、失败处理。文件上传失败会派送uploadError事件,成功则派送uploadSuccess事件。不管成功或者失败,在文件上传完后都会触发uploadComplete事件。

  4. 创建Web Uploader实例

    //初始化WebUploader
    varuploader=WebUploader.create({
    //选完文件后,是否自动上传。
    auto:true,
    //swf文件路径
    swf:BASE_URL+'/js/Uploader.swf',
    //文件接收服务端。
    server:'http://webuploader.app.com/server/fileupload.php',
    //选择文件的按钮。可选。
    //内部根据当前运行是创建,可能是input元素,也可能是flash.
    pick:'#filePicker',
    //只允许选择图片文件。
    accept:{
    title:'Images',
    extensions:'gif,jpg,jpeg,bmp,png',
    mimeTypes:'image/*'
    }
    });

附:

  1. 监听fileQueued事件,通过uploader.makeThumb来创建图片预览图。PS: 这里得到的是Data URL数据,IE6、IE7不支持直接预览。可以借助FLASH或者服务端来完成预览。

  2. 然后剩下的就是上传状态提示了,当文件上传过程中, 上传成功,上传失败,上传完成都分别对应uploadProgress,uploadSuccess, uploadError, uploadComplete事件。

㈩ webuploader分片上传的实现代码(前后端分离)

本文介绍了webuploader分片上传的实现代码(前后端分离),分享给大家,具体如下:
WebUploader是由Bai
WebFE(FEX)团队开发的一个简单的以HTML5为主,FLASH为辅的现代文件上传组件。在现代的浏览器里面能充分发挥HTML5的优势,同时又不摒弃主流IE浏览器,沿用原来的FLASH运行时,兼容IE6+,iOS
6+,
android
4+。两套运行时,同样的调用方式,可供用户任意选用。采用大文件分片并发上传,极大的提高了文件上传效率。(这个是从官网上直接的解释)
功能描述
1、webuploader是网络研发的上传组件,文档不是特别规整,但是也够用了。
2、前端使用官网的上传图片demo,在此基础上代码略微调整做分片。既可以上传图片也可以上传文件。文件超过分片大小才启用分片。
3、分片上传已做md5校验,达到秒传的效果。分片以后需要合并,可以先分片后合并,也可以边分片边合并,本示例采用的是边分片边合并的方案。
4、后端用springboot做框架搭建。springMVC做rest服务,开启跨域访问
5、容器用springboot内置的tomcat插件,运行Application的main方法即可启动服务;
显示效果
关键代码前端
WebUploader.Uploader.register({
'name':
'webUploaderHookCommand',
'before-send-file':
'beforeSendFile',
"before-send":
"beforeSend"
},
{
beforeSendFile:
function(file)
{
var
task
=
new
WebUploader.Deferred();
fileName
=
file.name;
fileSize
=
file.size;
(new
WebUploader.Uploader()).md5File(file,
0,
10
*
1024
*
1024).progress(function(percentage)
{}).then(function(val)
{
fileMd5
=
val;
var
url
=
checkUrl;
var
data
=
{
type:
0,
fileName:
fileName,
fileMd5:
fileMd5,
fileSize:
fileSize
};
$.ajax({
type:
"POST",
url:
url,
data:
data,
cache:
false,
async:
false,
//
同步
timeout:
1000,
//
todo
超时的话,只能认为该分片未上传过
dataType:
"json",
error:
function(XMLHttpRequest,
textStatus,
errorThrown)
{
file.statusText
=
'server_error';
task.reject();
}
}).then(function(data,
textStatus,
jqXHR)
{
if(data.rtn
==
0)
{
if(data.obj
==
1)
{
file.statusText
=
'file_existed';
task.reject();
}
else
{
task.resolve();
}
}
else
{
task.reject();
}
});
});
return
task.promise();
},
beforeSend:
function(block)
{
var
task
=
new
WebUploader.Deferred();
var
url
=
checkUrl;
var
data
=
{
type:
1,
fileName:
fileName,
fileMd5:
fileMd5,
chunk:
block.chunk,
fileSize:
block.end
-
block.start
};
$.ajax({
type:
"POST",
url:
url,
data:
data,
cache:
false,
async:
false,
//
同步
timeout:
1000,
//
todo
超时的话,只能认为该分片未上传过
dataType:
"json"
}).then(function(data,
textStatus,
jqXHR)
{
if(data.rtn
==
0
&&
data.obj
==
1)
{
task.reject();
//
分片存在,则跳过上传
}
else
{
task.resolve();
}
});
this.owner.options.formData.fileMd5
=
fileMd5;
this.owner.options.formData.chunkSize
=
chunkSize;
return
task.promise();
}
});
//
实例化
uploader
=
WebUploader.create({
pick:
{
id:
'#filePicker',
label:
'点击选择文件'
},
formData:
{
uid:
123
},
dnd:
'#dndArea',
//指定文件拖拽的区域
paste:
'#uploader',
//指定监听paste事件的容器,如果不指定,不启用此功能。此功能为通过粘贴来添加截屏的图片。建议设置为document.body.
swf:
'../plugins/webuploader/Uploader.swf',
chunked:
true,
chunkSize:
chunkSize,
chunkRetry:
false,
threads:
1,
server:
uploadUrl,
//
runtimeOrder:
'flash',
//
accept:
{
//
title:
'Images',
//
extensions:
'gif,jpg,jpeg,bmp,png',
//
mimeTypes:
'image/*'
//
},
//
禁掉全局的拖拽功能。这样不会出现图片拖进页面的时候,把图片打开。
disableGlobalDnd:
true,
fileNumLimit:
300
//限制多文件上传的个数
//fileSizeLimit:
200
*
1024
*
1024,
//
限制所有文件的大小
200
M
//fileSingleSizeLimit:
50
*
1024
*
1024
//
限制单个文件的大小
50
M
});
后端
import
java.io.File;
import
java.io.IOException;
import
org.slf4j.Logger;
import
org.slf4j.LoggerFactory;
import
org.springframework.beans.factory.annotation.Value;
import
org.springframework.stereotype.Service;
import
org.springframework.web.multipart.MultipartFile;
import
com.bear.upload.util.FileUtil;
import
com.bear.upload.util.RETURN;
import
com.bear.upload.vo.CheckMd5FileVO;
import
com.bear.upload.vo.UploadVO;
@Service
public
class
ChunkUploadService
{
private
static
Logger
LOG
=
LoggerFactory.getLogger(ChunkUploadService.class);
@Value("${file.upload.path}")
private
String
UPLOAD_PATH;
private
static
final
String
Delimiter
=
"-";
/**
*
上传之前校验(整个文件、分片)
*
*
@param
md5FileVO
*
@return
*/
public
Object
check(CheckMd5FileVO
md5FileVO)
{
Integer
type
=
md5FileVO.getType();
Long
chunk
=
md5FileVO.getChunk();
String
fileName
=
md5FileVO.getFileName();
Long
fileSize
=
md5FileVO.getFileSize();
if
(type
==
0)
{//
未分片校验
String
destfilePath
=
UPLOAD_PATH
+
File.separator
+
fileName;
File
destFile
=
new
File(destfilePath);
if
(destFile.exists()
&&
destFile.length()
==
fileSize)
{
return
RETURN.success("文件已存在,跳过",
1);
}
else
{
return
RETURN.success("文件不存在",
0);
}
}
else
{//
分片校验
String
fileMd5
=
md5FileVO.getFileMd5();
String
destFileDir
=
UPLOAD_PATH
+
File.separator
+
fileMd5;
String
destFileName
=
chunk
+
Delimiter
+
fileName;
String
destFilePath
=
destFileDir
+
File.separator
+
destFileName;
File
destFile
=
new
File(destFilePath);
if
(destFile.exists()
&&
destFile.length()
==
fileSize)
{
return
RETURN.success("分片已存在,跳过",
1);
}
else
{
return
RETURN.success("分片不存在",
0);
}
}
}
/**
*
文件上传
*
*
@param
file
*
@param
uploadVO
*
@param
appVersion
*
@return
*/
public
Object
upload(MultipartFile
file,
UploadVO
uploadVO)
{
Long
chunk
=
uploadVO.getChunk();
if
(chunk
==
null)
{//
没有分片
return
UnChunkUpload(file,
uploadVO);
}
else
{//
分片
return
ChunkUpload(file,
uploadVO);
}
}
/**
*
分片上传
*
*
@param
file
*
@param
uploadVO
*
@param
appVersion
*
@return
*/
public
Object
ChunkUpload(MultipartFile
file,
UploadVO
uploadVO)
{
String
fileName
=
uploadVO.getName();
String
fileMd5
=
uploadVO.getFileMd5();
Long
chunk
=
uploadVO.getChunk();//
当前片
Long
chunks
=
uploadVO.getChunks();//
总共多少片
//
分片目录创建
String
chunkDirPath
=
UPLOAD_PATH
+
File.separator
+
fileMd5;
File
chunkDir
=
new
File(chunkDirPath);
if
(!chunkDir.exists())
{
chunkDir.mkdirs();
}
//
分片文件上传
String
chunkFileName
=
chunk
+
Delimiter
+
fileName;
String
chunkFilePath
=
chunkDir
+
File.separator
+
chunkFileName;
File
chunkFile
=
new
File(chunkFilePath);
try
{
file.transferTo(chunkFile);
}
catch
(Exception
e)
{
LOG.error("分片上传出错",
e);
return
RETURN.fail("分片上传出错",
1);
}
//
合并分片
Long
chunkSize
=
uploadVO.getChunkSize();
long
seek
=
chunkSize
*
chunk;
String
destFilePath
=
UPLOAD_PATH
+
File.separator
+
fileName;
File
destFile
=
new
File(destFilePath);
if
(chunkFile.length()
>
0)
{
try
{
FileUtil.randomAccessFile(chunkFile,
destFile,
seek);
}
catch
(IOException
e)
{
LOG.error("分片{}合并失败:{}",
chunkFile.getName(),
e.getMessage());
return
RETURN.fail("分片合并失败",
1);
}
}
if
(chunk
==
chunks
-
1)
{
//
删除分片文件夹
FileUtil.deleteDirectory(chunkDirPath);
return
RETURN.success("上传成功",
1);
}
else
{
return
RETURN.fail("上传中...",
1);
}
}
/**
*
未分片上传
*
*
@param
file
*
@param
uploadVO
*
@param
appVersion
*
@return
*/
public
Object
UnChunkUpload(MultipartFile
file,
UploadVO
uploadVO)
{
String
fileName
=
uploadVO.getName();
//
String
fileMd5
=
uploadVO.getFileMd5();
//
文件上传
File
destFile
=
new
File(UPLOAD_PATH
+
File.separator
+
fileName);
if
(file
!=
null
&&
!file.isEmpty())
{
//
上传目录
File
fileDir
=
new
File(UPLOAD_PATH);
if
(!fileDir.exists())
{
fileDir.mkdirs();
}
if
(destFile.exists())
{
destFile.delete();
}
try
{
file.transferTo(destFile);
return
RETURN.success("上传成功",
0);
}
catch
(Exception
e)
{
LOG.error("文件上传出错",
e);
return
RETURN.fail("文件上传出错",
0);
}
}
return
RETURN.fail("上传失败",
0);
}
}
以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持脚本之家。
您可能感兴趣的文章:Vue2.0结合webuploader实现文件分片上传功能使用WebUploader实现分片断点上传文件功能(二)webuploader在springMVC+jquery+Java开发环境下的大文件分片上传的实例代码jQuery
webuploader分片上传大文件

热点内容
光遇安卓音韵季有什么 发布:2024-10-06 05:06:51 浏览:76
apk脚本破解 发布:2024-10-06 04:33:23 浏览:51
数模编程 发布:2024-10-06 04:04:43 浏览:16
雷霆一击服务器搭建 发布:2024-10-06 03:58:14 浏览:500
导演脚本 发布:2024-10-06 03:37:34 浏览:566
施耐德有密码程序如何打开 发布:2024-10-06 03:37:00 浏览:893
解压缩文件修复 发布:2024-10-06 03:31:17 浏览:705
如何设置休眠时不需要开机密码 发布:2024-10-06 03:03:25 浏览:233
密码工作三个事关的内容是什么 发布:2024-10-06 02:39:44 浏览:426
21款昂科威哪个配置好 发布:2024-10-06 02:20:39 浏览:839