You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何用Java REST API在CouchDB创建附件?含迁移技术咨询

在Java中实现CouchDB(含Azure CouchDB)附件存储(从Cloudant迁移视角)

Hey there! 既然你们正从Cloudant迁移到Azure上的CouchDB,刚好Cloudant的Java客户端本身就兼容标准CouchDB的API,所以大部分代码调整起来不会太麻烦。下面我就一步步讲怎么实现附件存储,涉及的API、示例代码和注意事项都给你列清楚。

一、核心依赖与API说明

你们已经在用的com.cloudant.client.api.Database和com.cloudant.client.api.model.Response就是核心操作类,CouchDB的附件操作主要靠这个客户端库完成,关键API包括:

  • Database.save():保存带附件的新文档,或更新已有文档的附件
  • Database.getAttachment():获取指定文档的附件流
  • Database.deleteAttachment():删除文档指定的附件
  • Database.find():查询目标文档(更新/删除附件时必须获取最新版本号,避免冲突)

二、完整示例代码

1. 初始化客户端(适配Azure CouchDB)

Azure CouchDB的连接配置和Cloudant逻辑一致,只需要替换为你的实例信息:

import com.cloudant.client.api.ClientBuilder;
import com.cloudant.client.api.CloudantClient;
import com.cloudant.client.api.Database;
import java.net.MalformedURLException;
import java.net.URL;

public class CouchDBAttachmentHandler {
    public static void main(String[] args) throws MalformedURLException {
        // Azure CouchDB实例信息
        String couchDbUrl = "https://your-azure-couchdb-instance.azurewebsites.net";
        String username = "your-couchdb-username";
        String password = "your-couchdb-password";

        // 初始化客户端
        CloudantClient client = ClientBuilder.url(new URL(couchDbUrl))
                .username(username)
                .password(password)
                .build();

        // 获取目标数据库(第二个参数false表示不存在则不创建)
        Database db = client.database("your-target-db", false);
    }
}

2. 上传附件到新文档

import com.cloudant.client.api.model.Response;
import com.cloudant.client.api.model.Attachment;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.util.Collections;
import java.util.HashMap;

// 上传附件到新创建的文档
public static Response uploadAttachmentToNewDoc(Database db) throws IOException {
    // 1. 创建基础文档(可以用自定义POJO,也可以用HashMap灵活存储)
    HashMap<String, Object> baseDoc = new HashMap<>();
    baseDoc.put("docType", "attachment-file");
    baseDoc.put("description", "示例PDF文件");

    // 2. 读取本地文件生成Attachment对象
    File localFile = new File("/path/to/your/example.pdf");
    Attachment pdfAttachment = new Attachment.Builder("example.pdf", "application/pdf")
            .inputStream(new FileInputStream(localFile))
            .build();

    // 3. 将附件绑定到文档的_attachments字段
    baseDoc.put("_attachments", Collections.singletonMap(pdfAttachment.getName(), pdfAttachment));

    // 4. 保存文档到数据库
    return db.save(baseDoc);
}

3. 给已有文档添加/更新附件

更新附件必须先获取文档的最新_rev版本号,否则会触发冲突异常:

import com.cloudant.client.api.model.Response;
import com.cloudant.client.api.model.Attachment;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.util.HashMap;
import java.util.Map;

// 给已有文档添加或更新附件
public static Response updateAttachmentOnExistingDoc(Database db, String targetDocId) throws IOException {
    // 1. 获取文档的最新版本(包含_rev字段)
    HashMap<String, Object> existingDoc = db.find(HashMap.class, targetDocId);

    // 2. 创建新的Attachment对象(同名会直接覆盖旧附件)
    File updatedFile = new File("/path/to/your/updated-example.pdf");
    Attachment updatedAttachment = new Attachment.Builder("example.pdf", "application/pdf")
            .inputStream(new FileInputStream(updatedFile))
            .build();

    // 3. 更新文档的附件集合
    Map<String, Attachment> attachments = existingDoc.containsKey("_attachments")
            ? (Map<String, Attachment>) existingDoc.get("_attachments")
            : new HashMap<>();
    attachments.put(updatedAttachment.getName(), updatedAttachment);
    existingDoc.put("_attachments", attachments);

    // 4. 保存更新后的文档
    return db.save(existingDoc);
}

4. 下载附件

import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;

// 下载指定文档的附件到本地
public static void downloadAttachment(Database db, String docId, String attachmentName) throws IOException {
    // 获取附件的输入流
    InputStream attachmentStream = db.getAttachment(docId, attachmentName);

    // 将流写入本地文件
    try (FileOutputStream outputStream = new FileOutputStream("/path/to/save/downloaded-file.pdf")) {
        byte[] buffer = new byte[1024];
        int bytesRead;
        while ((bytesRead = attachmentStream.read(buffer)) != -1) {
            outputStream.write(buffer, 0, bytesRead);
        }
    }
}

5. 删除附件

import com.cloudant.client.api.model.Response;
import java.io.IOException;
import java.util.HashMap;

// 删除指定文档的附件
public static Response deleteAttachment(Database db, String docId) throws IOException {
    // 获取文档最新版本的_rev
    HashMap<String, Object> targetDoc = db.find(HashMap.class, docId);
    String latestRev = targetDoc.get("_rev").toString();

    // 删除名为example.pdf的附件
    return db.deleteAttachment(docId, "example.pdf", latestRev);
}

三、迁移注意事项(Cloudant → Azure CouchDB)

  • API兼容性:Cloudant Java客户端完全兼容标准CouchDB,所以大部分代码无需重写,仅需替换连接配置(URL、用户名、密码)
  • 附件大小限制:Azure CouchDB默认和标准CouchDB一致,单个附件建议不超过10MB,大文件建议分块或搭配外部存储
  • 权限配置:确保Azure CouchDB的账号拥有目标数据库的读写权限,附件操作依赖基础文档权限
  • 冲突处理:更新/删除附件时必须获取最新_rev,这一点和Cloudant的冲突机制完全一致

内容的提问来源于stack exchange,提问作者user680702

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.28 09:55:46