//
|
// Source code recreated from a .class file by IntelliJ IDEA
|
// (powered by FernFlower decompiler)
|
//
|
|
package org.jeecg.modules.doc.component;
|
|
import java.io.File;
|
import java.io.IOException;
|
import java.io.RandomAccessFile;
|
import java.nio.ByteBuffer;
|
import java.nio.channels.FileChannel;
|
import java.util.ArrayList;
|
import java.util.Iterator;
|
import java.util.List;
|
import java.util.UUID;
|
import java.util.concurrent.TimeUnit;
|
import javax.annotation.Resource;
|
import javax.servlet.http.HttpServletRequest;
|
import org.apache.commons.fileupload.servlet.ServletFileUpload;
|
import org.apache.commons.io.FileUtils;
|
import org.apache.commons.io.IOUtils;
|
import org.jeecg.common.util.RedisUtil;
|
import org.jeecg.modules.doc.vo.UploadFile;
|
import org.jeecg.modules.doc.vo.UploadFileResult;
|
import org.slf4j.Logger;
|
import org.slf4j.LoggerFactory;
|
import org.springframework.stereotype.Component;
|
import org.springframework.web.multipart.MultipartFile;
|
import org.springframework.web.multipart.support.StandardMultipartHttpServletRequest;
|
|
@Component
|
public abstract class Uploader {
|
private static final Logger log = LoggerFactory.getLogger(Uploader.class);
|
@Resource
|
RedisLock redisLock;
|
@Resource
|
RedisUtil redisUtil;
|
|
public Uploader() {
|
}
|
|
public List<UploadFileResult> upload(HttpServletRequest httpServletRequest) {
|
UploadFile uploadFile = new UploadFile();
|
uploadFile.setChunkNumber(1);
|
uploadFile.setChunkSize(0L);
|
uploadFile.setTotalChunks(1);
|
uploadFile.setIdentifier(UUID.randomUUID().toString());
|
List<UploadFileResult> uploadFileResultList = this.upload(httpServletRequest, uploadFile);
|
return uploadFileResultList;
|
}
|
|
public List<UploadFileResult> upload(HttpServletRequest httpServletRequest, UploadFile uploadFile) {
|
List<UploadFileResult> uploadFileResultList = new ArrayList();
|
StandardMultipartHttpServletRequest request = (StandardMultipartHttpServletRequest)httpServletRequest;
|
boolean isMultipart = ServletFileUpload.isMultipartContent(request);
|
if (!isMultipart) {
|
throw new UploadException("未包含文件上传域");
|
} else {
|
try {
|
Iterator<String> iter = request.getFileNames();
|
|
while(iter.hasNext()) {
|
List<MultipartFile> multipartFileList = request.getFiles((String)iter.next());
|
Iterator var8 = multipartFileList.iterator();
|
|
while(var8.hasNext()) {
|
MultipartFile multipartFile = (MultipartFile)var8.next();
|
QiwenMultipartFile qiwenMultipartFile = new QiwenMultipartFile(multipartFile);
|
UploadFileResult uploadFileResult = this.doUploadFlow(qiwenMultipartFile, uploadFile);
|
uploadFileResultList.add(uploadFileResult);
|
}
|
}
|
|
return uploadFileResultList;
|
} catch (Exception var12) {
|
throw new UploadException(var12);
|
}
|
}
|
}
|
|
protected UploadFileResult doUploadFlow(QiwenMultipartFile qiwenMultipartFile, UploadFile uploadFile) {
|
try {
|
this.rectifier(qiwenMultipartFile, uploadFile);
|
UploadFileResult uploadFileResult = this.organizationalResults(qiwenMultipartFile, uploadFile);
|
return uploadFileResult;
|
} catch (Exception var5) {
|
throw new UploadException(var5);
|
}
|
}
|
|
public abstract void cancelUpload(UploadFile uploadFile);
|
|
protected abstract void doUploadFileChunk(QiwenMultipartFile qiwenMultipartFile, UploadFile uploadFile) throws IOException;
|
|
protected abstract UploadFileResult organizationalResults(QiwenMultipartFile qiwenMultipartFile, UploadFile uploadFile);
|
|
private void rectifier(QiwenMultipartFile qiwenMultipartFile, UploadFile uploadFile) {
|
String key = "QiwenUploader:Identifier:" + uploadFile.getIdentifier() + ":lock";
|
String current_upload_chunk_number = "QiwenUploader:Identifier:" + uploadFile.getIdentifier() + ":current_upload_chunk_number";
|
this.redisLock.lock(key);
|
|
try {
|
if (this.redisUtil.get(current_upload_chunk_number) == null) {
|
this.redisUtil.set(current_upload_chunk_number, 1, 3600000L);
|
}
|
|
int currentUploadChunkNumber = Integer.parseInt((String)this.redisUtil.get(current_upload_chunk_number));
|
if (uploadFile.getChunkNumber() != currentUploadChunkNumber) {
|
this.redisLock.unlock(key);
|
Thread.sleep(100L);
|
|
while(this.redisLock.tryLock(key, 300L, TimeUnit.SECONDS)) {
|
currentUploadChunkNumber = Integer.parseInt((String)this.redisUtil.get(current_upload_chunk_number));
|
if (uploadFile.getChunkNumber() <= currentUploadChunkNumber) {
|
break;
|
}
|
|
if (Math.abs(currentUploadChunkNumber - uploadFile.getChunkNumber()) > 2) {
|
log.error("传入的切片数据异常,当前应上传切片为第{}块,传入的为第{}块。", currentUploadChunkNumber, uploadFile.getChunkNumber());
|
throw new UploadException("传入的切片数据异常");
|
}
|
|
this.redisLock.unlock(key);
|
}
|
}
|
|
log.info("文件名{},正在上传第{}块, 共{}块>>>>>>>>>>", new Object[]{qiwenMultipartFile.getMultipartFile().getOriginalFilename(), uploadFile.getChunkNumber(), uploadFile.getTotalChunks()});
|
if (uploadFile.getChunkNumber() == currentUploadChunkNumber) {
|
this.doUploadFileChunk(qiwenMultipartFile, uploadFile);
|
log.info("文件名{},第{}块上传成功", qiwenMultipartFile.getMultipartFile().getOriginalFilename(), uploadFile.getChunkNumber());
|
this.redisUtil.getIncr("QiwenUploader:Identifier:" + uploadFile.getIdentifier() + ":current_upload_chunk_number");
|
}
|
} catch (Exception var9) {
|
log.error("第{}块上传失败,自动重试", uploadFile.getChunkNumber());
|
this.redisUtil.set("QiwenUploader:Identifier:" + uploadFile.getIdentifier() + ":current_upload_chunk_number", uploadFile.getChunkNumber(), 3600000L);
|
throw new UploadException("更新远程文件出错", var9);
|
} finally {
|
this.redisLock.unlock(key);
|
}
|
|
}
|
|
public synchronized boolean checkUploadStatus(UploadFile param, File confFile) throws IOException {
|
RandomAccessFile confAccessFile = new RandomAccessFile(confFile, "rw");
|
|
try {
|
confAccessFile.setLength((long)param.getTotalChunks());
|
confAccessFile.seek((long)(param.getChunkNumber() - 1));
|
confAccessFile.write(127);
|
} finally {
|
IOUtils.closeQuietly(confAccessFile);
|
}
|
|
byte[] completeStatusList = FileUtils.readFileToByteArray(confFile);
|
|
for(int i = 0; i < completeStatusList.length; ++i) {
|
if (completeStatusList[i] != 127) {
|
return false;
|
}
|
}
|
if (param.getChunkNumber() < param.getTotalChunks()) {
|
log.info("当前块号:{},总块号:{},文件id:{}", param.getChunkNumber(), param.getTotalChunks(),param.getIdentifier());
|
return false;
|
}
|
|
confFile.delete();
|
return true;
|
}
|
|
public void writeByteDataToFile(byte[] fileData, File file, UploadFile uploadFile) {
|
RandomAccessFile raf = null;
|
|
try {
|
raf = new RandomAccessFile(file, "rw");
|
FileChannel fileChannel = raf.getChannel();
|
long position = (long)(uploadFile.getChunkNumber() - 1) * uploadFile.getChunkSize();
|
fileChannel.position(position);
|
fileChannel.write(ByteBuffer.wrap(fileData));
|
fileChannel.force(true);
|
fileChannel.close();
|
raf.close();
|
} catch (IOException var8) {
|
throw new UploadException(var8);
|
}
|
}
|
}
|