package app.pool.storage;
import app.pool.utils.*;
import org.apache.commons.io.FileUtils;
import org.apache.commons.io.IOUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.web.multipart.MultipartFile;
import java.io.*;
import java.util.*;
import java.util.zip.ZipEntry;
import java.util.zip.ZipFile;
public class StorageMethods {
private static Storage storage = new Storage();
public static void setBaseDir(File dir) {
storage.setBaseDir(dir);
}
public static boolean existEntry(EntryInfo entry) {
return storage.existEntry(entry);
}
public static void storeFile(FileData file) throws IOException {
storage.storeFile(file);
}
public static String[] listFileNames() {
return storage.listFileNames();
}
public static File appFile(String name) {
return storage.appFile(name);
}
static class Storage {
private static Logger logger = LoggerFactory.getLogger(Storage.class);
private File baseDir;
private Set<CacheEntryInfo> cacheEntryInfos = Collections.synchronizedSet(new HashSet<CacheEntryInfo>());
public void setBaseDir(File baseDir) {
this.baseDir = baseDir;
this.tmpDir().mkdir();
this.cacheDir().mkdir();
this.appDir().mkdir();
for (File file : this.cacheDir().listFiles()) {
if (CacheEntryInfo.isCachefile(file.getName())) {
CacheEntryInfo entryInfo = new CacheEntryInfo();
String[] items = file.getName().split("_");
int length = Integer.parseInt(items[0]);
if (length == file.length()) {
entryInfo.setMd5(items[1]);
entryInfo.setLength(length);
this.cacheEntryInfos.add(entryInfo);
}
}
}
}
private File appDir() {
return new File(this.baseDir, "app");
}
private File cacheDir() {
return new File(this.baseDir, "cache");
}
private File tmpDir() {
return new File(this.baseDir, "tmp");
}
public boolean existEntry(EntryInfo entryInfo) {
return cacheEntryInfos.contains(entryInfo);
}
public void storeFile(FileData file) throws IOException {
byte[] uploadfilecontent = IOUtils.toByteArray(file.getFile().getInputStream());
List<EntryInfo> existedEntryInfos = JSONUtils.toList(file.getEntryInfos(), EntryInfo.class);
File tmpTargetFile = createTargetFile(uploadfilecontent, existedEntryInfos);
String targetMd5 = MD5Utils.getMD5(FileUtils.readFileToByteArray(tmpTargetFile));
logger.info("上传的文件MD5=" + file.getMd5() + ",恢复后文件MD5=" + targetMd5);
if (!file.getMd5().equals(targetMd5)) {
throw new RuntimeException("文件恢复失败,MD5值不相等.上传的文件MD5=" + file.getMd5() + ",恢复后文件MD5=" + targetMd5);
}
cacheBigEntry(tmpTargetFile, existedEntryInfos);
File dest = new File(this.appDir(), file.getFile().getOriginalFilename());
if (dest.exists()) {
if (!dest.delete()) {
throw new RuntimeException("删除旧文件失败");
}
}
if (!tmpTargetFile.renameTo(dest)) {
logger.error("文件重命名失败" + tmpTargetFile.getAbsolutePath() + "->" + dest.getAbsolutePath());
throw new RuntimeException("文件重命名失败");
}
logger.info("上传的文件MD5=" + file.getMd5() + ",存储到" + dest + ",MD5=" + targetMd5);
}
private void cacheBigEntry(File file, List<EntryInfo> existedEntryInfos) {
try (ZipFile zipSrc = new ZipFile(file);) {
Enumeration srcEntries = zipSrc.entries();
while (srcEntries.hasMoreElements()) {
ZipEntry entry = (ZipEntry) srcEntries.nextElement();
if (EntryInfo.findByName(existedEntryInfos, entry.getName()) == null) {
byte[] content = IOUtils.toByteArray(zipSrc.getInputStream(entry));
if (content.length > 1024 * 100) {
createCache(content);
}
}
}
} catch (IOException e) {
throw new RuntimeException(e);
}
}
private File createTargetFile(byte[] uploadfilecontent, List<EntryInfo> entryInfos) {
try {
List<FileContentUtils.FilePart> filePartList = new ArrayList<>();
for (EntryInfo entryInfo : entryInfos) {
File md5File = getCacheFile(entryInfo);
if (!md5File.exists()) {
logger.error("找不到对应的文件" + md5File.getAbsolutePath());
throw new FileNotFoundException(md5File.getName());
}
FileContentUtils.FilePart filePart = new FileContentUtils.FilePart();
filePart.setData(FileUtils.readFileToByteArray(md5File));
filePart.setStart(entryInfo.getStart());
filePart.setLength(entryInfo.getLength());
filePartList.add(filePart);
}
byte[] newfilecontent = FileContentUtils.restoreDeletedFileContent(uploadfilecontent, new FileContentUtils.FileParts(filePartList));
File targetFile = new File(this.tmpDir(), UUID.randomUUID().toString());
FileUtils.writeByteArrayToFile(targetFile, newfilecontent);
return targetFile;
} catch (Exception e) {
throw new RuntimeException(e);
}
}
private File getTempCacheFile(CacheEntryInfo cacheEntryInfo) {
return new File(this.cacheDir(), cacheEntryInfo.tmpCacheFilename());
}
private File getCacheFile(CacheEntryInfo cacheEntryInfo) {
return new File(this.cacheDir(), cacheEntryInfo.cacheFilename());
}
private void createCache(byte[] content) throws IOException {
String md5 = MD5Utils.getMD5(content);
CacheEntryInfo cacheEntryInfo = new CacheEntryInfo();
cacheEntryInfo.setMd5(md5);
cacheEntryInfo.setLength(content.length);
File tmpCacheFile = getTempCacheFile(cacheEntryInfo);
FileUtils.writeByteArrayToFile(tmpCacheFile, content);
File cacheFile = getCacheFile(cacheEntryInfo);
if (tmpCacheFile.renameTo(cacheFile)) {
logger.info("建立cache文件" + tmpCacheFile);
CacheEntryInfo entryInfo = new CacheEntryInfo();
entryInfo.setMd5(md5);
entryInfo.setLength(content.length);
this.cacheEntryInfos.add(entryInfo);
} else {
tmpCacheFile.delete();
}
}
public String[] listFileNames() {
return this.appDir().list();
}
public File appFile(String name) {
return new File(this.appDir(), name);
}
}
}
没有合适的资源?快使用搜索试试~ 我知道了~
温馨提示
文件传输服务器,采用增量传输方式,解决远程机房上传文件网速慢问题;上传文件到远程机房速度一般比较慢,例如100KB/s。使用putty工具上传war包(40M)到远程服务器需要几分钟。为了提高效率,减少上传文件时间,我们可以尽量减少要传输的文件内容。war包是zip压缩文件,同一个应用,不同版本的war包,会包含很多相同的压缩文件。上传文件时,如果不需要上传服务器端已经存在的压缩文件,那就可以大大减少要传输的文件内容
资源推荐
资源详情
资源评论
收起资源包目录
app-pool-server-master.zip (22个子文件)
app-pool-server-master
pom.xml 3KB
src
test
java
app
pool
server
utils
FileUtilsTest.java 1KB
FilePartsTest.java 3KB
main
resources
logback.xml 1KB
static
js
jsbase.js 54KB
jquery-2.1.4.js 242KB
index.html 904B
application.yml 130B
java
app
pool
utils
Utils.java 2KB
JSONUtils.java 3KB
FileContentUtils.java 4KB
MD5Utils.java 2KB
storage
EntryInfo.java 508B
FileData.java 259B
StorageMethods.java 7KB
CacheEntryInfo.java 1KB
server
FilesController.java 2KB
AppConfig.java 3KB
App.java 804B
img
result.jpg 12KB
design.jpg 44KB
.gitignore 19B
共 22 条
- 1
资源评论
Java程序员-张凯
- 粉丝: 1w+
- 资源: 6650
上传资源 快速赚钱
- 我的内容管理 展开
- 我的资源 快来上传第一个资源
- 我的收益 登录查看自己的收益
- 我的积分 登录查看自己的积分
- 我的C币 登录后查看C币余额
- 我的收藏
- 我的下载
- 下载帮助
安全验证
文档复制为VIP权益,开通VIP直接复制
信息提交成功