IBM Cloud Docs
如何使用附件

如何使用附件

存储数据的另一种方法是使用附件。 附件是二进制大对象 (BLOB) 文档中包含的文件。

最好保持附件的大小和数量较小,因为附件会影响性能。

BLOB 存储在文档的 _attachments 组件中。 BLOB 保存包含以下信息的数据:

  • 附件名称
  • 附件的类型
  • 实际内容

BLOB 的示例将是图像和多媒体。

如果将附件作为整体 JSON 的 内联 组件包含,那么将使用 BASE64 表单来表示附件内容。

内容类型对应于 MIME 类型。 例如,如果要将 .jpg 图像文件附加到文档,请将附件 MIME 类型指定为 image/jpeg

不允许在 _replicator_users 数据库中的文档上使用附件。

创建或更新

要在创建新文档的同时创建新附件,请将附件作为 JSON 内容的 内联 组件包含在内。

要在现有文档上创建新附件,或更新文档上的附件,请使用文档的最新 _revhttps://$ACCOUNT.cloudant.com/$DATABASE/$DOCUMENT_ID/$ATTACHMENT发出 PUT 请求。 必须使用 Content-Type 头来指定附件的 内容类型$ATTACHMENT 值是与文档关联的附件的名称。

通过确保每个附件的 $ATTACHMENT 值在文档中是唯一的,可以为文档创建多个附件。

请参阅以下示例以使用 HTTP 创建或更新附件:

PUT /$DATABASE/$DOCUMENT_ID/$ATTACHMENT?rev=$REV HTTP/1.1
Content-Type: $$ATTACHMENT_MIME_TYPE

请参阅以下示例以创建或更新附件:

curl -H "Authorization: Bearer $API_BEARER_TOKEN" -X PUT "$SERVICE_URL/products/small-appliances:100001/product_details.txt" -H "Content-Type: text/plain" --data 'This appliance includes...'
import com.ibm.cloud.cloudant.v1.Cloudant;
import com.ibm.cloud.cloudant.v1.model.DocumentResult;
import com.ibm.cloud.cloudant.v1.model.PutAttachmentOptions;

import java.io.ByteArrayInputStream;
import java.io.InputStream;
import java.nio.charset.StandardCharsets;

Cloudant service = Cloudant.newInstance();

String detailedDescription = "This appliance includes...";

InputStream detailedDescriptionStream =
    new ByteArrayInputStream(detailedDescription
        .getBytes(StandardCharsets.UTF_8));

PutAttachmentOptions attachmentOptions =
    new PutAttachmentOptions.Builder()
        .db("products")
        .docId("small-appliances:100001")
        .attachmentName("product_details.txt")
        .attachment(detailedDescriptionStream)
        .contentType("text/plain")
        .build();

DocumentResult response =
    service.putAttachment(attachmentOptions).execute()
        .getResult();

System.out.println(response);
const { CloudantV1 } = require('@ibm-cloud/cloudant');

const service = CloudantV1.newInstance({});

const stream = new Readable();
stream.push('This appliance includes...');
stream.push(null);

service.putAttachment({
  db: 'products',
  docId: 'small-appliances:100001',
  attachmentName: 'product_details.txt',
  attachment: stream,
  contentType: 'text/plain'
}).then(response => {
  console.log(response.result);
});
from ibmcloudant.cloudant_v1 import CloudantV1

service = CloudantV1.new_instance()

detailed_description = "This appliance includes..."
response = service.put_attachment(
  db='products',
  doc_id='small-appliances:100001',
  attachment_name='product_details.txt',
  attachment=detailed_description,
  content_type='text/plain'
).get_result()

print(response)
putAttachmentOptions := service.NewPutAttachmentOptions(
  "products",
  "small-appliances:100001",
  "product_details.txt",
  ioutil.NopCloser(
    bytes.NewReader([]byte("This appliance includes...")),
  ),
  "text/plain",
)

documentResult, response, err := service.PutAttachment(putAttachmentOptions)
if err != nil {
  panic(err)
}

b, _ := json.MarshalIndent(documentResult, "", "  ")
fmt.Println(string(b))

先前的 Go 示例需要以下导入块:

import (
   "encoding/json"
   "fmt"
   "io/ioutil"
   "github.com/IBM/cloudant-go-sdk/cloudantv1"
)

所有 Go 示例都需要初始化 service 对象。 有关更多信息,请参阅 API 文档 "认证" 部分 以获取示例。

响应包含文档标识和新文档修订版。

附件没有自己的修订版。 相反,当您更新或创建附件时,它附加到更改的文档的修订版。

请参阅包含文档标识和新修订版的以下示例响应:

{
	"id" : "FishStew",
	"ok" : true,
	"rev" : "9-247bb19a41bfd9bfdaf5ee6e2e05be74"
}

读取

要检索附件,请向 https://$ACCOUNT.cloudant.com/$DATABASE/$DOCUMENT_ID/$ATTACHMENT发出 GET 请求。 响应的主体是附件的原始内容。

请参阅以下使用 HTTP 读取附件的示例:

GET /$DATABASE/$DOCUMENT_ID/$ATTACHMENT HTTP/1.1

请参阅以下读取附件的示例:

curl -H "Authorization: Bearer $API_BEARER_TOKEN" -X GET "$SERVICE_URL/products/small-appliances:100001/product_details.txt"
import com.ibm.cloud.cloudant.v1.Cloudant;
import com.ibm.cloud.cloudant.v1.model.GetAttachmentOptions;

import java.io.BufferedReader;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.util.stream.Collectors;

Cloudant service = Cloudant.newInstance();

GetAttachmentOptions attachmentOptions =
    new GetAttachmentOptions.Builder()
        .db("products")
        .docId("small-appliances:100001")
        .attachmentName("product_details.txt")
        .build();

InputStream streamResult =
    service.getAttachment(attachmentOptions).execute()
        .getResult();

String response =
    new BufferedReader(new InputStreamReader(streamResult))
        .lines().collect(Collectors.joining("\n"));

System.out.println(response);
const { CloudantV1 } = require('@ibm-cloud/cloudant');

const service = CloudantV1.newInstance({});

service.getAttachment({
  db: 'products',
  docId: 'small-appliances:100001',
  attachmentName: 'product_details.txt'
}).then(response => {
  let attachment = response.result as Readable;
  attachment.pipe(process.stdout);
});
from ibmcloudant.cloudant_v1 import CloudantV1

service = CloudantV1.new_instance()

response_attachment = service.get_attachment(
  db='products',
  doc_id='small-appliances:100001',
  attachment_name='product_details.txt'
).get_result().content

print(response_attachment)
getAttachmentOptions := service.NewGetAttachmentOptions(
  "products",
  "small-appliances:100001",
  "product_details.txt",
)

result, response, err := service.GetAttachment(getAttachmentOptions)
if err != nil {
  panic(err)
}

data, _ := ioutil.ReadAll(result)
fmt.Println("\n", string(data))

先前的 Go 示例需要以下导入块:

import (
   "fmt"
   "io/ioutil"
   "github.com/IBM/cloudant-go-sdk/cloudantv1"
)

所有 Go 示例都需要初始化 service 对象。 有关更多信息,请参阅 API 文档的 认证部分 以获取示例。

删除附件

要删除附件,请使用文档的最新 _rev 发出 DELETE 请求 到 https://$ACCOUNT.cloudant.com/$DATABASE/$DOCUMENT_ID/$ATTACHMENT。 如果未提供最新的 _rev,那么响应为 409 错误

请参阅以下使用 HTTP 删除附件的示例:

DELETE /$DATABASE/$DOCUMENT_ID/$ATTACHMENT?rev=$REV HTTP/1.1

请参阅以下删除附件的示例:

curl -H "Authorization: Bearer $API_BEARER_TOKEN" -X DELETE "$SERVICE_URL/products/small-appliances:100001/product_details.txt?rev=4-1a0d1cd6f40472509e9aac646183736a"
import com.ibm.cloud.cloudant.v1.Cloudant;
import com.ibm.cloud.cloudant.v1.model.DeleteAttachmentOptions;
import com.ibm.cloud.cloudant.v1.model.DocumentResult;

Cloudant service = Cloudant.newInstance();

DeleteAttachmentOptions attachmentOptions =
    new DeleteAttachmentOptions.Builder()
        .db("products")
        .docId("small-appliances:100001")
        .attachmentName("product_details.txt")
        .rev("4-1a0d1cd6f40472509e9aac646183736a")
        .build();

DocumentResult response =
    service.deleteAttachment(attachmentOptions).execute()
        .getResult();

System.out.println(response);
const { CloudantV1 } = require('@ibm-cloud/cloudant');

const service = CloudantV1.newInstance({});

service.deleteAttachment({
  db: 'products',
  docId: 'small-appliances:100001',
  attachmentName: 'product_details.txt',
  rev: '4-1a0d1cd6f40472509e9aac646183736a'
}).then(response => {
  console.log(response.result);
});
from ibmcloudant.cloudant_v1 import CloudantV1

service = CloudantV1.new_instance()

response = service.delete_attachment(
  db='products',
  doc_id='small-appliances:100001',
  attachment_name='product_details.txt',
  rev='4-1a0d1cd6f40472509e9aac646183736a'
).get_result()

print(response)
deleteAttachmentOptions := service.NewDeleteAttachmentOptions(
  "products",
  "small-appliances:100001",
  "product_details.txt",
)
deleteAttachmentOptions.SetRev("4-1a0d1cd6f40472509e9aac646183736a")

documentResult, response, err := service.DeleteAttachment(deleteAttachmentOptions)
if err != nil {
  panic(err)
}

b, _ := json.MarshalIndent(documentResult, "", "  ")
fmt.Println(string(b))

先前的 Go 示例需要以下导入块:

import (
   "encoding/json"
   "fmt"
   "github.com/IBM/cloudant-go-sdk/cloudantv1"
)

所有 Go 示例都需要初始化 service 对象。 有关更多信息,请参阅 API 文档的 认证部分 以获取示例。

如果删除成功,那么响应将包含 "ok": true以及文档的标识和新修订版。

成功删除附件后,请参阅以下示例响应:

{
	"ok": true,
	"id": "DocID",
	"rev": "3-aedfb06537c1d77a087eb295571f7fc9"
}

内联

内联附件是包含在 JSON 内容中的附件。 必须使用 BASE64 表示来提供内容,如示例中所示。

media types 文章中提供了介质类型的完整列表。

请参阅以下示例 JSON 文档,其中包含 jpeg 图像的内联附件:

{
	"_id":"document_with_attachment",
	"_attachments":
	{
		"name_of_attachment": {
			"content_type":"image/jpeg",
			"data": "iVBORw0KGgoAA... ...AASUVORK5CYII="
		}
	}
}

性能注意事项

虽然文档附件很有用,但它们确实会影响应用程序性能。 尤其是,具有过多的附件会在复制期间产生不利的性能影响。

例如,如果应用程序需要将多个映像作为附件进行存储,或者包含大型映像,那么必须使用备用 BLOB 存储机制来存储这些映像。 然后,您可以使用 IBM Cloudant 来保留图像元数据,例如指向 BLOB 商店的 URL。

您可能会发现,对特定应用程序执行性能测试以确定哪种方法最适合您的情况是很有用的。