如何用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
相关产品推荐
相关产品推荐

