大容量ファイルを効率的にアップロードするための分割アップロード手法について解説します。以下の実装例では5MB単位でファイルを分割し、マルチスレッドで並列アップロードを行います。
// 分割アップロードメインクラス
public class ChunkedUploader {
private static final int DEFAULT_CHUNK_SIZE = 5 * 1024 * 1024; // 基本分割サイズ
public void executeUpload(File targetFile, String storageBucket) throws Exception {
// アップロードセッション開始
StartUploadSessionRequest startReq = new StartUploadSessionRequest(storageBucket, targetFile.getName());
UploadSession session = storageClient.startUploadSession(startReq);
// 並列処理用スレッドプール
ExecutorService threadPool = Executors.newFixedThreadPool(getOptimalThreadCount());
List<Future<UploadPartTag>> taskResults = new ArrayList<>();
// ファイル分割処理
long totalSize = targetFile.length();
int totalParts = calculateTotalParts(totalSize, DEFAULT_CHUNK_SIZE);
// 分割タスク実行
for (int partIndex = 1; partIndex <= totalParts; partIndex++) {
long startByte = (partIndex - 1) * DEFAULT_CHUNK_SIZE;
long partSize = Math.min(DEFAULT_CHUNK_SIZE, totalSize - startByte);
UploadTask task = new UploadTask(
session.getSessionId(),
storageBucket,
targetFile.getName(),
targetFile,
startByte,
partSize,
partIndex
);
taskResults.add(threadPool.submit(task));
}
// 全タスク完了待機
List<UploadPartTag> partTags = new ArrayList<>();
for (Future<UploadPartTag> result : taskResults) {
partTags.add(result.get());
}
// 分割ファイル結合
CompleteUploadRequest completeReq = new CompleteUploadRequest(
storageBucket, targetFile.getName(), session.getSessionId(), partTags);
storageClient.completeUpload(completeReq);
}
private int calculateTotalParts(long fileSize, int chunkSize) {
return (int) Math.ceil((double)fileSize / chunkSize);
}
private int getOptimalThreadCount() {
return Runtime.getRuntime().availableProcessors() * 2;
}
}
// 分割アップロードタスク
class UploadTask implements Callable<UploadPartTag> {
// 各分割部分のアップロード処理実装
@Override
public UploadPartTag call() throws Exception {
// ファイルチャンク読み込み
// アップロードリクエスト作成
// ストレージへのアップロード実行
// 結果タグを返却
}
}
ファイルサイズに応じた動的な分割サイズ決定ロジック:
def determine_chunk_size(file_size_bytes):
# ファイルサイズに基づき最適な分割サイズを決定
if file_size_bytes <= 50 * 1024 * 1024: # 50MB以下
return 1 * 1024 * 1024 # 1MB分割
elif file_size_bytes <= 5 * 1024 * 1024 * 1024: # 5GB以下
return 5 * 1024 * 1024 # 5MB分割
else:
return 10 * 1024 * 1024 # 10MB分割