你当前正在访问 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 令牌。

  1. 转到存储帐户
  2. Shared access signature从左侧菜单中选择
  3. 在设置) 后单击 Generate SAS and connection string “ (”
共享密钥凭据

a. 使用“帐户名称”和“帐户密钥”。 帐户名称是存储帐户名称。

  1. 转到存储帐户
  2. Access keys从左侧菜单中选择
  3. 在下key1/key2复制字段的内容Key

b. 使用连接字符串。

  1. 转到存储帐户
  2. Access keys从左侧菜单中选择
  3. 在下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

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

使用BlobClientBlobContainerClient生成的 上传到 BinaryData Blob。

BlobClient blobClient = blobContainerClient.getBlobClient("myblockblob");
String dataSample = "samples";
blobClient.upload(BinaryData.fromString(dataSample));

从流上传 Blob

使用BlockBlobClientInputStream 生成的 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

使用 BlobClientBlobContainerClient生成的 将文件上传到 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 下载到 OutputStreamBlobClient

BinaryData content = blobClient.downloadContent();

将 Blob 下载到流

使用 将 Blob 下载到 OutputStreamBlobClient

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 开放源代码行为准则。 有关详细信息,请参阅行为准则常见问题解答,或如果有任何其他问题或意见,请与 联系。

曝光数