你当前正在访问 Microsoft Azure Global Edition 技术文档网站。 如果需要访问由世纪互联运营的 Microsoft Azure 中国技术文档网站,请访问 https://docs.azure.cn。
适用于 Java 的 Azure 存储 Blob 客户端库 - 版本 12.24.1
Azure Blob 存储是 Microsoft 提供的适用于云的对象存储解决方案。 Blob 存储最适合存储巨量的非结构化数据。 非结构化数据是不遵循特定数据模型或定义(如文本或二进制数据)的数据。
源代码 | API 参考文档 | REST API 文档 | 产品文档 | 样品
入门
先决条件
添加包
包括 BOM 文件
请将 azure-sdk-bom 包含在项目中,以依赖于库的 GA 版本。 在以下代码段中,将 {bom_version_to_target} 占位符替换为版本号。 若要详细了解 BOM,请参阅 AZURE SDK BOM 自述文件。
<dependencyManagement>
<dependencies>
<dependency>
<groupId>com.azure</groupId>
<artifactId>azure-sdk-bom</artifactId>
<version>{bom_version_to_target}</version>
<type>pom</type>
<scope>import</scope>
</dependency>
</dependencies>
</dependencyManagement>
然后在没有版本标记的依赖项部分中包含直接依赖项。
<dependencies>
<dependency>
<groupId>com.azure</groupId>
<artifactId>azure-storage-blob</artifactId>
</dependency>
</dependencies>
包括直接依赖项
如果要依赖于 BOM 中不存在的特定版本的库,请将直接依赖项添加到项目中,如下所示。
<dependency>
<groupId>com.azure</groupId>
<artifactId>azure-storage-blob</artifactId>
<version>12.24.1</version>
</dependency>
创建存储帐户
若要创建存储帐户,可以使用 Azure 门户 或 Azure CLI。
az storage account create \
--resource-group <resource-group-name> \
--name <storage-account-name> \
--location <location>
存储帐户 URL(后来标识为 <your-storage-account-url>
)的格式如下: http(s)://<storage-account-name>.blob.core.windows.net
验证客户端
若要与存储服务 (Blob、队列、消息、MessageId、File) 进行交互,需要创建服务客户端类的实例。 为此,需要存储帐户的帐户 SAS (共享访问签名) 字符串。 有关详细信息,请参阅 SAS 令牌。
获取凭据
SAS 令牌
a. 使用以下 Azure CLI 代码片段从存储帐户获取 SAS 令牌。
az storage blob generate-sas \
--account-name {Storage Account name} \
--container-name {container name} \
--name {blob name} \
--permissions {permissions to grant} \
--expiry {datetime to expire the SAS token} \
--services {storage services the SAS allows} \
--resource-types {resource types the SAS allows}
例如:
CONNECTION_STRING=<connection-string>
az storage blob generate-sas \
--account-name MyStorageAccount \
--container-name MyContainer \
--name MyBlob \
--permissions racdw \
--expiry 2020-06-15
b. 或者,从 Azure 门户获取帐户 SAS 令牌。
- 转到存储帐户
Shared access signature
从左侧菜单中选择- 在设置) 后单击
Generate SAS and connection string
“ (”
共享密钥凭据
a. 使用“帐户名称”和“帐户密钥”。 帐户名称是存储帐户名称。
- 转到存储帐户
Access keys
从左侧菜单中选择- 在下
key1
/key2
复制字段的内容Key
或
b. 使用连接字符串。
- 转到存储帐户
Access keys
从左侧菜单中选择- 在下
key1
/key2
复制字段的内容Connection string
关键概念
Blob 存储用于:
- 直接向浏览器提供图像或文档
- 存储文件以供分布式访问
- 对视频和音频进行流式处理
- 写入日志文件
- 存储用于备份和还原、灾难恢复及存档的数据
- 存储数据以供本地或 Azure 托管服务执行分析
URL 格式
Blob 可使用以下 URL 格式进行寻址:以下 URL 用于寻址 blob:
https://myaccount.blob.core.windows.net/mycontainer/myblob
资源 URI 语法
对于存储帐户,Blob 操作的基 URI 仅包括帐户的名称:
https://myaccount.blob.core.windows.net
对于容器,基本 URI 包含帐户名称和容器名称:
https://myaccount.blob.core.windows.net/mycontainer
对于 Blob,基 URI 包括帐户名称、容器名称和 Blob 的名称:
https://myaccount.blob.core.windows.net/mycontainer/myblob
请注意,上述 URI 可能不适用于更高级的方案,例如自定义域名。
示例
以下部分提供了几个代码片段,涵盖了一些最常见的 Azure 存储 Blob 任务,包括:
- 创建
BlobServiceClient
- 创建
BlobContainerClient
- 创建
BlobClient
- 创建容器
- 将数据上传到 Blob
- 从流上传 Blob
- 从本地路径上传 Blob
- 上传 Blob(如果尚不存在)
- 上传 Blob 并覆盖(如果已存在)
- 通过 上传 Blob
OutputStream
- 从 Blob 下载数据
- 将 Blob 下载到流
- 将 Blob 下载到本地路径
- 通过 读取 blob
InputStream
- 枚举 Blob
- 复制 Blob
- 生成 SAS 令牌
- 使用 Azure 标识进行身份验证
- 生成客户端时设置代理
创建 BlobServiceClient
BlobServiceClient
使用sasToken
上面生成的 创建 。
BlobServiceClient blobServiceClient = new BlobServiceClientBuilder()
.endpoint("<your-storage-account-url>")
.sasToken("<your-sasToken>")
.buildClient();
或
// Only one "?" is needed here. If the SAS token starts with "?", please removing one "?".
BlobServiceClient blobServiceClient = new BlobServiceClientBuilder()
.endpoint("<your-storage-account-url>" + "?" + "<your-sasToken>")
.buildClient();
创建 BlobContainerClient
BlobContainerClient
使用 BlobServiceClient
创建 。
BlobContainerClient blobContainerClient = blobServiceClient.getBlobContainerClient("mycontainer");
BlobContainerClient
从上面生成的生成器sasToken
创建 。
BlobContainerClient blobContainerClient = new BlobContainerClientBuilder()
.endpoint("<your-storage-account-url>")
.sasToken("<your-sasToken>")
.containerName("mycontainer")
.buildClient();
或
// Only one "?" is needed here. If the SAS token starts with "?", please removing one "?".
BlobContainerClient blobContainerClient = new BlobContainerClientBuilder()
.endpoint("<your-storage-account-url>" + "/" + "mycontainer" + "?" + "<your-sasToken>")
.buildClient();
创建 BlobClient
BlobClient
使用 BlobContainerClient
创建 。
BlobClient blobClient = blobContainerClient.getBlobClient("myblob");
或
BlobClient
从上面生成的生成器sasToken
创建 。
BlobClient blobClient = new BlobClientBuilder()
.endpoint("<your-storage-account-url>")
.sasToken("<your-sasToken>")
.containerName("mycontainer")
.blobName("myblob")
.buildClient();
或
// Only one "?" is needed here. If the SAS token starts with "?", please removing one "?".
BlobClient blobClient = new BlobClientBuilder()
.endpoint("<your-storage-account-url>" + "/" + "mycontainer" + "/" + "myblob" + "?" + "<your-sasToken>")
.buildClient();
创建容器
使用 BlobServiceClient
创建容器。
blobServiceClient.createBlobContainer("mycontainer");
或
使用 BlobContainerClient
创建容器。
blobContainerClient.create();
将数据上传到 Blob
使用BlobClient
从 BlobContainerClient
生成的 上传到 BinaryData
Blob。
BlobClient blobClient = blobContainerClient.getBlobClient("myblockblob");
String dataSample = "samples";
blobClient.upload(BinaryData.fromString(dataSample));
从流上传 Blob
使用BlockBlobClient
从 InputStream
生成的 BlobContainerClient
从 上传到 Blob。
BlockBlobClient blockBlobClient = blobContainerClient.getBlobClient("myblockblob").getBlockBlobClient();
String dataSample = "samples";
try (ByteArrayInputStream dataStream = new ByteArrayInputStream(dataSample.getBytes())) {
blockBlobClient.upload(dataStream, dataSample.length());
} catch (IOException e) {
e.printStackTrace();
}
从本地路径上传 Blob
使用 BlobClient
从 BlobContainerClient
生成的 将文件上传到 Blob。
BlobClient blobClient = blobContainerClient.getBlobClient("myblockblob");
blobClient.uploadFromFile("local-file.jpg");
上传 Blob(如果尚不存在)
将数据上传到 Blob,如果 Blob 已存在,则失败。
/*
* Rather than use an if block conditioned on an exists call, there are three ways to upload-if-not-exists using
* one network call instead of two. Equivalent options are present on all upload methods.
*/
// 1. The minimal upload method defaults to no overwriting
String dataSample = "samples";
try (ByteArrayInputStream dataStream = new ByteArrayInputStream(dataSample.getBytes())) {
blobClient.upload(dataStream, dataSample.length());
} catch (IOException e) {
e.printStackTrace();
}
// 2. The overwrite flag can explicitly be set to false to make intention clear
try (ByteArrayInputStream dataStream = new ByteArrayInputStream(dataSample.getBytes())) {
blobClient.upload(dataStream, dataSample.length(), false /* overwrite */);
} catch (IOException e) {
e.printStackTrace();
}
// 3. If the max overload is needed, access conditions must be used to prevent overwriting
try (ByteArrayInputStream dataStream = new ByteArrayInputStream(dataSample.getBytes())) {
BlobParallelUploadOptions options =
new BlobParallelUploadOptions(dataStream, dataSample.length());
// Setting IfNoneMatch="*" ensures the upload will fail if there is already a blob at the destination.
options.setRequestConditions(new BlobRequestConditions().setIfNoneMatch("*"));
blobClient.uploadWithResponse(options, null, Context.NONE);
} catch (IOException e) {
e.printStackTrace();
}
上传 Blob 并覆盖(如果已存在)
将数据上传到 Blob 并覆盖目标上的任何现有数据。
/*
* Rather than use an if block conditioned on an exists call, there are three ways to upload-if-exists in one
* network call instead of two. Equivalent options are present on all upload methods.
*/
String dataSample = "samples";
// 1. The overwrite flag can explicitly be set to true. This will succeed as a create and overwrite.
try (ByteArrayInputStream dataStream = new ByteArrayInputStream(dataSample.getBytes())) {
blobClient.upload(dataStream, dataSample.length(), true /* overwrite */);
} catch (IOException e) {
e.printStackTrace();
}
/*
* 2. If the max overload is needed and no access conditions are passed, the upload will succeed as both a
* create and overwrite.
*/
try (ByteArrayInputStream dataStream = new ByteArrayInputStream(dataSample.getBytes())) {
BlobParallelUploadOptions options =
new BlobParallelUploadOptions(dataStream, dataSample.length());
blobClient.uploadWithResponse(options, null, Context.NONE);
} catch (IOException e) {
e.printStackTrace();
}
/*
* 3. If the max overload is needed, access conditions may be used to assert that the upload is an overwrite and
* not simply a create.
*/
try (ByteArrayInputStream dataStream = new ByteArrayInputStream(dataSample.getBytes())) {
BlobParallelUploadOptions options =
new BlobParallelUploadOptions(dataStream, dataSample.length());
// Setting IfMatch="*" ensures the upload will succeed only if there is already a blob at the destination.
options.setRequestConditions(new BlobRequestConditions().setIfMatch("*"));
blobClient.uploadWithResponse(options, null, Context.NONE);
} catch (IOException e) {
e.printStackTrace();
}
通过 上传 Blob OutputStream
通过打开 BlobOutputStream
并通过标准流 API 向 Blob 写入来上传 Blob。
/*
* Opening a blob input stream allows you to write to a blob through a normal stream interface. It will not be
* committed until the stream is closed.
* This option is convenient when the length of the data is unknown.
* This can only be done for block blobs. If the target blob already exists as another type of blob, it will
* fail.
*/
try (BlobOutputStream blobOS = blobClient.getBlockBlobClient().getBlobOutputStream()) {
blobOS.write(new byte[0]);
} catch (IOException e) {
e.printStackTrace();
}
从 Blob 下载数据
使用 将 Blob 下载到 OutputStream
。BlobClient
BinaryData content = blobClient.downloadContent();
将 Blob 下载到流
使用 将 Blob 下载到 OutputStream
。BlobClient
try (ByteArrayOutputStream outputStream = new ByteArrayOutputStream()) {
blobClient.downloadStream(outputStream);
} catch (IOException e) {
e.printStackTrace();
}
将 Blob 下载到本地路径
使用 BlobClient
将 Blob 下载到本地文件。
blobClient.downloadToFile("downloaded-file.jpg");
通过 读取 blob InputStream
通过打开 BlobInputStream
并通过标准流 API 从中读取来下载 Blob。
/*
* Opening a blob input stream allows you to read from a blob through a normal stream interface. It is also
* mark-able.
*/
try (BlobInputStream blobIS = blobClient.openInputStream()) {
blobIS.read();
} catch (IOException e) {
e.printStackTrace();
}
枚举 Blob
使用 BlobContainerClient
枚举所有 blob。
for (BlobItem blobItem : blobContainerClient.listBlobs()) {
System.out.println("This is the blob name: " + blobItem.getName());
}
或
枚举所有 Blob 并创建指向项的新客户端。
for (BlobItem blobItem : blobContainerClient.listBlobs()) {
BlobClient blobClient;
if (blobItem.getSnapshot() != null) {
blobClient = blobContainerClient.getBlobClient(blobItem.getName(), blobItem.getSnapshot());
} else {
blobClient = blobContainerClient.getBlobClient(blobItem.getName());
}
System.out.println("This is the new blob uri: " + blobClient.getBlobUrl());
}
复制 Blob
复制 Blob。 有关复制源及其身份验证要求的详细信息,请参阅其中每种方法的 javadocs。
SyncPoller<BlobCopyInfo, Void> poller = blobClient.beginCopy("<url-to-blob>", Duration.ofSeconds(1));
poller.waitForCompletion();
或
blobClient.copyFromUrl("url-to-blob");
生成 SAS 令牌
使用客户端实例生成新的 SAS 令牌。
/*
* Generate an account sas. Other samples in this file will demonstrate how to create a client with the sas
* token.
*/
// Configure the sas parameters. This is the minimal set.
OffsetDateTime expiryTime = OffsetDateTime.now().plusDays(1);
AccountSasPermission accountSasPermission = new AccountSasPermission().setReadPermission(true);
AccountSasService services = new AccountSasService().setBlobAccess(true);
AccountSasResourceType resourceTypes = new AccountSasResourceType().setObject(true);
// Generate the account sas.
AccountSasSignatureValues accountSasValues =
new AccountSasSignatureValues(expiryTime, accountSasPermission, services, resourceTypes);
String sasToken = blobServiceClient.generateAccountSas(accountSasValues);
// Generate a sas using a container client
BlobContainerSasPermission containerSasPermission = new BlobContainerSasPermission().setCreatePermission(true);
BlobServiceSasSignatureValues serviceSasValues =
new BlobServiceSasSignatureValues(expiryTime, containerSasPermission);
blobContainerClient.generateSas(serviceSasValues);
// Generate a sas using a blob client
BlobSasPermission blobSasPermission = new BlobSasPermission().setReadPermission(true);
serviceSasValues = new BlobServiceSasSignatureValues(expiryTime, blobSasPermission);
blobClient.generateSas(serviceSasValues);
使用 Azure 标识进行身份验证
Azure 标识库为使用 Azure 存储进行身份验证提供 Azure Active Directory 支持。
BlobServiceClient blobStorageClient = new BlobServiceClientBuilder()
.endpoint("<your-storage-account-url>")
.credential(new DefaultAzureCredentialBuilder().build())
.buildClient();
生成客户端时设置代理
ProxyOptions options = new ProxyOptions(ProxyOptions.Type.HTTP, new InetSocketAddress("localhost", 888));
BlobServiceClient client = new BlobServiceClientBuilder()
.httpClient(new NettyAsyncHttpClientBuilder().proxy(options).build())
.buildClient();
或
允许客户端生成器确定要使用的类型, HttpClient
但使用传递的配置构造它。
HttpClientOptions clientOptions = new HttpClientOptions()
.setProxyOptions(new ProxyOptions(ProxyOptions.Type.HTTP, new InetSocketAddress("localhost", 888)));
BlobServiceClient client = new BlobServiceClientBuilder()
.clientOptions(clientOptions)
.buildClient();
疑难解答
使用此 Java 客户端库与 Blob 交互时,服务返回的错误对应于为 REST API 请求返回的相同 HTTP 状态代码。 例如,如果尝试检索存储帐户中不存在的容器或 Blob,则会返回错误 404
,指示 Not Found
。
默认的 HTTP 客户端
默认情况下,所有客户端库都使用 Netty HTTP 客户端。 添加上述依赖项会自动将客户端库配置为使用 Netty HTTP 客户端。 HTTP 客户端 Wiki 中详述了如何配置或更改 HTTP 客户端。
默认 SSL 库
默认情况下,所有客户端库均使用 Tomcat 原生 Boring SSL 库来为 SSL 操作启用原生级别性能。 Boring SSL 库是一个 uber jar,其中包含适用于 Linux/macOS/Windows 的原生库。与 JDK 内的默认 SSL 实现相比,它提供更好的性能。 有关详细信息(包括如何减小依赖项大小),请参阅 Wiki 的性能优化部分。
后续步骤
SDK 的 GitHub 存储库中提供了多个存储 Blob Java SDK 示例。 这些示例提供了使用 密钥保管库 时经常遇到的其他方案的示例代码:
后续步骤示例
此处详细介绍了示例。
贡献
本项目欢迎贡献和建议。 大多数贡献要求你同意贡献者许可协议 (CLA),并声明你有权(并且确实有权)授予我们使用你的贡献的权利。
提交拉取请求时,CLA 机器人将自动确定你是否需要提供 CLA,并相应地修饰 PR(例如标签、注释)。 直接按机器人提供的说明操作。 只需使用 CLA 对所有存储库执行一次这样的操作。
此项目采用了 Microsoft 开放源代码行为准则。 有关详细信息,请参阅行为准则常见问题解答,或如果有任何其他问题或意见,请与 联系。