如何通过Salesforce Apex向IBM Watson上传文档及示例需求
我来帮你搞定这几个需求,结合实际项目中Salesforce和IBM Watson集成的经验,直接上可落地的代码和说明:
1. AddDocumentOptionsBuilder Apex类使用示例
这个类主要用来构建Watson文档上传的参数集合,帮你规范传递文件内容、元数据、集合ID等信息,直接看代码示例(注释已经标清楚关键逻辑):
// 初始化Builder实例 AddDocumentOptionsBuilder docBuilder = new AddDocumentOptionsBuilder(); // 设置目标Watson集合ID(从你的集成配置里获取对应值) docBuilder.setCollectionId('your-watson-collection-id'); // 从Salesforce读取文件内容(这里以ContentVersion为例) ContentVersion targetFile = [SELECT VersionData, Title FROM ContentVersion WHERE Id = '068xxxxxxx' LIMIT 1]; Blob fileContent = targetFile.VersionData; docBuilder.setFile(fileContent); // 设置文档元数据,方便后续在Watson中关联Salesforce记录 Map<String, String> metadata = new Map<String, String>{ 'salesforce_record_id' => '001xxxxxxx', // 关联的Salesforce主记录ID 'document_name' => targetFile.Title, 'upload_source' => 'Salesforce' }; docBuilder.setMetadata(metadata); // 设置文件名(建议和Salesforce中保持一致) docBuilder.setFilename(targetFile.PathOnClient != null ? targetFile.PathOnClient : targetFile.Title); // 构建最终的上传选项对象 AddDocumentOptions uploadOptions = docBuilder.build(); // 调用Watson上传服务(假设你已经封装了服务类) WatsonDiscoveryService discoveryService = new WatsonDiscoveryService(); AddDocumentResponse uploadResp = discoveryService.addDocument(uploadOptions); // 处理上传结果 if(uploadResp.isSuccess()) { System.debug('Watson文档上传成功,文档ID:' + uploadResp.getDocumentId()); } else { System.debug('上传失败:' + uploadResp.getErrorMsg()); }
2. 文件上传自动同步的Apex触发器
我们监听ContentVersion对象(Salesforce上传文件后会生成该记录),在文件插入后自动触发同步逻辑,注意批量处理避免Governor Limit:
trigger ContentVersionToWatsonSync on ContentVersion (after insert) { List<AddDocumentOptions> uploadTasks = new List<AddDocumentOptions>(); WatsonDiscoveryService discoveryService = new WatsonDiscoveryService(); for(ContentVersion cv : Trigger.New) { // 只处理已发布的正式文件(跳过草稿版本) if(cv.IsLatest && cv.ContentLocation == 'S') { AddDocumentOptionsBuilder docBuilder = new AddDocumentOptionsBuilder(); // 设置Watson集合ID docBuilder.setCollectionId('your-watson-collection-id'); // 绑定文件内容 docBuilder.setFile(cv.VersionData); // 设置关联元数据 Map<String, String> metadata = new Map<String, String>{ 'content_version_id' => cv.Id, 'related_record_id' => cv.FirstPublishLocationId, // 文件关联的Salesforce记录ID 'document_title' => cv.Title }; docBuilder.setMetadata(metadata); docBuilder.setFilename(cv.PathOnClient != null ? cv.PathOnClient : cv.Title); uploadTasks.add(docBuilder.build()); } } // 批量上传到Watson if(!uploadTasks.isEmpty()) { try { List<AddDocumentResponse> results = discoveryService.batchAddDocuments(uploadTasks); // 遍历结果记录同步状态(可以写入自定义日志对象方便排查) for(AddDocumentResponse res : results) { if(!res.isSuccess()) { System.debug('同步失败:' + res.getErrorMsg()); } } } catch(Exception e) { System.debug('批量同步异常:' + e.getMessage()); } } }
3. Apex向IBM Watson上传文档的具体实现
如果你的集成还没封装Watson服务类,这里是核心的HTTP请求实现(以Watson Discovery服务为例):
public class WatsonDiscoveryService { // 建议从Named Credential或Custom Setting读取,不要硬编码 private String watsonApiKey = 'your-watson-api-key'; private String watsonBaseUrl = 'https://api.us-south.discovery.watson.cloud.ibm.com/instances/your-instance-id/v1/environments/your-environment-id/collections/your-collection-id/documents'; private String apiVersion = '2023-03-31'; // 对应你的Watson API版本 public AddDocumentResponse addDocument(AddDocumentOptions options) { AddDocumentResponse response = new AddDocumentResponse(); Http http = new Http(); HttpRequest req = new HttpRequest(); // 构建请求URL String requestUrl = watsonBaseUrl + '?version=' + apiVersion; req.setEndpoint(requestUrl); req.setMethod('POST'); // 设置Watson认证头(Basic Auth,apikey作为用户名) String authHeader = 'Basic ' + EncodingUtil.base64Encode(Blob.valueOf('apikey:' + watsonApiKey)); req.setHeader('Authorization', authHeader); req.setHeader('Content-Type', 'multipart/form-data'); // 构建多部分请求体(文件+元数据) MultipartFormDataGenerator form = new MultipartFormDataGenerator(); form.addBlobPart('file', options.getFilename(), options.getFile()); if(options.getMetadata() != null) { form.addStringPart('metadata', JSON.serialize(options.getMetadata()), 'application/json'); } req.setBody(form.getAsString()); req.setHeader('Content-Length', String.valueOf(form.getAsString().length())); try { HttpResponse res = http.send(req); if(res.getStatusCode() == 201) { // 201表示文档创建成功 Map<String, Object> respJson = (Map<String, Object>)JSON.deserializeUntyped(res.getBody()); response.setSuccess(true); response.setDocumentId((String)respJson.get('document_id')); } else { response.setSuccess(false); response.setErrorMsg('HTTP状态码:' + res.getStatusCode() + ',响应内容:' + res.getBody()); } } catch(Exception e) { response.setSuccess(false); response.setErrorMsg('请求异常:' + e.getMessage()); } return response; } // 批量上传方法,提高处理效率 public List<AddDocumentResponse> batchAddDocuments(List<AddDocumentOptions> optionsList) { List<AddDocumentResponse> responses = new List<AddDocumentResponse>(); for(AddDocumentOptions opt : optionsList) { responses.add(addDocument(opt)); } return responses; } } // 辅助类:封装上传选项 public class AddDocumentOptions { private String collectionId; private Blob file; private String filename; private Map<String, String> metadata; public AddDocumentOptions(String collectionId, Blob file, String filename, Map<String, String> metadata) { this.collectionId = collectionId; this.file = file; this.filename = filename; this.metadata = metadata; } public String getCollectionId() { return collectionId; } public Blob getFile() { return file; } public String getFilename() { return filename; } public Map<String, String> getMetadata() { return metadata; } } // 辅助类:封装上传响应结果 public class AddDocumentResponse { private Boolean isSuccess; private String documentId; private String errorMsg; public void setSuccess(Boolean success) { isSuccess = success; } public Boolean isSuccess() { return isSuccess; } public void setDocumentId(String docId) { documentId = docId; } public String getDocumentId() { return documentId; } public void setErrorMsg(String msg) { errorMsg = msg; } public String getErrorMsg() { return errorMsg; } }
额外注意事项
- 凭证安全:不要硬编码API Key和URL,建议用Salesforce的
Named Credentials或Custom Settings存储,降低泄露风险。 - 限制处理:Watson API有文件大小限制(比如Discovery最大支持50MB),可以在触发器中添加文件大小校验逻辑。
- 日志记录:建议创建自定义对象(如
WatsonSyncLog)来记录每次同步的状态,方便后续排查问题。
内容的提问来源于stack exchange,提问作者Nabs
相关产品推荐
相关产品推荐

