Aws S3上傳優化

上傳大約 3.4GB 的 JSON 文件,zip算法壓縮后約為 395MB,上傳至 S3 效率優化,有一些優化方案可以提高上傳速率。下面是幾種可能的優化方式,包括選擇壓縮算法、調整上傳方式、以及其他可能的方案。

方案

1. 選擇更好的壓縮算法

壓縮算法直接影響壓縮比率和壓縮/解壓速度。對于你的數據,考慮到是 JSON 文件,可以嘗試以下幾種壓縮算法:

a. Zstandard (zstd)
  • 特點:Zstandard 是一種高效的壓縮算法,提供 更高的壓縮比率更快的壓縮/解壓速度。它是目前最受歡迎的壓縮算法之一,尤其適用于需要平衡壓縮比和速度的場景。
  • 優勢
    • 高壓縮比:相比于 gzip 或 bzip2,Zstd 可以提供更高的壓縮比。
    • 壓縮速度:Zstd 提供了非常快的壓縮速度,甚至在高壓縮比時也能保持較快速度。
    • 支持字典壓縮:Zstd 可以針對特定類型的數據(如 JSON)使用預訓練的字典,以進一步提高壓縮比。
  • 如何使用
    • 使用 zstd 工具壓縮 JSON 文件,或者使用如 java-zstd 之類的 Java 庫。
    • zstd 中,你可以通過調整壓縮級別來平衡壓縮率與速度,通常 level 19 以上會提供最優的壓縮比。
b. Brotli
  • 特點:Brotli 是 Google 開發的壓縮算法,通常壓縮比率較高,但速度稍慢于 Zstd。
  • 優勢
    • 高壓縮比:Brotli 提供非常高的壓縮比,尤其適合文本類文件(如 JSON)。
    • 支持 HTTP 壓縮:在 web 應用中,Brotli 是一種推薦的壓縮算法,適用于 HTTP 傳輸壓縮。
  • 如何使用
    • 如果你關注最大壓縮比,可以使用 Brotli,但可能會犧牲一定的速度。
    • Java 可以通過 brotli-java 庫進行壓縮。
c. Gzip
  • 特點:Gzip 是最常用的壓縮格式,雖然壓縮比和速度比 Zstd 和 Brotli 稍遜,但仍然是一個廣泛應用的標準。
  • 優勢
    • 高度兼容:幾乎所有的工具和平臺都支持 Gzip。
    • 較快的壓縮速度,適合流式處理。
  • 如何使用
    • Gzip 可以通過 Java 的 java.util.zip.GZIPOutputStream 進行壓縮,通常選擇適中級別的壓縮。
d. LZ4
  • 特點:LZ4 是一個超高速的壓縮算法,壓縮比不如 Zstd 或 Brotli 高,但它提供了極快的壓縮和解壓速度,適用于需要高吞吐量的場景。
  • 優勢
    • 非常快的壓縮/解壓速度。
    • 適用于實時數據傳輸或非常頻繁的壓縮操作。

如何使用

- 適用于流式處理,如果你對上傳時間有非常高的要求,可以考慮使用 LZ4。

2. 上傳優化方案

壓縮文件的上傳到 S3,除了壓縮算法外,上傳方式也會影響性能。以下是一些優化上傳速率的建議:

a. 分塊上傳(Multipart Upload)

對于大文件(如你 395MB 的壓縮包),使用 S3 的 Multipart Upload 可以顯著提高上傳速度。

  • 分塊上傳:將大文件分割成多個較小的塊(如 5MB 或更大的塊),每個塊并行上傳,然后在服務器端合并。這種方式可以顯著提高上傳速率,尤其是網絡帶寬受限時。
  • 并行上傳:上傳多個文件或文件塊時,確保使用多線程或并行任務來提升上傳速率。
b. 優化 S3 配置
  • 選擇合適的 S3 存儲類型:對于頻繁訪問的文件,選擇 S3 Standard 存儲類型;對于長期存儲不頻繁訪問的數據,可以選擇 S3 GlacierS3 Intelligent-Tiering,這樣能進一步優化成本。
  • 上傳的區域選擇:確保將文件上傳至與用戶或服務最接近的 AWS 區域。不同區域的網絡帶寬不同,選擇一個低延遲、高帶寬的區域將有助于提升上傳速度。
c. 使用 AWS SDK 或 AWS CLI 上傳
  • AWS SDK:使用 AWS 提供的 SDK(如 AWS SDK for Java)進行分塊上傳可以幫助管理并發任務,提升上傳效率。
  • AWS CLI:如果使用命令行,aws s3 cpaws s3 sync 命令本身就支持分塊上傳,并且能自動優化上傳過程。
aws s3 cp largefile.zip s3://yourbucket/ --storage-class STANDARD_IA --sse AES256 --multipart-chunk-size-mb 10
d. 壓縮時減少冗余

在壓縮時,盡量去除 JSON 文件中的冗余數據(如空格、換行符等),以便達到更高的壓縮比。你可以在壓縮前通過工具(如 jq)將 JSON 格式化處理為一個最小的單行格式。

cat *.json | jq -c . > compressed.json

3. 硬件和網絡優化

  • 網絡帶寬:上傳文件的速度受限于你服務器或本地網絡的上傳帶寬。如果可能,嘗試優化網絡連接(例如使用更快的上傳鏈路、避免網絡瓶頸)。
  • 硬盤讀寫速度:確保壓縮文件時,硬盤讀寫性能足夠好,特別是使用 SSD 而非機械硬盤,以避免磁盤 I/O 成為瓶頸。

4. 云端優化

如果你通過中間服務器上傳至 S3,考慮使用 AWS Direct Connect 或與 AWS 區域直接連接的高速網絡線路,以避免互聯網帶寬限制。

5. 總結

  • 壓縮算法選擇:Zstandard(zstd)在提供高壓縮比和高速壓縮性能之間有很好的平衡,適合用于此類文件壓縮。
  • 分塊上傳:通過 S3 的 Multipart Upload 功能,并行上傳大文件,能顯著提高上傳速率。
  • 工具和網絡優化:使用 AWS SDK、CLI,或者在壓縮文件時去除冗余,進一步提升效率。

根據這些方案,你可以顯著提升文件上傳至 S3 的速度和效率。

實踐

Apache Commons Compress

依賴

  • Maven:
<dependency><groupId>org.apache.commons</groupId><artifactId>commons-compress</artifactId><version>1.21</version>
</dependency>

壓縮文件

首先,我們通過 CompressorStreamFactory 來根據指定的壓縮算法(如 Brotli)壓縮文件。

import org.apache.commons.compress.compressors.CompressorStreamFactory;
import org.apache.commons.compress.compressors.CompressorOutputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.OutputStream;public class CompressionExample {public static void main(String[] args) {String inputData = "This is some sample text to be compressed using Brotli.";String outputFile = "output.br";  // 輸出為 Brotli 壓縮文件try {// 創建輸出流OutputStream fileOutputStream = new FileOutputStream(outputFile);CompressorStreamFactory factory = new CompressorStreamFactory();// 動態選擇壓縮算法(Brotli)try (CompressorOutputStream compressorOutputStream = factory.createCompressorOutputStream("brotli", fileOutputStream)) {compressorOutputStream.write(inputData.getBytes());// 文件流之間復制// 使用 IOUtils 工具類將輸入流的數據寫入到壓縮輸出流// IOUtils.copy(fileInputStream, lz4OutputStream);}System.out.println("File compressed to: " + outputFile);} catch (IOException | org.apache.commons.compress.compressors.CompressorException e) {e.printStackTrace();}}
}

解壓縮文件

對于解壓縮操作,我們使用 CompressorStreamFactory 來自動選擇與壓縮時相同的解壓縮算法,并解壓文件。

import org.apache.commons.compress.compressors.CompressorStreamFactory;
import org.apache.commons.compress.compressors.CompressorInputStream;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;public class DecompressionExample {public static void main(String[] args) {String inputFile = "output.br";  // 輸入為 Brotli 壓縮文件String outputFile = "decompressed.txt";  // 解壓后的文件try {// 創建輸入流InputStream fileInputStream = new FileInputStream(inputFile);CompressorStreamFactory factory = new CompressorStreamFactory();// 動態選擇解壓縮算法(Brotli)try (CompressorInputStream compressorInputStream = factory.createCompressorInputStream("brotli", fileInputStream)) {int byteRead;StringBuilder decompressedData = new StringBuilder();// 讀取解壓縮后的數據while ((byteRead = compressorInputStream.read()) != -1) {decompressedData.append((char) byteRead);}// 輸出解壓縮數據System.out.println("Decompressed data: " + decompressedData.toString());}} catch (IOException | org.apache.commons.compress.compressors.CompressorException e) {e.printStackTrace();}}
}

其他類庫

zstd

要在 Java 中使用 Zstandard (zstd) 進行壓縮和解壓縮,你可以使用第三方庫,例如 zstd-jni,它是一個基于 JNI 的 Java 實現,允許你在 Java 中高效地使用 Zstandard 算法。

1. 添加依賴

如果你使用的是 Maven,可以在 pom.xml 中添加以下依賴:

<dependency><groupId>com.github.luben</groupId><artifactId>zstd-jni</artifactId><version>1.5.2-1</version>
</dependency>

2. Zstandard 壓縮與解壓縮案例

以下是一個簡單的 Java 示例,展示如何使用 zstd-jni 進行文件的壓縮和解壓縮。

a. 壓縮文件
import com.github.luben.zstd.ZstdOutputStream;import java.io.*;
import java.nio.file.Files;public class ZstdCompressExample {public static void main(String[] args) throws IOException {String inputFile = "input.json";String outputFile = "output.zst";// 創建輸入文件流try (InputStream in = new FileInputStream(inputFile);OutputStream out = new FileOutputStream(outputFile);ZstdOutputStream zstdOut = new ZstdOutputStream(out)) {// 進行壓縮byte[] buffer = new byte[8192];int bytesRead;while ((bytesRead = in.read(buffer)) != -1) {zstdOut.write(buffer, 0, bytesRead);}}System.out.println("File compressed successfully: " + outputFile);}
}
  • 解釋
    • 通過 ZstdOutputStream 將輸入文件流壓縮后寫入到輸出文件中。
    • 使用 8KB 緩沖區來提高處理效率。
b. 解壓縮文件
import com.github.luben.zstd.ZstdInputStream;import java.io.*;public class ZstdDecompressExample {public static void main(String[] args) throws IOException {String inputFile = "output.zst";String outputFile = "decompressed.json";// 創建輸入文件流try (InputStream in = new FileInputStream(inputFile);ZstdInputStream zstdIn = new ZstdInputStream(in);OutputStream out = new FileOutputStream(outputFile)) {// 進行解壓縮byte[] buffer = new byte[8192];int bytesRead;while ((bytesRead = zstdIn.read(buffer)) != -1) {out.write(buffer, 0, bytesRead);}}System.out.println("File decompressed successfully: " + outputFile);}
}
  • 解釋
    • 通過 ZstdInputStream 讀取壓縮文件并解壓,然后將解壓后的數據寫入輸出文件中。

3. 壓縮和解壓縮字節數組(內存中的數據)

如果你不想直接操作文件,也可以對字節數組進行壓縮和解壓縮。

a. 壓縮字節數組
import com.github.luben.zstd.Zstd;import java.io.IOException;
import java.util.Arrays;public class ZstdByteArrayCompressExample {public static void main(String[] args) throws IOException {byte[] inputData = "This is a sample data to be compressed.".getBytes();// 使用 Zstandard 壓縮字節數組byte[] compressedData = Zstd.compress(inputData);System.out.println("Original size: " + inputData.length);System.out.println("Compressed size: " + compressedData.length);}
}
b. 解壓縮字節數組
import com.github.luben.zstd.Zstd;import java.io.IOException;public class ZstdByteArrayDecompressExample {public static void main(String[] args) throws IOException {byte[] compressedData = "This is a sample data to be compressed.".getBytes(); // 假設這已經是壓縮過的數據// 使用 Zstandard 解壓字節數組byte[] decompressedData = Zstd.decompress(compressedData, 1000);  // 1000 是最大預期大小System.out.println("Decompressed data: " + new String(decompressedData));}
}

4. 優化壓縮級別

你還可以通過設置壓縮級別來平衡壓縮率和壓縮速度。Zstandard 提供了多個級別(1 到 22),數字越大,壓縮比越高,但速度較慢。

import com.github.luben.zstd.Zstd;import java.io.IOException;public class ZstdCompressExample {public static void main(String[] args) throws IOException {byte[] inputData = "This is a sample data to be compressed.".getBytes();// 使用級別 3 進行壓縮byte[] compressedData = Zstd.compress(inputData, 3);System.out.println("Original size: " + inputData.length);System.out.println("Compressed size: " + compressedData.length);}
}

5. 總結

  • zstd-jni 是一個高效的 Zstandard 實現,適用于壓縮和解壓大文件或字節數組。
  • 壓縮和解壓過程支持文件和內存中的數據,靈活性較高。
  • 通過設置壓縮級別,可以在壓縮比和壓縮速度之間找到平衡。
  • 你可以結合壓縮和多線程來提升上傳速度,尤其是在上傳到 S3 這類云存儲時。

通過這些方法,你可以在 Java 項目中高效地使用 Zstandard 來處理壓縮和解壓縮,提升數據傳輸效率。

Brotli

Google 的 Brotli Java 綁定可以通過 Brotli 官方提供的 Java 庫來使用,它是由 Google 維護的,具有更活躍的社區支持和更多的更新。這個庫是直接通過 com.google 包提供的,你可以使用它來進行 Brotli 壓縮和解壓縮。

下面是如何使用 Google 的 Brotli Java 綁定 來進行壓縮和解壓縮操作的示例。

1. 添加依賴

你可以通過以下方式將 Brotli 添加到你的項目中。

Maven

pom.xml 中添加依賴:

<dependency><groupId>com.google.code.findbugs</groupId><artifactId>jsr305</artifactId><version>3.0.2</version>
</dependency>
<dependency><groupId>com.google.brotli</groupId><artifactId>brotli</artifactId><version>1.7.0</version>
</dependency>

2. 使用 Brotli 進行壓縮和解壓縮

以下是壓縮和解壓縮文件的示例。

壓縮數據
import com.google.brotli.encoder.BrotliOutputStream;import java.io.*;public class BrotliCompressExample {public static void main(String[] args) {String inputFilePath = "input.txt";  // 輸入文件路徑String outputFilePath = "output.br"; // 輸出壓縮文件路徑try {// 讀取輸入文件File inputFile = new File(inputFilePath);byte[] inputData = readFile(inputFile);// 壓縮數據byte[] compressedData = compress(inputData);// 將壓縮數據寫入輸出文件writeFile(outputFilePath, compressedData);System.out.println("Compression complete: " + outputFilePath);} catch (IOException e) {e.printStackTrace();}}// 讀取文件內容為字節數組public static byte[] readFile(File file) throws IOException {try (InputStream is = new FileInputStream(file);ByteArrayOutputStream buffer = new ByteArrayOutputStream()) {byte[] chunk = new byte[1024];int bytesRead;while ((bytesRead = is.read(chunk)) != -1) {buffer.write(chunk, 0, bytesRead);}return buffer.toByteArray();}}// 使用 Brotli 壓縮數據public static byte[] compress(byte[] input) throws IOException {try (ByteArrayOutputStream baos = new ByteArrayOutputStream();BrotliOutputStream brotliOut = new BrotliOutputStream(baos)) {brotliOut.write(input);brotliOut.flush();return baos.toByteArray();}}// 寫數據到文件public static void writeFile(String filePath, byte[] data) throws IOException {try (FileOutputStream fos = new FileOutputStream(filePath)) {fos.write(data);}}
}
解壓縮數據
import com.google.brotli.decoder.BrotliInputStream;import java.io.*;public class BrotliDecompressExample {public static void main(String[] args) {String inputFilePath = "output.br";  // 輸入文件路徑(壓縮文件)String outputFilePath = "decompressed.txt"; // 輸出解壓文件路徑try {// 解壓縮數據byte[] decompressedData = decompress(new File(inputFilePath));// 將解壓縮的數據寫入文件writeFile(outputFilePath, decompressedData);System.out.println("Decompression complete: " + outputFilePath);} catch (IOException e) {e.printStackTrace();}}// 使用 Brotli 解壓縮數據public static byte[] decompress(File inputFile) throws IOException {try (InputStream is = new FileInputStream(inputFile);BrotliInputStream brotliIn = new BrotliInputStream(is);ByteArrayOutputStream baos = new ByteArrayOutputStream()) {byte[] buffer = new byte[1024];int bytesRead;while ((bytesRead = brotliIn.read(buffer)) != -1) {baos.write(buffer, 0, bytesRead);}return baos.toByteArray();}}// 寫數據到文件public static void writeFile(String filePath, byte[] data) throws IOException {try (FileOutputStream fos = new FileOutputStream(filePath)) {fos.write(data);}}
}

3. 代碼解析

  • 壓縮BrotliOutputStream 用于壓縮數據。你只需要通過 write() 將數據寫入流中,然后使用 flush() 提交壓縮的數據。
  • 解壓縮BrotliInputStream 用于讀取壓縮數據并解壓。數據通過 read() 方法被讀取并解壓到輸出流中,最終可以通過 ByteArrayOutputStream 獲取解壓后的數據。
  • 文件操作:我們使用 FileInputStreamFileOutputStream 來處理文件的讀取和寫入。

4. 性能與配置

Brotli 算法提供了非常高效的壓縮率,尤其適合用于 Web 內容壓縮,但其壓縮速度相對較慢。你可以調整壓縮級別來平衡壓縮率與性能:

  • 壓縮級別:通過 BrotliOutputStream 構造函數的第二個參數設置壓縮級別,范圍是 0 到 11,0 表示最快但壓縮率低,11 表示最慢但壓縮率高。

示例:設置壓縮級別為 5:

BrotliOutputStream brotliOut = new BrotliOutputStream(baos, 5);

5. 總結

Google 的 Brotli Java 綁定提供了 BrotliInputStreamBrotliOutputStream 類,分別用于解壓和壓縮 Brotli 格式的文件。這個庫比 Brotli4j 更活躍,且得到了 Google 官方的支持。通過調整壓縮級別,你可以在壓縮率和速度之間找到合適的平衡。

LZ4

在 Java 中使用 LZ4 壓縮算法,可以通過 lz4-java 庫,它是一個對 LZ4 算法的 Java 實現。LZ4 以其超高速壓縮和解壓速度著稱,適用于需要高吞吐量的場景。以下是如何在 Java 中使用 LZ4 來壓縮和解壓數據的完整示例。

1. 添加依賴

首先,確保將 lz4-java 添加到你的項目依賴中。

Maven

pom.xml 中添加以下依賴:

<dependency><groupId>net.jpountz.lz4</groupId><artifactId>lz4</artifactId><version>1.8.0</version>
</dependency>

2. 使用 LZ4 壓縮和解壓縮

以下是一個基本的示例,展示了如何使用 LZ4 壓縮和解壓縮文件內容。

壓縮數據
import net.jpountz.lz4.LZ4BlockOutputStream;
import net.jpountz.lz4.LZ4Factory;import java.io.*;public class LZ4CompressExample {public static void main(String[] args) {String inputFilePath = "input.txt";  // 輸入文件路徑String outputFilePath = "output.lz4"; // 輸出壓縮文件路徑try {// 讀取輸入文件File inputFile = new File(inputFilePath);byte[] inputData = readFile(inputFile);// 壓縮數據byte[] compressedData = compress(inputData);// 將壓縮數據寫入輸出文件writeFile(outputFilePath, compressedData);System.out.println("Compression complete: " + outputFilePath);} catch (IOException e) {e.printStackTrace();}}// 讀取文件內容為字節數組public static byte[] readFile(File file) throws IOException {try (InputStream is = new FileInputStream(file);ByteArrayOutputStream buffer = new ByteArrayOutputStream()) {byte[] chunk = new byte[1024];int bytesRead;while ((bytesRead = is.read(chunk)) != -1) {buffer.write(chunk, 0, bytesRead);}return buffer.toByteArray();}}// 使用 LZ4 壓縮數據public static byte[] compress(byte[] input) throws IOException {LZ4Factory factory = LZ4Factory.fastestInstance();ByteArrayOutputStream baos = new ByteArrayOutputStream();try (LZ4BlockOutputStream lz4Out = new LZ4BlockOutputStream(baos, factory.fastestCompressor())) {lz4Out.write(input);lz4Out.flush();}return baos.toByteArray();}// 寫數據到文件public static void writeFile(String filePath, byte[] data) throws IOException {try (FileOutputStream fos = new FileOutputStream(filePath)) {fos.write(data);}}
}
解壓縮數據
import net.jpountz.lz4.LZ4BlockInputStream;
import net.jpountz.lz4.LZ4Factory;import java.io.*;public class LZ4DecompressExample {public static void main(String[] args) {String inputFilePath = "output.lz4";  // 輸入文件路徑(壓縮文件)String outputFilePath = "decompressed.txt"; // 輸出解壓文件路徑try {// 解壓縮數據byte[] decompressedData = decompress(new File(inputFilePath));// 將解壓縮的數據寫入文件writeFile(outputFilePath, decompressedData);System.out.println("Decompression complete: " + outputFilePath);} catch (IOException e) {e.printStackTrace();}}// 使用 LZ4 解壓縮數據public static byte[] decompress(File inputFile) throws IOException {try (InputStream is = new FileInputStream(inputFile);LZ4BlockInputStream lz4In = new LZ4BlockInputStream(is)) {ByteArrayOutputStream baos = new ByteArrayOutputStream();byte[] buffer = new byte[1024];int bytesRead;while ((bytesRead = lz4In.read(buffer)) != -1) {baos.write(buffer, 0, bytesRead);}return baos.toByteArray();}}// 寫數據到文件public static void writeFile(String filePath, byte[] data) throws IOException {try (FileOutputStream fos = new FileOutputStream(filePath)) {fos.write(data);}}
}

3. 代碼解析

  • 壓縮LZ4BlockOutputStream 用于將數據寫入壓縮流。你可以通過傳入 LZ4Factory.fastestCompressor() 來選擇最快的壓縮器。壓縮后的字節數據可以被寫入到 ByteArrayOutputStream,并最終得到壓縮后的數據。
  • 解壓縮LZ4BlockInputStream 用于從壓縮流中讀取數據并進行解壓。讀取后,數據會被寫入到 ByteArrayOutputStream,最終得到解壓后的字節數據。
  • 性能:LZ4 是一種非常快速的壓縮算法,它優化了 CPU 使用率,并且能夠在壓縮速度和壓縮比之間取得較好的平衡。fastestCompressor() 是最快的壓縮方法,適用于需要快速壓縮的場景。

4. 壓縮級別

LZ4 并不像其他壓縮算法(如 Zstd)那樣支持多個壓縮級別。它的設計重點是壓縮速度,因此它的壓縮速度相對較快,但壓縮比沒有像 Zstd 那么高。如果你需要更高的壓縮比,Zstd 或 Brotli 可能更適合。不過,對于需要極快壓縮/解壓速度的場景,LZ4 是一個非常好的選擇。

5. 總結

  • LZ4 的特點:LZ4 是一個高性能、低延遲的壓縮算法,適合處理對速度要求較高的場景,尤其是流式數據和大數據處理。
  • 壓縮方式:Java 中通過 LZ4BlockOutputStreamLZ4BlockInputStream 來處理文件壓縮與解壓縮。對于內存中的字節數組,可以使用 LZ4CompressorLZ4FastDecompressor
  • 性能:LZ4 提供了非常快的壓縮和解壓縮速度,雖然壓縮比相對較低,但仍適合用于大部分實時應用場景。

通過這種方式,你可以在 Java 中高效地使用 LZ4 壓縮和解壓縮數據,提升數據傳輸和存儲的效率。

S3分塊上傳

分塊上傳(Multipart Upload)是 Amazon S3 的一個功能,允許將大文件分為多個部分進行上傳,從而提高上傳效率,并支持在上傳過程中斷點續傳。在 AWS SDK for Java 中,你可以使用 TransferManager 來實現分塊上傳,或者使用 AmazonS3 提供的原生 initiateMultipartUpload 方法進行自定義實現。

分塊上傳的步驟

  1. 初始化上傳:調用 initiateMultipartUpload 方法開始一個分塊上傳操作。
  2. 上傳各個部分:將文件分割成多個塊并上傳。
  3. 完成上傳:調用 completeMultipartUpload 來完成上傳。

使用 AWS SDK for Java 實現分塊上傳的示例

1. Maven 依賴

確保你的 Maven 項目中包含了 AWS SDK for Java 的相關依賴:

<dependency><groupId>com.amazonaws</groupId><artifactId>aws-java-sdk-s3</artifactId><version>2.20.1</version> <!-- 請使用最新版本 -->
</dependency>

2. 分塊上傳代碼示例

下面是一個分塊上傳的代碼示例,使用 AmazonS3TransferManager 進行分塊上傳。

import com.amazonaws.AmazonServiceException;
import com.amazonaws.auth.profile.ProfileCredentialsProvider;
import com.amazonaws.services.s3.AmazonS3;
import com.amazonaws.services.s3.AmazonS3ClientBuilder;
import com.amazonaws.services.s3.model.*;import java.io.File;
import java.io.IOException;
import java.nio.file.Files;
import java.util.ArrayList;
import java.util.List;public class S3MultipartUpload {private static final String BUCKET_NAME = "your-bucket-name"; // 目標S3桶名private static final String OBJECT_KEY = "your-object-key"; // 目標文件在S3的鍵(路徑)public static void main(String[] args) throws IOException {// 初始化AmazonS3客戶端AmazonS3 s3Client = AmazonS3ClientBuilder.standard().withCredentials(new ProfileCredentialsProvider()) // 使用配置文件中的憑證.build();// 文件路徑File file = new File("path-to-large-file");// 分塊大小,5MB是最小的分塊大小long partSize = 5 * 1024 * 1024; // 獲取文件大小long fileSize = file.length();// 初始化分塊上傳InitiateMultipartUploadRequest initRequest = new InitiateMultipartUploadRequest(BUCKET_NAME, OBJECT_KEY);InitiateMultipartUploadResult initResponse = s3Client.initiateMultipartUpload(initRequest);String uploadId = initResponse.getUploadId();// 按照分塊大小分割文件并上傳List<PartETag> partETags = new ArrayList<>();try {// 分塊上傳for (long i = 0; i < fileSize; i += partSize) {long size = Math.min(partSize, fileSize - i);UploadPartRequest uploadRequest = new UploadPartRequest().withBucketName(BUCKET_NAME).withKey(OBJECT_KEY).withUploadId(uploadId).withPartNumber((int) (i / partSize) + 1).withFileOffset(i).withFile(file).withPartSize(size);// 上傳分塊UploadPartResult uploadPartResult = s3Client.uploadPart(uploadRequest);partETags.add(uploadPartResult.getPartETag());System.out.println("Uploaded part " + (i / partSize + 1));}// 完成上傳CompleteMultipartUploadRequest completeRequest = new CompleteMultipartUploadRequest(BUCKET_NAME, OBJECT_KEY, uploadId, partETags);s3Client.completeMultipartUpload(completeRequest);System.out.println("File uploaded successfully!");} catch (AmazonServiceException e) {// 如果上傳失敗,取消上傳s3Client.abortMultipartUpload(new AbortMultipartUploadRequest(BUCKET_NAME, OBJECT_KEY, uploadId));e.printStackTrace();}}
}

3. 代碼說明

  • 初始化上傳(**initiateMultipartUpload**:通過 InitiateMultipartUploadRequest 創建一個新的上傳任務,并返回一個 uploadId,這個 ID 用于后續分塊上傳和完成上傳。
  • 分塊上傳(**uploadPart**:通過 UploadPartRequest 來上傳每個文件塊。withFileOffset 表示文件上傳的起始偏移位置,withPartSize 用于指定每個塊的大小。
  • 完成上傳(**completeMultipartUpload**:所有部分上傳成功后,使用 CompleteMultipartUploadRequest 來完成分塊上傳,所有上傳的部分會被合并成一個完整的文件。
  • 錯誤處理(**abortMultipartUpload**:在上傳過程中如果發生異常(例如服務端錯誤),我們調用 abortMultipartUpload 來取消上傳,并清理資源。

4. 注意事項

  • 分塊大小:AWS 對分塊上傳有一定的要求。每個部分必須至少為 5MB,最后一個部分可以小于 5MB。可以根據文件的大小選擇合理的分塊大小。
  • 上傳過程中的錯誤:如果上傳失敗,記得調用 abortMultipartUpload 來中止上傳,避免留下未完成的部分。
  • 憑證管理:本示例使用了 ProfileCredentialsProvider,你也可以選擇其他憑證提供方式,例如環境變量或硬編碼憑證,但不推薦硬編碼。

5. **更高效的方式:使用 ****TransferManager**

對于一些應用場景,你可以使用 TransferManager 進行更加高效和便捷的分塊上傳。TransferManager 是 AWS SDK 提供的高級 API,自動處理分塊上傳和下載、進度報告等功能。以下是使用 TransferManager 實現分塊上傳的示例:

使用 TransferManager 實現分塊上傳
import com.amazonaws.auth.profile.ProfileCredentialsProvider;
import com.amazonaws.services.s3.AmazonS3;
import com.amazonaws.services.s3.AmazonS3ClientBuilder;
import com.amazonaws.services.s3.model.*;
import com.amazonaws.services.s3.transfer.TransferManager;
import com.amazonaws.services.s3.transfer.Upload;import java.io.File;public class TransferManagerExample {private static final String BUCKET_NAME = "your-bucket-name";private static final String OBJECT_KEY = "your-object-key";public static void main(String[] args) {// 初始化S3客戶端和TransferManagerAmazonS3 s3Client = AmazonS3ClientBuilder.standard().withCredentials(new ProfileCredentialsProvider()).build();TransferManager transferManager = TransferManagerBuilder.standard().s3Client(s3Client).build();// 創建文件對象File file = new File("path-to-large-file");// 開始分塊上傳Upload upload = transferManager.upload(BUCKET_NAME, OBJECT_KEY, file);try {// 等待上傳完成upload.waitForCompletion();System.out.println("Upload completed!");} catch (Exception e) {e.printStackTrace();}}
}

在這個示例中,TransferManager 會自動處理文件分割、上傳和合并的工作,你不需要手動拆分文件和上傳每一部分。

6. 總結

  • 分塊上傳:AWS S3 提供了分塊上傳功能,適用于上傳大文件。你可以使用 AmazonS3 的原生方法或者 TransferManager 來簡化這個過程。
  • **TransferManager**:是 AWS SDK 提供的更高層次的 API,簡化了分塊上傳的過程,自動處理了上傳任務和塊的管理。
  • 錯誤處理:上傳過程中如果發生異常,記得調用 abortMultipartUpload 來清理未完成的上傳任務。

選擇哪種方式取決于你的需求,如果你需要更多控制和自定義分塊上傳的行為,可以使用 AmazonS3 的原生方法;如果你希望快速實現且自動處理所有細節,TransferManager 是一個更方便的選擇。

API選擇建議

文件大小

  • 小文件(<100MB):S3 SDK 原生 API。
  • 中型文件(100MB~500MB):S3 Transfer Manager,享受分塊傳輸的性能優化。
  • 大文件(>500MB):Transfer Manager 或者 AWS CLI。

性能對比

工具適用范圍優勢劣勢
S3 Transfer Manager100MB~GB+并發傳輸、分塊優化、高效、異步支持需要更多依賴,初始化稍復雜
原生 S3 API小于 500MB簡單直接,無需額外配置無分塊傳輸,性能有限
AWS CLI小型/大型文件易用,后臺優化傳輸性能需要使用命令行,無法嵌入 Java 項目

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/news/903888.shtml
繁體地址,請注明出處:http://hk.pswp.cn/news/903888.shtml
英文地址,請注明出處:http://en.pswp.cn/news/903888.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

CAD(計算機輔助設計)基礎知識點整理

以下是CAD&#xff08;計算機輔助設計&#xff09;的基礎知識點整理&#xff0c;涵蓋核心概念、操作技巧和行業規范&#xff0c;適合新手學習和參考&#xff1a; 一、CAD基本概念 什么是CAD ? 利用計算機技術進行設計和繪圖的工具&#xff0c;廣泛應用于機械、建筑、電子等領…

重構之道:識別并替換不合適使用的箭頭函數

1、引言 JavaScript 自 ES6 引入了箭頭函數(Arrow Function)后,因其簡潔的語法和對 this 的詞法綁定機制,迅速成為開發者喜愛的寫法之一。然而,并不是所有場景都適合使用箭頭函數。 在實際開發中,我們常常會因為追求代碼簡潔而忽視其潛在問題,例如: this 指向錯誤不適…

[英語單詞] from under

最近在看RCU的資料&#xff0c;讀到下面的一句&#xff0c;感覺總是特別怪怪的&#xff0c;就是從單詞的組合角度&#xff0c;記錄一下。 Use rcu_read_lock() and rcu_read_unlock() to ensure that the structure does not get deleted out from under us。 意思是我們還在使…

Python 中 DAO 層使用泛型的探索

方法一&#xff1a; from types import UnionType from typing import TypeVar, Generic, TypeModelT TypeVar(ModelT)def _new_cls_with_grm_generic_args(cls, __item):new_cls type(f"{cls.__name__}[{__item.__name__}]", (cls,), {})new_cls._grm_generic_ar…

Cesium 環境搭建

一、前提條件 1. **安裝 Node.js** - 訪問 [Node.js 官方網站](https://nodejs.org/)&#xff0c;下載并安裝適合你操作系統的版本。Node.js 用于運行本地開發服務器和安裝依賴。 2. **安裝 Vue CLI** - Vue CLI 是一個用于快速開發 Vue.js 項目的工具。在終端中運行以下…

DarkGS:論文解讀與全流程環境配置及數據集測試【基于Ubuntu20.04 】【2025最新實戰無坑版!!】

一、背景及意義 DarkGS是一個創新性的研究項目&#xff0c;旨在解決機器人在黑暗或低光照環境中探索的問題。傳統的3D重建和視覺定位系統在光照條件不佳時表現不佳&#xff0c;這嚴重限制了機器人在黑暗環境中的應用&#xff0c;如夜間救援、深海探索或洞穴勘測等場景。 這項工…

(八)RestAPI 毛子(Unit Testing/Integration)

文章目錄 項目地址一、Unit Testing1.1 創建X unit 測試項目1. 創建項目目錄2. 管理包1.2 創建CreateEntryDtoValidator測試1.3 創建CreateEntryDtoValidator測試二、Integration test2.1 創建Integration test環境1. 安裝所需要的包2.2 配置基礎設置1. 數據庫鏈接DevHabitWebA…

設計模式--橋接模式詳解

橋接模式&#xff08;bridge pattern&#xff09; 橋接模式時將抽象部分與它的實現部分分離&#xff0c;使他們可以獨立的變化。它是一種對象結構型模式&#xff0c;又稱為柄體&#xff08;Handle and Body&#xff09;模式或者接口&#xff08;interface&#xff09;模式&…

關于 live555延遲優化之緩存區優化“StreamParser::afterGettingBytes() warning: read”” 的解決方法

若該文為原創文章&#xff0c;轉載請注明原文出處 本文章博客地址&#xff1a;https://hpzwl.blog.csdn.net/article/details/146354088 長沙紅胖子Qt&#xff08;長沙創微智科&#xff09;博文大全&#xff1a;開發技術集合&#xff08;包含Qt實用技術、樹莓派、三維、OpenCV…

Vite 動態導入靜態資源與自動依賴發現實戰解析

一、Vite 動態導入靜態資源的實現方案 在 Vite 中&#xff0c;動態加載圖片、JSON 等靜態資源是高頻需求&#xff0c;但動態路徑拼接可能導致構建失敗或資源未識別。以下結合示例代碼&#xff0c;分析三種實現方案&#xff1a; 1. 方案一&#xff1a;new URL 動態路徑轉換 通…

在matlab中使用UAV123官方toolkits測試自己的數據集

一、前言 最近需要將自己的跟蹤代碼在自己拍攝的數據集上進行測試&#xff0c;這里我選擇使用 UAV123 官方 toolkits 進行配置。首先需要搞清楚這部分代碼是如何運行的&#xff0c;精度圖和成功率圖是如何繪制出來的&#xff0c;然后再將自己的數據集加進去進行測試。 二、UA…

9.idea中創建springboot項目_jdk1.8

9. idea中創建springboot項目_jdk1.8 步驟 1&#xff1a;打開 IntelliJ IDEA 并創建新項目 啟動 IntelliJ IDEA。在歡迎界面&#xff0c;點擊 New Project&#xff08;或通過菜單欄 File > New > Project&#xff09;。 步驟 2&#xff1a;選擇 Maven 項目類型 在左側…

SpringAI實現AI應用-搭建知識庫

SpringAI實戰鏈接 1.SpringAl實現AI應用-快速搭建-CSDN博客 2.SpringAI實現AI應用-搭建知識庫-CSDN博客 概述 想要使用SpringAI搭建知識庫&#xff0c;就要使用SpringAI中的TikaDocumentReader&#xff0c;它屬于ETL&#xff08;提取、轉換、加載&#xff09;框架中的提取&…

內網服務器映射到公網上怎么做?網絡將內網服務轉換到公網上

如何將內網映射到公網&#xff1f;本地局域網的網絡下部署的內網服務地址轉換到公網上連接訪問是大家比較關注的問題&#xff0c;特別是在無公網IP使用的情況下&#xff0c;很多人不知道怎么做。 在沒有公網 IP 的情況下&#xff0c;要將內網映射到公網&#xff0c;以便外網能…

intellij idea最新版git開啟Local Changes

習慣了在idea的git插件里&#xff0c;查看項目已修改的文件&#xff0c;但是新版idea默認不展示了&#xff0c;用起來很難受。 參考網上教程開啟方法如下&#xff1a; 1. 確保安裝Git Modal Commit Interface插件并開啟該插件 2. 在Advanced Settings開啟Use Modal Commit In…

??智能制造中的預測性維護:基于深度學習的設備故障預測??

智能制造中的預測性維護:基于深度學習的設備故障預測 引言 在智能制造領域,設備突發故障可能導致巨大的經濟損失。傳統維護方式(如定期檢修或事后維修)往往效率低下且成本高昂。預測性維護(Predictive Maintenance, PdM)通過實時監測設備狀態并預測潛在故障,能夠顯著減…

DeepSeek+即夢:AI視頻創作從0到1全突破

目錄 一、開啟 AI 視頻創作大門&#xff1a;前期準備1.1 注冊與登錄1.2 熟悉工具界面1.3 硬件與網絡要求 二、用 DeepSeek 構思視頻腳本2.1 明確創作主題與目標2.2 編寫優質提示詞2.3 生成并優化腳本 三、即夢 AI 實現畫面生成3.1 文生圖基礎操作3.2 調整參數提升畫質3.3 保持人…

初始化列表詳解

1.類中包含以下成員&#xff0c;必須放在初始化列表位置進行初始化&#xff1a; 1. 引用成員變量 2.const成員變量 3. 自定義類型成員(且該類沒有默認構造函數時 ) 2. 成員變量在類中聲明次序就是其在初始化列表中的初始化順序&#xff0c;與其在初始化列表中的先后次序無關…

基于建造者模式的信號量與理解建造者模式

信號量是什么&#xff1f; AI解釋&#xff1a;信號量&#xff08;Semaphore&#xff09;是操作系統中用于 進程同步與互斥 的經典工具&#xff0c;由荷蘭計算機科學家 Edsger Dijkstra 在 1965 年提出。它本質上是一個 非負整數變量&#xff0c;通過原子操作&#xff08;P 操作…

開閉原則(OCP)

非常棒的問題&#xff01;&#x1f50d; 開閉原則&#xff08;OCP, Open/Closed Principle&#xff09;是軟件設計的核心原則之一&#xff0c;下面我將從定義、意義、優劣分析、Python示例和結構圖五個方面完整解析給你。 &#x1f9e0; 什么是開閉原則&#xff1f; 開閉原則&a…