为了处理公司上传大文件的需求,学习如何使用阿里对象存储oss进行上传文件、断点续传等功能,基于阿里oss的javaSdk做了简单的封装。
常见操作方法介绍
常见的操作方法有前端将文件上传到后台,通过后台sdk直接将文件上传到对象存储,也可以直接通过前端web直传到阿里oss。
认证生成OSS对象用于上传文件
private static String key = "*";
private static String secret = "*";
private static String endpoint = "http://oss-cn-beijing.aliyuncs.com";
private static String bucketName = "bucket-bm";
private static String httpsUrl = "http://bucket-bm.oss-cn-beijing.aliyuncs.com/";
/**
* 分片大小
*/
private static long partSize = 20 * 1024 * 1024;
static OSSClient ossClient = null;
static {
ossClient = new OSSClient(endpoint, key, secret);
}
分片上传和断点续传
/**
* 断点上传文件
*
* @param fileName 文件名称
* @param file 文件
*/
public static String uploadCheckPoint(String fileName, MultipartFile file, String recordPath,HttpSession session)
throws Throwable {
// ObjectMetadata data = new ObjectMetadata();
// // 设置上传类型
// data.setContentType("video/mpeg4");
File f = null;
try {
f = File.createTempFile("tmp", null);
file.transferTo(f);
f.deleteOnExit();
} catch (Exception e) {
e.printStackTrace();
}
UploadFileRequest uploadFileRequest = new UploadFileRequest(bucketName, fileName);
//指定本地上传的文件
uploadFileRequest.setUploadFile(f.getAbsolutePath());
// 设置并发数默认为1
uploadFileRequest.setTaskNum(30);
// 设置分片上传大小
uploadFileRequest.setPartSize(partSize);
// 开启断点续传
uploadFileRequest.setEnableCheckpoint(true);
// 设置记录断点续传记录文件记录位置 如果不配置默认为上传文件的文件夹中
uploadFileRequest.setCheckpointFile(recordPath);
//
// uploadFileRequest.setObjectMetadata(data);
// 上传成功之后的回调
// uploadFileRequest.setCallback(new Callback());
uploadFileRequest.setProgressListener(new PutObjectProgressListener(session));
SetBucketLoggingRequest request = new SetBucketLoggingRequest(bucketName);
request.setTargetBucket(null);
request.setTargetPrefix(null);
ossClient.setBucketLogging(request);
UploadFileResult uploadFileResult = ossClient.uploadFile(uploadFileRequest);
//关闭ossClient
ossClient.shutdown();
return httpsUrl + fileName;
}
监听上传进度
/**
* @author : tangping
* @description :
* @Date : 2018/8/17/017 10:48
*/
public class PutObjectProgressListener implements ProgressListener {
private long bytesWritten = 0;
private long totalBytes = -1;
private boolean succeed = false;
private HttpSession session;
public PutObjectProgressListener(HttpSession session) {
this.session = session;
}
@Override
public void progressChanged(ProgressEvent progressEvent) {
long bytes = progressEvent.getBytes();
ProgressEventType eventType = progressEvent.getEventType();
switch (eventType) {
case TRANSFER_STARTED_EVENT:
System.out.println("Start to upload......");
break;
case REQUEST_CONTENT_LENGTH_EVENT:
this.totalBytes = bytes;
System.out.println(this.totalBytes + " bytes in total will be uploaded to OSS");
break;
case REQUEST_BYTE_TRANSFER_EVENT:
this.bytesWritten += bytes;
if (this.totalBytes != -1) {
int percent = (int) (this.bytesWritten * 100.0 / this.totalBytes);
this.session.setAttribute("progress",percent);
System.out.println(
bytes + " bytes have been written at this time, upload progress: " + percent + "%("
+ this.bytesWritten + "/" + this.totalBytes + ")");
} else {
System.out.println(
bytes + " bytes have been written at this time, upload ratio: unknown" + "("
+ this.bytesWritten + "/...)");
}
break;
case TRANSFER_COMPLETED_EVENT:
this.succeed = true;
System.out.println(
"Succeed to upload, " + this.bytesWritten + " bytes have been transferred in total");
break;
case TRANSFER_FAILED_EVENT:
System.out
.println("Failed to upload, " + this.bytesWritten + " bytes have been transferred");
break;
default:
break;
}
}
public boolean isSucceed() {
return succeed;
}
}
web直传方式封装
web直传方式引入js-sdk
const applyTokenDo = function (func, refreshSts) {
refresh = true;
if (refresh) {
$.ajax({
url:'../progress/getToken',
data:{},
async:false,
success:function (data) {
client = new OSS({
region:data.region,
accessKeyId: data.accessKeyId,
accessKeySecret: data.accessKeySecret,
bucket:data.bucket
});
}
});
console.log(OSS.version);
return func(client);
}
return func();
}
分片上传文件
const uploadFile = function uploadFile(client) {
if (!uploadFileClient || Object.keys(uploadFileClient).length === 0) {
uploadFileClient = client;
}
document.getElementById("start_time").innerHTML ="开始时间:" + new Date().toLocaleString();
var interval = setInterval(function () {
document.getElementById("end_time").innerHTML ="结束时间:"+ new Date().toLocaleString();
},1000);
const file = document.getElementById('file').files[0];
const key = document.getElementById('object-key-file').value.trim() || 'object';
console.log(`${file.name} => ${key}`);
const options = {
progress,
partSize: 20*1024 * 1024,
parallel: 30,
meta: {
year: 2017,
people: 'test',
},
};
if (currentCheckpoint) {
options.checkpoint = currentCheckpoint;
}
return uploadFileClient.multipartUpload(key, file, options).then((res) => {
console.log('upload success: %j', res);
wx.miniProgram.postMessage({ data:{success:true,url:res.res.requestUrls[0] }})
currentCheckpoint = null;
uploadFileClient = null;
clearInterval(interval);
}).catch((err) => {
wx.miniProgram.postMessage({ data:{success:false }})
clearInterval(interval);
if (uploadFileClient && uploadFileClient.isCancel()) {
console.log('stop-upload!');
} else {
console.error(err);
}
});
};
进度条展示
const progress = async function progress(p, checkpoint) {
currentCheckpoint = checkpoint;
const bar = document.getElementById('progress-bar');
bar.style.width = `${Math.floor(p * 100)}%`;
bar.innerHTML = `${Math.floor(p * 100)}%`;
}
web直传的方式,体验性能等比较好。