Blob 数据下载
备注
Blob 数据下载目前支持 Java SDK 和 Python SDK,Go SDK 暂不支持。
MaxCompute 的 BLOB 类型用于存储非结构化的二进制大对象数据(如图片、音频、文档等)。Blob 在表中以引用(Reference)的形式存储,实际的二进制数据需要通过 BlobManager(Java)或 StorageApiClient.read_blobs()(Python)单独下载。
前置条件
- 添加
odps-sdk-storage-api模块依赖 - 已初始化
MaxStorageClient - 目标表包含
BLOB类型列 - SDK 版本 >= 0.54.0
完整示例
- Java
- Python
import com.aliyun.odps.storage.api.MaxStorageClient;
import com.aliyun.odps.storage.api.TableIdentifier;
import com.aliyun.odps.storage.api.blob.Blob;
import com.aliyun.odps.storage.api.blob.BlobManager;
import com.aliyun.odps.storage.api.blob.BlobDataIterator;
import com.aliyun.odps.storage.api.read.TableReadSession;
import com.aliyun.odps.storage.api.read.InputSplit;
import com.aliyun.odps.data.Record;
import com.aliyun.odps.data.RecordReader;
import org.apache.arrow.vector.ipc.ArrowReader;
import java.nio.file.Files;
import com.aliyun.odps.storage.internal.io.BlobDataStream;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
public class BlobDownloadExample {
public static void main(String[] args) throws Exception {
// 1. 创建客户端
MaxStorageClient client = MaxStorageClient.builder()
.endpoint("https://service.cn-hangzhou.maxcompute.aliyun.com/api")
.credentialsProvider(credentialsProvider)
.build();
// 2. 读取包含 Blob 列的表
TableIdentifier tableId = TableIdentifier.of("my_project", "image_table");
TableReadSession session = client.createTableReadSessionBuilder(tableId)
.withColumns(Arrays.asList("id", "image_data"))
.build();
// 3. 获取 BlobManager
BlobManager blobManager = client.openBlobManager();
// 4. 读取表数据并收集 Blob 引用
for (InputSplit split : session.getSplits()) {
ArrowReader arrowReader = session.createReaderBuilder(split).build();
RecordReader recordReader = arrowReader.getAsRecordReader();
List<Blob> blobs = new ArrayList<>();
List<Long> ids = new ArrayList<>();
recordReader.forEach(record -> {
Blob blob = (Blob) record.get("image_data");
if (blob != null) {
blobs.add(blob);
ids.add((Long) record.get("id"));
}
});
// 5. 批量下载 Blob 数据
try (BlobDataIterator iterator = blobManager.batchDownload(blobs)) {
int index = 0;
while (iterator.hasNext()) {
try (BlobDataStream data = iterator.next()) {
byte[] content = data.readAllBytes();
String mimeType = data.getMimeType();
// 保存到本地文件
Path outputPath = Paths.get("/tmp/images/" + ids.get(index) + ".jpg");
Files.write(outputPath, content);
System.out.println("已下载: " + outputPath + " (" + content.length + " bytes, mime=" + mimeType + ")");
}
index++;
}
}
arrowReader.close();
recordReader.close();
}
}
}