欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

Java負載均衡服務(wù)器實現(xiàn)上傳文件同步

 更新時間:2020年09月19日 16:22:03   作者:賈樹丙  
這篇文章主要介紹了Java負載均衡服務(wù)器實現(xiàn)上傳文件同步,文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友可以參考下

負載服務(wù)器Z,應用服務(wù)器A 和B ,從A上傳的附件,如何在B上下載下來?

這個問題我的解決思路如下(后來被一個裝逼的面試官給批評了這種做法,不過我瞧不起他)

服務(wù)器A、B 上傳附件的時候,將這個附件備份到服務(wù)器Z ,當A、B下載文件的時候,首先會在自己服務(wù)器的目錄下尋找,如果找不到,就會從服務(wù)器Z 上下載一份到當前服務(wù)器。

服務(wù)器之間的文件備份通過sftp,參考:http://www.dbjr.com.cn/article/196008.htm(下文中的SftpCustom 類就是這個鏈接里的 “SFTP上傳下載文件例子” 中的類)

這里主要介紹一下重寫上傳、下載的方法時應該添加的代碼

上傳文件,異步操作

 new Thread(() -> {

  SftpCustom fu = new SftpCustom();
  fu.upload(file.getAbsolutePath(), getFileName(fileDescr));
  fu.closeChannel();
}).start();

下載文件,先從當前服務(wù)器尋找

String tmpPath = roots[0].getPath() + '/' + getFileName(fileDescr);
File file2 = new File(tmpPath);
if (file2.exists()) {
  return FileUtils.openInputStream(file2);
}

SftpCustom fu = new SftpCustom();
fu.download(getFileName(fileDescr), tmpPath);
file2 = new File(tmpPath);
inputStream = FileUtils.openInputStream(file2);
fu.closeChannel();
return inputStream;

cuba 框架中重寫上傳文件類FileStorage.java 的代碼如下:

package com.haulmont.cuba.core.app.custom;

import com.google.common.util.concurrent.ThreadFactoryBuilder;
import com.haulmont.cuba.core.app.FileStorageAPI;
import com.haulmont.cuba.core.app.ServerConfig;
import com.haulmont.cuba.core.entity.FileDescriptor;
import com.haulmont.cuba.core.global.*;
import com.haulmont.cuba.core.sys.AppContext;
import com.haulmont.cuba.core.sys.SecurityContext;
import org.apache.commons.io.FileUtils;
import org.apache.commons.io.IOUtils;
import org.apache.commons.lang.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import javax.annotation.PostConstruct;
import javax.annotation.PreDestroy;
import javax.inject.Inject;
import java.io.*;
import java.nio.charset.StandardCharsets;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.List;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

import static com.haulmont.bali.util.Preconditions.checkNotNullArgument;

public class FileStorage implements FileStorageAPI {

  private final Logger log = LoggerFactory.getLogger(FileStorage.class);

  @Inject
  protected UserSessionSource userSessionSource;

  @Inject
  protected TimeSource timeSource;

  @Inject
  protected Configuration configuration;

  protected boolean isImmutableFileStorage;

  protected ExecutorService writeExecutor = Executors.newFixedThreadPool(5,
      new ThreadFactoryBuilder().setNameFormat("FileStorageWriter-%d").build());

  protected volatile File[] storageRoots;

  @PostConstruct
  public void init() {
    this.isImmutableFileStorage = configuration.getConfig(ServerConfig.class).getImmutableFileStorage();
  }

  /**
   * INTERNAL. Don't use in application code.
   */
  public File[] 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 = new File[]{dir};
      } else {
        List<File> list = new ArrayList<>();
        for (String str : conf.split(",")) {
          str = str.trim();
          if (!StringUtils.isEmpty(str)) {
            File file = new File(str);
            if (!list.contains(file))
              list.add(file);
          }
        }
        storageRoots = list.toArray(new File[list.size()]);
      }
    }
    return storageRoots;
  }

  @Override
  public long saveStream(final FileDescriptor fileDescr, final InputStream inputStream) throws FileStorageException {
    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 = new File(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 = new SftpCustom();
        fu.upload(file.getAbsolutePath(), getFileName(fileDescr));
        fu.closeChannel();
      }).start();

    } catch (IOException e) {
      IOUtils.closeQuietly(os);
      FileUtils.deleteQuietly(file);

      throw new FileStorageException(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 = new File(copyDir, getFileName(fileDescr));

      writeExecutor.submit(new Runnable() {
        @Override
        public void run() {
          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);
          }
        }
      });
    }

    return size;
  }

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

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

  protected void checkPrimaryStorageAccessible(File[] roots, FileDescriptor fileDescr) throws FileStorageException {
    if (!roots[0].exists()) {
      log.error("Inaccessible primary storage at {}", roots[0]);
      throw new FileStorageException(FileStorageException.Type.STORAGE_INACCESSIBLE, fileDescr.getId().toString());
    }
  }

  protected void checkStorageDefined(File[] roots, FileDescriptor fileDescr) throws FileStorageException {
    if (roots.length == 0) {
      log.error("No storage directories defined");
      throw new FileStorageException(FileStorageException.Type.STORAGE_INACCESSIBLE, fileDescr.getId().toString());
    }
  }

  @Override
  public void saveFile(final FileDescriptor fileDescr, final byte[] data) throws FileStorageException {
    checkNotNullArgument(data, "File content is null");
    saveStream(fileDescr, new ByteArrayInputStream(data));
  }

  protected synchronized void writeLog(File file, boolean remove) {
    SimpleDateFormat df = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss.SSS");

    StringBuilder sb = new StringBuilder();
    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);
    }
  }

  @Override
  public void removeFile(FileDescriptor fileDescr) throws FileStorageException {
    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 = new File(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 void checkFileDescriptor(FileDescriptor fd) {
    if (fd == null || fd.getCreateDate() == null) {
      throw new IllegalArgumentException("A FileDescriptor instance with populated 'createDate' attribute must be provided");
    }
  }

  @Override
  public InputStream openStream(FileDescriptor fileDescr) throws FileStorageException {
    checkFileDescriptor(fileDescr);

    File[] roots = getStorageRoots();
    if (roots.length == 0) {
      log.error("No storage directories available");
      throw new FileStorageException(FileStorageException.Type.FILE_NOT_FOUND, fileDescr.getId().toString());
    }

    InputStream inputStream = null;
    for (File root : roots) {
      File dir = getStorageDir(root, fileDescr);

      File file = new File(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) {
      return inputStream;
    } else {
      try {
        String tmpPath = roots[0].getPath() + '/' + getFileName(fileDescr);
        File file2 = new File(tmpPath);
        if (file2.exists()) {
          return FileUtils.openInputStream(file2);
        }

        SftpCustom fu = new SftpCustom();
        fu.download(getFileName(fileDescr), tmpPath);
        file2 = new File(tmpPath);
        inputStream = FileUtils.openInputStream(file2);
        fu.closeChannel();
        return inputStream;
      } catch (Exception e) {
        throw new FileStorageException(FileStorageException.Type.FILE_NOT_FOUND, fileDescr.getId().toString());
      }
    }
  }

  @Override
  public byte[] loadFile(FileDescriptor fileDescr) throws FileStorageException {
    InputStream inputStream = openStream(fileDescr);
    try {
      return IOUtils.toByteArray(inputStream);
    } catch (IOException e) {
      throw new FileStorageException(FileStorageException.Type.IO_EXCEPTION, fileDescr.getId().toString(), e);
    } finally {
      IOUtils.closeQuietly(inputStream);
    }
  }

  @Override
  public boolean fileExists(FileDescriptor fileDescr) {
    checkFileDescriptor(fileDescr);

    File[] roots = getStorageRoots();
    for (File root : roots) {
      File dir = getStorageDir(root, fileDescr);
      File file = new File(dir, getFileName(fileDescr));
      if (file.exists()) {
        return true;
      }
    }
    return false;
  }

  /**
   * INTERNAL. Don't use in application code.
   */
  public File 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 static String getFileName(FileDescriptor fileDescriptor) {
    return fileDescriptor.getId().toString() + "." + fileDescriptor.getExtension();
  }

  @PreDestroy
  protected void stopWriteExecutor() {
    writeExecutor.shutdown();
  }
}

以上就是本文的全部內(nèi)容,希望對大家的學習有所幫助,也希望大家多多支持腳本之家。

相關(guān)文章

  • SpringBoot+Vue實現(xiàn)EasyPOI導入導出的方法詳解

    SpringBoot+Vue實現(xiàn)EasyPOI導入導出的方法詳解

    項目開發(fā)過程中,很大的需求都有 導入導出功能。本文將利用SpringBoot+Vue實現(xiàn)EasyPOI導入導出功能,感興趣的可以了解一下
    2022-08-08
  • SpringBoot集成ip2region實現(xiàn)ip白名單的代碼示例

    SpringBoot集成ip2region實現(xiàn)ip白名單的代碼示例

    ip2region v2.0 - 是一個離線IP地址定位庫和IP定位數(shù)據(jù)管理框架,10微秒級別的查詢效率,提供了眾多主流編程語言的 xdb 數(shù)據(jù)生成和查詢客戶端實現(xiàn),本文介紹了SpringBoot集成ip2region實現(xiàn)ip白名單的代碼工程,需要的朋友可以參考下
    2024-08-08
  • MyBatis-Flex實現(xiàn)分頁查詢的示例代碼

    MyBatis-Flex實現(xiàn)分頁查詢的示例代碼

    在MyBatis-Flex中實現(xiàn)分頁查詢時,需要注意維護一個獲取數(shù)據(jù)庫總數(shù)的方法,詳細介紹了UserService、UserServiceImpl類以及Mapper.xml配置,感興趣的可以了解一下
    2024-10-10
  • Java Socket通信(一)之客戶端程序 發(fā)送和接收數(shù)據(jù)

    Java Socket通信(一)之客戶端程序 發(fā)送和接收數(shù)據(jù)

    對于Socket通信簡述,服務(wù)端往Socket的輸出流里面寫東西,客戶端就可以通過Socket的輸入流讀取對應的內(nèi)容,Socket與Socket之間是雙向連通的,所以客戶端也可以往對應的Socket輸出流里面寫東西,然后服務(wù)端對應的Socket的輸入流就可以讀出對應的內(nèi)容
    2016-03-03
  • mybatis整合springboot報BindingException:Invalid?bound?statement?(not?found)異常解決

    mybatis整合springboot報BindingException:Invalid?bound?stateme

    這篇文章主要給大家介紹了關(guān)于mybatis整合springboot報BindingException:Invalid?bound?statement?(not?found)異常的解決辦法,這個錯誤通常是由于Mapper文件中的statement?id與Java代碼中的方法名不一致導致的,需要的朋友可以參考下
    2024-01-01
  • Mybatis-Plus開發(fā)提速器generator的使用

    Mybatis-Plus開發(fā)提速器generator的使用

    本文就介紹這款基于Mybatis-Plus的代碼自助生成器,文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友們下面隨著小編來一起學習學習吧
    2023-07-07
  • springboot swagger不顯示接口的問題及解決

    springboot swagger不顯示接口的問題及解決

    這篇文章主要介紹了springboot swagger不顯示接口的問題及解決方案,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教
    2022-06-06
  • win10安裝JDK14.0.2的詳細安裝過程

    win10安裝JDK14.0.2的詳細安裝過程

    這篇文章主要介紹了win10安裝JDK14.0.2的詳細安裝過程的相關(guān)資料,本文通過圖文并茂的形式給大家介紹的非常詳細,對大家的學習或工作具有一定的參考借鑒價值,需要的朋友可以參考下
    2020-09-09
  • Java利用反射對list對象做過濾

    Java利用反射對list對象做過濾

    這篇文章主要介紹了Java利用反射對list對象做過濾,但是使用反射對效率有影響,但在一些特殊情況也有一定的參考價值,需要的小伙伴可以參考一下
    2022-03-03
  • 《阿里巴巴 Java開發(fā)手冊》讀后感小結(jié)

    《阿里巴巴 Java開發(fā)手冊》讀后感小結(jié)

    這篇文章主要介紹了《阿里巴巴 Java開發(fā)手冊》讀后感小結(jié),小編覺得挺不錯的,現(xiàn)在分享給大家,也給大家做個參考。一起跟隨小編過來看看吧
    2018-12-12

最新評論