1 簡介
你知道在JAVA應用程序中優化文件服務器的磁盤空間是非常重要的非功能性要求之一嗎?如果管理得當,可以節省文件存儲服務器上60%至70%的成本。因此,對于由Java Spring Boot API生成的數據文件進行壓縮顯得尤為非常重要。
Java提供了多個庫來幫助我們壓縮內容,同時也提供了本地文件操作來壓縮數據文件。在本文中,我們使用本地方法來實現壓縮。
2 使用Java實現文件壓縮和刪除功能
我們創建一個實用程序,它可以打包在Java代碼的任何位置,可以在你的微服務中的任何地方使用。你還可以將其放在共享庫中,作為組織中所有微服務的實用程序公開。我們的實用程序將具有兩個功能:
-
壓縮給定的源文件
-
在壓縮成功后刪除原始文件
先決條件:
JDK ≥ 1.8 + Maven > 3.X + Spring Boot 2.X + Lombok + Common-IO
我們創建一個對象,該對象將具有基本參數用于壓縮文件。在下面的代碼中,我們創建了一個名為FileZipper類,它通過Lombok實現Builder和Getter功能。
@Builder(setterPrefix = "set")
@Getter
public class FileZipper {
@NonNull
private String sourceFilePath;
@NonNull
private String sourceFileName;
@NonNull
private String sourceFileExtension;
@NonNull
private String zippedFilePath;
@NonNull
private String zippedFileName;
private boolean deleteSourceAfterZipped;
}
現在,我們創建一個名為FileZippingService的Java服務類,它將根據用戶輸入壓縮源文件。此服務類還具有文件刪除功能,可以在文件壓縮成功后刪除源文件。
public class FileZippingService {
private static final String DOT = ".";
private static final String ZIP = ".zip";
private FileZippingService() {
}
static Logger logger = LoggerFactory.getLogger(FileZippingService.class);
/**
* Method to Zip a file
*
* @param fileZipper
*/
public static void zipExportFile(FileZipper fileZipper) {
String sourceFileWithPath = fileZipper.getSourceFilePath().concat(fileZipper.getSourceFileName()).concat(DOT)
.concat(fileZipper.getSourceFileExtension());
String zippedFileWithPath = fileZipper.getZippedFilePath().concat(fileZipper.getZippedFileName()).concat(ZIP);
logger.info("Source File : {} will be zipped into {}", sourceFileWithPath, zippedFileWithPath);
try {
File fileToZip = new File(sourceFileWithPath);
if (fileToZip.exists()) {
FileOutputStream fos = new FileOutputStream(zippedFileWithPath);
ZipOutputStream zipOut = new ZipOutputStream(fos);
FileInputStream fis = new FileInputStream(fileToZip);
ZipEntry zipEntry = new ZipEntry(fileToZip.getName());
zipOut.putNextEntry(zipEntry);
byte[] bytes = new byte[1024];
int length;
while ((length = fis.read(bytes)) >= 0) {
zipOut.write(bytes, 0, length);
}
zipOut.close();
fis.close();
fos.close();
logger.info("{} zipped successfully at {}", sourceFileWithPath, zippedFileWithPath);
if (fileZipper.isDeleteSourceAfterZipped())
deleteFile(sourceFileWithPath);
}
} catch (IOException e) {
logger.error("Error while Zipping the file", e);
deleteFile(zippedFileWithPath);
}
}
/**
* Method to delete a file at given path
*
* @param fileToDelete
*/
private static void deleteFile(String fileToDelete) {
File filetoDelete = new File(fileToDelete);
if (filetoDelete.exists()) {
if (FileUtils.deleteQuietly(filetoDelete)) {
logger.info("{} deleted successfully.", fileToDelete);
} else {
logger.info("{} deletion unsuccessfull.", fileToDelete);
}
} else {
logger.info("{} was not found for deletion.", fileToDelete);
}
}
}
接下來我們通過運行Spring Boot應用程序來測試代碼。在下面的Java文件中,你可以看到提供的源文件路徑、名稱和擴展名,從中需要讀取文件;還提供了壓縮文件的文件名以及壓縮后需要存儲的路徑。此外,這里還設置了一個標志,用于決定是否在壓縮后刪除源文件。
@SpringBootApplication
public class FileZippingApplication {
public static void mAIn(String[] args) {
SpringApplication.run(FileZippingApplication.class, args);
FileZipper fileZipper = FileZipper.builder()
.setSourceFilePath("C:/Data/")
.setSourceFileName("UserData")
.setSourceFileExtension("xlsx")
.setZippedFileName("ZippedUserData")
.setZippedFilePath("C:/Data/")
.setDeleteSourceAfterZipped(true)
.build();
FileZippingService.zipExportFile(fileZipper);
}
}
3 結果
上述代碼的輸出結果令人非常驚訝。在我們的一個業務應用程序中,有大量的CSV文件,大小一般在600MB到1 GB之間,占用消耗大量的磁盤空間,因為我們在一個小時內收到了1000多個請求。
但是,在使用上述代碼壓縮后,磁盤空間減少了85%,我們甚至可以通過電子郵件向客戶發送文件。