java list断点续传_java分片上传,断点续传

1,是基于webUploader的前端开源插件实现的大大文件 分片上传功能:四种文件上传格式(以后要改进的地方)普通按钮点击上传

拖拽上传

复制粘贴上传

拖拽+按钮+复制粘贴上传

多线程上传文件

2,简单的文件分片合并上传原理:

借鉴的博客:  地址

前段页面

分片上传6

//方式6

$(".btnFile6").click(function () {

var upload = function (file, skip) {

var formData = new FormData();//初始化一个FormData对象

var blockSize = 1000000;//每块的大小

var nextSize = Math.min((skip + 1) * blockSize, file.size);//读取到结束位置

var fileData = file.slice(skip * blockSize, nextSize);//截取 部分文件 块

formData.append("file", fileData);//将 部分文件 塞入FormData

formData.append("fileName", file.name);//保存文件名字

$.ajax({

url: "/Home/SaveFile6",

type: "POST",

data: formData,

processData: false,  // 告诉jQuery不要去处理发送的数据

contentType: false,   // 告诉jQuery不要去设置Content-Type请求头

success: function (responseText) {

$(".result").html("已经上传了" + (skip + 1) + "块文件");

if (file.size <= nextSize) {//如果上传完成,则跳出继续上传

alert("上传完成");

return;

}

upload(file, ++skip);//递归调用

}

});

};

var file = $("#file6")[0].files[0];

upload(file, 0);

});

后端代码public string SaveFile6()

{

//保存文件到根目录 App_Data + 获取文件名称和格式

var filePath = Server.MapPath("~/App_Data/") + Request.Form["fileName"];

//创建一个追加(FileMode.Append)方式的文件流

using (FileStream fs = new FileStream(filePath, FileMode.Append, FileAccess.Write))

{

using (BinaryWriter bw = new BinaryWriter(fs))

{

//读取文件流

BinaryReader br = new BinaryReader(Request.Files[0].InputStream);

//将文件留转成字节数组

byte[] bytes = br.ReadBytes((int)Request.Files[0].InputStream.Length);

//将字节数组追加到文件

bw.Write(bytes);

}

}

return "保存成功";

}

3,监控文件上传的三个时间点:(上传)本地项目实例时间点1: 所有分块进行上传之前(1,算文件的唯一标识,2,判断文件是否秒传)计算分片文件的MD5唯一标识,

请求后台是否保存过该文件,存在跳过该文件,不存在则继续上传.

时间点2: 如果分片上传, 每个分片上传之前(1, 通知询问后台是否已经保存成功, 用于断点续传)每个每个分块有每个分块的下标和大小.请求后台是否保存过当前分块,存在跳过该分片文件,实现断点续传

请求后台是否保存完成该文件信息,如果保存过,则跳过; 如果不存在或者不完整则发送该分块内容

携带当前文件的唯一标识到后台, 用于让后台创建保存该文件分块的目录

时间点3: 所有分块上传成功之后(1, 通知后台进行分块文件的合并工作)前台通知后台合并文件

3,后台文件的处理:FileChannel outChannel  = FileOutputStream(file).getChannel()FileChannel inChannel(File tmp : fileList) {

inChannel = FileInputStream(tmp).getChannel()inChannel.transferTo(inChannel.size()outChannel)inChannel.close()file.delete()}

(outChannel != ) {

(f)outChannel.close()}

文件上传的前端代码:

webuploaderDemo

.upload-table{

padding: 2px 12px;

}

.fileQueue{

height: 300px;

overflow-x: hidden;

overflow-y: auto;

background-color: #f8f8f8;

width: 100%;

}

.hiden{

display: none

}

var base = "/upload";

var element;

var layer;

var index=0;

var batchWebUpload;

var fileAllNum=0;

var fileAllSize=0;

var successNum=0;

var successSize=0;

var  percentages = {}; // 所有文件的进度信息,key为file id

$(function(){

layui.use(['layer','element','code'], function(){

element = layui.element;

layer = layui.layer;

layui.code({

elem: 'pre', //默认值为.layui-code

encode: true, //是否转义html标签。默认不开启

about: false

});

layer.ready(function(){

showWindow()

});

});

var fileCheckUrl=base+"/file/checkFile";//检测文件是否存在url

var checkChunkUrl=base+"/file/checkChunk";//检测分片url

var mergeChunksUrl=base+"/file/mergeChunks";//合并文件请求地址

//监控文件上传的三个时间点(注意:该段代码必须放在WebUploader.create之前)

//时间点1::所有分块进行上传之前(1.可以计算文件的唯一标记;2.可以判断是否秒传)

//时间点2: 如果分块上传,每个分块上传之前(1.询问后台该分块是否已经保存成功,用于断点续传)

//时间点3:所有分块上传成功之后(1.通知后台进行分块文件的合并工作)

WebUploader.Uploader.register({

"before-send-file":"beforeSendFile",

"before-send":"beforeSend",

"after-send-file":"afterSendFile"

},{

//时间点1::所有分块进行上传之前调用此函数

//时间点1::所有分块进行上传之前调用此函数

beforeSendFile:function(file){//利用md5File()方法计算文件的唯一标记符

//创建一个deffered

var deferred = WebUploader.Deferred();

//1.计算文件的唯一标记,用于断点续传和秒传,获取文件前2m的md5值,越小越快,防止碰撞,把文件名文件大小和md5拼接作为文件唯一标识

(new WebUploader.Uploader()).md5File(file,0,2*1024*1024).progress(function(percentage){

}).then(function(val){

fileMd5 = file.size+"-"+val+"-"+file.name;//防止碰撞,把文件名文件大小和md5拼接作为文件唯一标识

file.fileMd5=fileMd5;

//2.请求后台是否保存过该文件,如果存在,则跳过该文件,实现秒传功能

$.ajax({

type:"POST",

url:fileCheckUrl,

data:{

fileMd5:fileMd5//文件唯一标记

},

dataType:"json",

success:function(response){

console.log(response);

if(response.success){

console.log($("#"+file.id).find('.percent').html());

$("#"+file.id).find('.percent').html("100%");

$("#"+file.id).find(".layui-progress-bar").removeClass('layui-bg-blue');

element.progress('progress_'+file.id, '100%');

batchWebUpload.skipFile(file);

successNum++;

successSize+=file.size;

//如果存在,则跳过该文件,秒传成功

deferred.reject();

}else{

//继续上传

deferred.resolve();

}

}

}

);

});

//返回deffered

return deferred.promise();

},

//时间点2:如果有分块上传,则 每个分块上传之前调用此函数

//block:代表当前分块对象

beforeSend:function(block){//向后台发送当前文件的唯一标记,用于后台创建保存分块文件的目录

//1.请求后台是否保存过当前分块,如果存在,则跳过该分块文件,实现断点续传功能

var deferred = WebUploader.Deferred();

//请求后台是否保存完成该文件信息,如果保存过,则跳过,如果没有,则发送该分块内容

$.ajax({

type:"POST",

url:checkChunkUrl,

data:{

//文件唯一标记,敲黑板划重点了,不要用file.fileMd5,不然服务器上的文件会出错

fileMd5: block.file.fileMd5,

//当前分块下标

chunk:block.chunk,

//当前分块大小

chunkSize:block.end-block.start

},

dataType:"json",

success:function(response){

if(response.success){

//分块存在,跳过该分块

deferred.reject();

}else{

//分块不存在或者不完整,重新发送该分块内容

deferred.resolve();

}

}

}

);

//携带当前文件的唯一标记到后台,用于让后台创建保存该文件分块的目录

// this.owner.options.formData.fileMd5 = block.file.fileMd5;

return deferred.promise();

},

//时间点3:所有分块上传成功之后调用此函数

afterSendFile:function(file){//前台通知后台合并文件

//1.如果分块上传,则通过后台合并所有分块文件

//请求后台合并文件

$.ajax({

type:"POST",

url:mergeChunksUrl,

data:{

//文件唯一标记

fileMd5:file.fileMd5,

//文件名称

fileName:file.name

},

dataType:"json",

success:function(response){

console.log("合并分片完成");

console.log(response);

$("#"+file.id).find(".layui-progress-bar").removeClass('layui-bg-blue');

element.progress('progress_'+file.id, '100%');

$("#"+file.id).find('.percent').html("100%");

successNum++;

successSize+=file.size;

}

});

}

});

var batchWebUpload_btn = $("#batchWebUpload");

batchWebUpload = WebUploader.create({

auto:false,

pick: {

id: batchWebUpload_btn,//指定选择文件的按钮容器,不指定则不创建按钮。注意 这里虽然写的是 id, 不仅支持 id, 还支持 class, 或者 dom 节点。

//label : title, 官方建议采用 innerHTML 代替

//innerHTML : title,

multiple :true //开启文件多选

},

flash:base+'/staticresource/webuploader/Uploader.swf',//ie9一下会自动使用flash上传

/** accept:{//不验证文件类型了

title: '不验证了',//字符串类型,文字描述

extensions: '*',//允许的文件后缀,不带点,多个用逗号分割。

mimeTypes: 'application/*,'//多个用逗号分割,怎么不知道咋写的,参考w3c  MIME 参考手册,传送门 http://www.w3school.com.cn/media/media_mimeref.asp

},**/

server: base+"/file/uploadChunks",

//压缩图片,如果图片尺寸超过设置的尺寸,会自动压缩图片,必要时会裁剪

compress:{

width: 600,

height: 600,

// 图片质量,只有type为`image/jpeg`的时候才有效。

quality: 90,

// 是否允许放大,如果想要生成小图的时候不失真,此选项应该设置为false.

allowMagnify: false,

// 是否允许裁剪

crop: false,

// 是否保留头部meta信息。

preserveHeaders: true,

// 如果发现压缩后文件大小比原来还大,则使用原来图片

// 此属性可能会影响图片自动纠正功能

noCompressIfLarger: false

},

// 单位字节,如果图片大小小于此值,不会采用压缩。512k  512*1024,如果设置为0,原图尺寸大于设置的尺寸就会压缩;如果大于0,只有在原图尺寸大于设置的尺寸,并且图片大小大于此值,才会压缩

compressSize: 0,

fileNumLimit : 10,//验证文件总数量, 超出则不允许加入队列,默认值:undefined,如果不配置,则不限制数量

fileSizeLimit : 100*1024*1024*1024, //1kb=1024*1024,验证文件总大小是否超出限制, 超出则不允许加入队列。

fileSingleSizeLimit :10*1024*1024*1024, //验证单个文件大小是否超出限制, 超出则不允许加入队列。

chunked:true,//是否开启分片上传

threads:3,

chunkSize:5*1024*1024,//如果要分片,每一片的文件大小

prepareNextFile:false//在上传当前文件时,准备好下一个文件,请设置成false,不然开启文件多选你浏览器会卡死

});

//当文件上传成功时触发。file {File} File对象, response {Object}服务端返回的数据

batchWebUpload.on('uploadSuccess',function(file,response){

layer.msg("上传完成,服务端返回信息请按F12,看控制台:");

console.log(file);

if(response.success){

console.log(response);

}

})

//错误类型。文件验证不通过时触发

//错误类型说明:Q_EXCEED_NUM_LIMIT 上传文件超过限制的数量

//Q_EXCEED_SIZE_LIMIT文件总大小超出限制

//Q_TYPE_DENIED 当文件类型不对

batchWebUpload.on("error",function(type,file){

console.log(type);

if (type=="Q_TYPE_DENIED"){

layer.msg("只能上传gif,jpg,jpeg,bmp,png格式文件");

}else if(type=="Q_EXCEED_SIZE_LIMIT"){

layer.msg("所有的文件大小总和不能超过10M");

}else if(type=='F_EXCEED_SIZE'){

layer.msg("单个文件大小不能超过1M");

}else if(type=='Q_EXCEED_NUM_LIMIT'){

layer.msg(typeName+"最多只能上传10个");

}else if(type=='F_DUPLICATE'){

layer.msg(file.name+"已经在上传队列,请勿重复上传");

}else{

layer.msg("上传出错");

}

})

//文件加入队列

batchWebUpload.on("fileQueued",function(file){

fileAllNum++;

fileAllSize+=file.size;

var fileSize = (file.size/1024/1024.0).toFixed(2)+"M";

var progress = '

var buttons = '暂停';

buttons+='继续上传';

buttons+='删除';

var htm = '

'+file.name+

'

'+file.ext+

'

'+fileSize+

'

'+progress+  '0%等待上传'+buttons+'';

$("#fileList").append(htm);

//绑定事件

$("#pause_Btn_"+file.id).bind('click',function(){

batchWebUpload.stop(file);

})

$("#continue_Btn_"+file.id).bind('click',function(){

batchWebUpload.upload(file);

})

$("#delete_Btn_"+file.id).bind('click',function(){

batchWebUpload.removeFile( file, true );//从文件队列移除

})

percentages[ file.id ] = [ file.size, 0 ];

file.on('statuschange', function( cur, prev ) {

// 成功

if ( cur === 'error' || cur === 'invalid' ) {

percentages[ file.id ][ 1 ] = 1;

}  else if ( cur === 'queued' ) {

percentages[ file.id ][ 1 ] = 0;

}

})

$("#"+file.id).find('.percent').html("0%");

element.progress('progress_'+file.id, '0%');

});

/**从文件队列移除**/

batchWebUpload.on('fileDequeued', function( file ) {

fileAllNum--;

fileAllSize-=file.size;

delete percentages[ file.id ];

});

/**上传之前**/

batchWebUpload.on('uploadBeforeSend', function( block, data, headers ) {

data.fileMd5 = block.file.fileMd5;

//block.file.chunks = block.chunks;//当前文件总分片数量

data.chunks = block.file.chunks;

});

/**上传过程中触发,携带上传进度**/

batchWebUpload.on('uploadProgress',function(file ,percentage){

var percent=(percentage*100 ).toFixed(2)+"%";

element.progress('progress_'+file.id, percent);//设置进度条百分比

if(JSON.stringify(percentages) != "{}"){

percentages[ file.id ][ 1 ] = percentage;

}

if(percentage==1){

percentages[ file.id ][ 1 ] = 1;

}

$("#"+file.id).find(".status").text("正在上传");

$("#"+file.id).find('.percent').html(percent);

})

batchWebUpload.on( 'all', function( type ,file) {

updateTotalProgress();

switch( type ) {

case 'uploadComplete':

parentId = file.id;

percentages[ file.id ][ 1 ] = 1;

break;

case 'uploadFinished':

break;

case 'uploadProgress':

break;

case 'uploadStart':

break;

case 'stopUpload':

break;

}

})

})

/**左下角弹出框**/

function showWindow(){

if(index!=0){

try{

layer.restore(index);

}catch(err){

//console.log("弹出层已经打开");

return index;

}

return index;

}

//iframe窗

index=layer.open({

type: 1,

title:  ['上传队列', 'font-size:14px;'],

closeBtn: 0, //不显示关闭按钮

shade: false,

area: ['700px', '400px'],

offset: 'rb', //右下角弹出

anim: 2,

maxmin :true,

content: $("#fileListDom"), //iframe的url,no代表不显示滚动条

});

return index;

}

function startAll(file){

batchWebUpload.upload(file);

}

function stopUpload(file){

if(file==undefined){

batchWebUpload.stop();

}else{

batchWebUpload.stop(file);

}

}

function cancelFile(file){

batchWebUpload.cancelFile(file);

}

/**设置总百分比**/

function updateTotalProgress() {

var fize = (fileAllSize/1024/1024.0).toFixed(2);

var sSize = (successSize/1024/1024.0).toFixed(2);

$("#fileQueueNum").text(fileAllNum)

$("#fileQueueSize").text(fize);

var loaded = 0;

var total = 0;

var percent = 0;;

$.each( percentages, function( k, v ) {

total += v[ 0 ];

loaded += v[ 0 ] * v[ 1 ];

} );

percent = total ? loaded / total : 0;

$("#successNum").text(successNum);

$("#successSize").text(sSize);

var show_pe= Math.round( percent * 100 ) + '%';

element.progress('sumProgress', show_pe);

$("#sumPercent").text(show_pe);

}

划重点,多选,分片批量上传+断点续传

全部开始

全部暂停

文件名文件类型文件大小进度百分比状态操作

选中0个文件,共0M。

上传成功0个文件,共0M。

后端代码

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
AWS S3分片上传断点续传是一种常见的上传大文件的方式,它可以将一个大文件分割成多个小块进行上传,同时支持在上传过程中中断和恢复。 下面是使用Java实现AWS S3分片上传断点续传的步骤: 1. 创建AmazonS3客户端 首先,需要创建AmazonS3客户端,以便可以连接到AWS S3服务并执行操作。可以使用以下代码创建客户端: ``` AmazonS3 s3Client = AmazonS3ClientBuilder.standard() .withRegion(Regions.US_EAST_1) .build(); ``` 2. 初始化分片上传上传之前,需要初始化分片上传并获取分片上传ID。可以使用以下代码初始化分片上传: ``` InitiateMultipartUploadRequest initRequest = new InitiateMultipartUploadRequest(bucketName, objectKey); InitiateMultipartUploadResult initResult = s3Client.initiateMultipartUpload(initRequest); String uploadId = initResult.getUploadId(); ``` 其中,`bucketName`是存储桶名称,`objectKey`是上传到S3的对象名称。 3. 上传分片 将文件分割成多个块,并将每个块上传到S3。可以使用以下代码上传分片: ``` UploadPartRequest uploadRequest = new UploadPartRequest() .withBucketName(bucketName) .withKey(objectKey) .withUploadId(uploadId) .withPartNumber(partNumber) .withPartSize(partSize) .withInputStream(inputStream); UploadPartResult uploadResult = s3Client.uploadPart(uploadRequest); ``` 其中,`partNumber`是分片的编号,`partSize`是分片的大小,`inputStream`是分片数据的输入流。 上传分片后,需要将每个分片的ETag(Entity Tag)存储在列表中以备后用。可以使用以下代码存储ETag: ``` partETags.add(uploadResult.getPartETag()); ``` 4. 完成分片上传 当所有分片上传完成后,需要使用以下代码完成分片上传: ``` CompleteMultipartUploadRequest compRequest = new CompleteMultipartUploadRequest(bucketName, objectKey, uploadId, partETags); s3Client.completeMultipartUpload(compRequest); ``` 其中,`partETags`是包含每个分片ETag的列表。 5. 断点续传上传过程中,如果上传中断,可以使用以下代码恢复上传: ``` List<PartETag> partETags = new ArrayList<>(); ListPartsRequest listPartsRequest = new ListPartsRequest() .withBucketName(bucketName) .withKey(objectKey) .withUploadId(uploadId); PartListing partListing = s3Client.listParts(listPartsRequest); for (PartSummary partSummary : partListing.getParts()) { partETags.add(new PartETag(partSummary.getPartNumber(), partSummary.getETag())); } UploadPartRequest uploadRequest = new UploadPartRequest() .withBucketName(bucketName) .withKey(objectKey) .withUploadId(uploadId) .withPartNumber(partNumber) .withPartSize(partSize) .withInputStream(inputStream) .withPartETag(partETags.get(partNumber - 1)); UploadPartResult uploadResult = s3Client.uploadPart(uploadRequest); partETags.set(partNumber - 1, uploadResult.getPartETag()); ``` 其中,`partETags`是包含每个分片ETag的列表。 在恢复上传后,需要继续上传剩余的分片,并使用相同的方式完成分片上传

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值