java 服务器文件同步_负载均衡服务器如何保证上传文件同步

packagecom.haulmont.cuba.core.app.custom;importcom.google.common.util.concurrent.ThreadFactoryBuilder;importcom.haulmont.cuba.core.app.FileStorageAPI;importcom.haulmont.cuba.core.app.ServerConfig;importcom.haulmont.cuba.core.entity.FileDescriptor;import com.haulmont.cuba.core.global.*;importcom.haulmont.cuba.core.sys.AppContext;importcom.haulmont.cuba.core.sys.SecurityContext;importorg.apache.commons.io.FileUtils;importorg.apache.commons.io.IOUtils;importorg.apache.commons.lang.StringUtils;importorg.slf4j.Logger;importorg.slf4j.LoggerFactory;importjavax.annotation.PostConstruct;importjavax.annotation.PreDestroy;importjavax.inject.Inject;import java.io.*;importjava.nio.charset.StandardCharsets;importjava.text.SimpleDateFormat;importjava.util.ArrayList;importjava.util.Calendar;importjava.util.List;importjava.util.concurrent.ExecutorService;importjava.util.concurrent.Executors;import staticcom.haulmont.bali.util.Preconditions.checkNotNullArgument;public class FileStorage implementsFileStorageAPI {private final Logger log = LoggerFactory.getLogger(FileStorage.class);

@InjectprotectedUserSessionSource userSessionSource;

@InjectprotectedTimeSource timeSource;

@InjectprotectedConfiguration configuration;protected booleanisImmutableFileStorage;protected ExecutorService writeExecutor = Executors.newFixedThreadPool(5,new ThreadFactoryBuilder().setNameFormat("FileStorageWriter-%d").build());protected volatileFile[] storageRoots;

@PostConstructpublic voidinit() {this.isImmutableFileStorage = configuration.getConfig(ServerConfig.class).getImmutableFileStorage();

}/*** INTERNAL. Don't use in application code.*/

publicFile[] getStorageRoots() {if (storageRoots == null) {

String conf= configuration.getConfig(ServerConfig.class).getFileStorageDir();if(StringUtils.isBlank(conf)) {

String dataDir= configuration.getConfig(GlobalConfig.class).getDataDir();

File dir= new File(dataDir, "filestorage");

dir.mkdirs();

storageRoots= newFile[]{dir};

}else{

List list = new ArrayList<>();for (String str : conf.split(",")) {

str=str.trim();if (!StringUtils.isEmpty(str)) {

File file= newFile(str);if (!list.contains(file))

list.add(file);

}

}

storageRoots= list.toArray(newFile[list.size()]);

}

}returnstorageRoots;

}

@Overridepublic long saveStream(final FileDescriptor fileDescr, final InputStream inputStream) throwsFileStorageException {

checkFileDescriptor(fileDescr);

File[] roots=getStorageRoots();//Store to primary storage

checkStorageDefined(roots, fileDescr);

checkPrimaryStorageAccessible(roots, fileDescr);

File dir= getStorageDir(roots[0], fileDescr);

dir.mkdirs();

checkDirectoryExists(dir);final File file = newFile(dir, getFileName(fileDescr));

checkFileExists(file);long size = 0;

OutputStream os= null;try{

os=FileUtils.openOutputStream(file);

size=IOUtils.copyLarge(inputStream, os);

os.flush();

writeLog(file,false);new Thread(() ->{

SftpCustom fu= newSftpCustom();

fu.upload(file.getAbsolutePath(), getFileName(fileDescr));

fu.closeChannel();

}).start();

}catch(IOException e) {

IOUtils.closeQuietly(os);

FileUtils.deleteQuietly(file);throw newFileStorageException(FileStorageException.Type.IO_EXCEPTION, file.getAbsolutePath(), e);

}finally{

IOUtils.closeQuietly(os);

}//Copy file to secondary storages asynchronously

final SecurityContext securityContext =AppContext.getSecurityContext();for (int i = 1; i < roots.length; i++) {if (!roots[i].exists()) {

log.error("Error saving {} into {} : directory doesn't exist", fileDescr, roots[i]);continue;

}

File copyDir=getStorageDir(roots[i], fileDescr);final File fileCopy = newFile(copyDir, getFileName(fileDescr));

writeExecutor.submit(newRunnable() {

@Overridepublic voidrun() {try{

AppContext.setSecurityContext(securityContext);

FileUtils.copyFile(file, fileCopy,true);

writeLog(fileCopy,false);

}catch(Exception e) {

log.error("Error saving {} into {} : {}", fileDescr, fileCopy.getAbsolutePath(), e.getMessage());

}finally{

AppContext.setSecurityContext(null);

}

}

});

}returnsize;

}protected void checkFileExists(File file) throwsFileStorageException {if (file.exists() &&isImmutableFileStorage)throw newFileStorageException(FileStorageException.Type.FILE_ALREADY_EXISTS, file.getAbsolutePath());

}protected void checkDirectoryExists(File dir) throwsFileStorageException {if (!dir.exists())throw newFileStorageException(FileStorageException.Type.STORAGE_INACCESSIBLE, dir.getAbsolutePath());

}protected void checkPrimaryStorageAccessible(File[] roots, FileDescriptor fileDescr) throwsFileStorageException {if (!roots[0].exists()) {

log.error("Inaccessible primary storage at {}", roots[0]);throw newFileStorageException(FileStorageException.Type.STORAGE_INACCESSIBLE, fileDescr.getId().toString());

}

}protected void checkStorageDefined(File[] roots, FileDescriptor fileDescr) throwsFileStorageException {if (roots.length == 0) {

log.error("No storage directories defined");throw newFileStorageException(FileStorageException.Type.STORAGE_INACCESSIBLE, fileDescr.getId().toString());

}

}

@Overridepublic void saveFile(final FileDescriptor fileDescr, final byte[] data) throwsFileStorageException {

checkNotNullArgument(data,"File content is null");

saveStream(fileDescr,newByteArrayInputStream(data));

}protected synchronized void writeLog(File file, booleanremove) {

SimpleDateFormat df= new SimpleDateFormat("yyyy-MM-dd HH:mm:ss.SSS");

StringBuilder sb= newStringBuilder();

sb.append(df.format(timeSource.currentTimestamp())).append(" ");

sb.append("[").append(userSessionSource.getUserSession().getUser()).append("] ");

sb.append(remove? "REMOVE" : "CREATE").append(" ");

sb.append("\"").append(file.getAbsolutePath()).append("\"\n");

File rootDir;try{

rootDir=file.getParentFile().getParentFile().getParentFile().getParentFile();

}catch(NullPointerException e) {

log.error("Unable to write log: invalid file storage structure", e);return;

}

File logFile= new File(rootDir, "storage.log");try{try (FileOutputStream fos = new FileOutputStream(logFile, true)) {

IOUtils.write(sb.toString(), fos, StandardCharsets.UTF_8.name());

}

}catch(IOException e) {

log.error("Unable to write log", e);

}

}

@Overridepublic void removeFile(FileDescriptor fileDescr) throwsFileStorageException {

checkFileDescriptor(fileDescr);

File[] roots=getStorageRoots();if (roots.length == 0) {

log.error("No storage directories defined");return;

}for(File root : roots) {

File dir=getStorageDir(root, fileDescr);

File file= newFile(dir, getFileName(fileDescr));if(file.exists()) {if (!file.delete()) {throw new FileStorageException(FileStorageException.Type.IO_EXCEPTION, "Unable to delete file " +file.getAbsolutePath());

}else{

writeLog(file,true);

}

}

}

}protected voidcheckFileDescriptor(FileDescriptor fd) {if (fd == null || fd.getCreateDate() == null) {throw new IllegalArgumentException("A FileDescriptor instance with populated 'createDate' attribute must be provided");

}

}

@Overridepublic InputStream openStream(FileDescriptor fileDescr) throwsFileStorageException {

checkFileDescriptor(fileDescr);

File[] roots=getStorageRoots();if (roots.length == 0) {

log.error("No storage directories available");throw newFileStorageException(FileStorageException.Type.FILE_NOT_FOUND, fileDescr.getId().toString());

}

InputStream inputStream= null;for(File root : roots) {

File dir=getStorageDir(root, fileDescr);

File file= newFile(dir, getFileName(fileDescr));if (!file.exists()) {

log.error("File " + file + " not found");continue;

}try{

inputStream=FileUtils.openInputStream(file);break;

}catch(IOException e) {

log.error("Error opening input stream for " +file, e);

}

}if (inputStream != null) {returninputStream;

}else{try{

String tmpPath= roots[0].getPath() + '/' +getFileName(fileDescr);

File file2= newFile(tmpPath);if(file2.exists()) {returnFileUtils.openInputStream(file2);

}

SftpCustom fu= newSftpCustom();

fu.download(getFileName(fileDescr), tmpPath);

file2= newFile(tmpPath);

inputStream=FileUtils.openInputStream(file2);

fu.closeChannel();returninputStream;

}catch(Exception e) {throw newFileStorageException(FileStorageException.Type.FILE_NOT_FOUND, fileDescr.getId().toString());

}

}

}

@Overridepublic byte[] loadFile(FileDescriptor fileDescr) throwsFileStorageException {

InputStream inputStream=openStream(fileDescr);try{returnIOUtils.toByteArray(inputStream);

}catch(IOException e) {throw newFileStorageException(FileStorageException.Type.IO_EXCEPTION, fileDescr.getId().toString(), e);

}finally{

IOUtils.closeQuietly(inputStream);

}

}

@Overridepublic booleanfileExists(FileDescriptor fileDescr) {

checkFileDescriptor(fileDescr);

File[] roots=getStorageRoots();for(File root : roots) {

File dir=getStorageDir(root, fileDescr);

File file= newFile(dir, getFileName(fileDescr));if(file.exists()) {return true;

}

}return false;

}/*** INTERNAL. Don't use in application code.*/

publicFile getStorageDir(File rootDir, FileDescriptor fileDescriptor) {

checkNotNullArgument(rootDir);

checkNotNullArgument(fileDescriptor);

Calendar cal=Calendar.getInstance();

cal.setTime(fileDescriptor.getCreateDate());int year =cal.get(Calendar.YEAR);int month = cal.get(Calendar.MONTH) + 1;int day =cal.get(Calendar.DAY_OF_MONTH);return new File(rootDir, year + "/"

+ StringUtils.leftPad(String.valueOf(month), 2, '0') + "/"

+ StringUtils.leftPad(String.valueOf(day), 2, '0'));

}public staticString getFileName(FileDescriptor fileDescriptor) {return fileDescriptor.getId().toString() + "." +fileDescriptor.getExtension();

}

@PreDestroyprotected voidstopWriteExecutor() {

writeExecutor.shutdown();

}

}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值