From ef5f55982ecef5f2440523073ef8c4c83ba2ceb5 Mon Sep 17 00:00:00 2001 From: code-c-light Date: Thu, 30 Oct 2025 17:31:50 +0800 Subject: [PATCH] feat: support file parsing sync (#60) Co-authored-by: mengqian --- .../api/fileparsing/FileParsingApi.java | 10 +++ .../java/ai/z/openapi/core/Constants.java | 3 +- .../fileparsing/FileParsingService.java | 9 +++ .../fileparsing/FileParsingServiceImpl.java | 53 ++++++++++++- .../fileparsing/FileParsingServiceTest.java | 4 +- pom.xml | 2 +- .../FileParsingExample.java | 74 ++++++++++--------- .../FileParsingSyncExample.java | 64 ++++++++++++++++ 8 files changed, 177 insertions(+), 42 deletions(-) create mode 100644 samples/src/main/ai.z.openapi.samples/FileParsingSyncExample.java diff --git a/core/src/main/java/ai/z/openapi/api/fileparsing/FileParsingApi.java b/core/src/main/java/ai/z/openapi/api/fileparsing/FileParsingApi.java index 58f6d43..1e105f5 100644 --- a/core/src/main/java/ai/z/openapi/api/fileparsing/FileParsingApi.java +++ b/core/src/main/java/ai/z/openapi/api/fileparsing/FileParsingApi.java @@ -44,4 +44,14 @@ public interface FileParsingApi { @GET("files/parser/result/{taskId}/{formatType}") Call downloadParseResult(@Path("taskId") String taskId, @Path("formatType") String formatType); + /** + * Executes a synchronous file parsing operation. Uploads a file and returns the + * parsing result with specified tool and file type. + * @param multipartBody The multipart request body containing the file and related + * metadata (tool type, file type) + * @return Parsing result content as a FileParsingDownloadResp object + */ + @POST("files/parser/sync") + Call syncParse(@Body MultipartBody multipartBody); + } \ No newline at end of file diff --git a/core/src/main/java/ai/z/openapi/core/Constants.java b/core/src/main/java/ai/z/openapi/core/Constants.java index 12557b3..b3043d5 100644 --- a/core/src/main/java/ai/z/openapi/core/Constants.java +++ b/core/src/main/java/ai/z/openapi/core/Constants.java @@ -3,10 +3,9 @@ package ai.z.openapi.core; /** * Constants class containing all the configuration values and model identifiers used * throughout the Z.AI OpenAPI SDK. - * + *

* This class provides centralized access to: - API base URLs - Model identifiers for * different AI capabilities - Invocation method constants - * */ public final class Constants { diff --git a/core/src/main/java/ai/z/openapi/service/fileparsing/FileParsingService.java b/core/src/main/java/ai/z/openapi/service/fileparsing/FileParsingService.java index 654b2b3..a9f8ae8 100644 --- a/core/src/main/java/ai/z/openapi/service/fileparsing/FileParsingService.java +++ b/core/src/main/java/ai/z/openapi/service/fileparsing/FileParsingService.java @@ -20,4 +20,13 @@ public interface FileParsingService { */ FileParsingDownloadResponse getParseResult(FileParsingDownloadReq request); + /** + * Executes a synchronous file parsing operation. Uploads a file and immediately + * returns the parsing result, using the specified tool and file type. + * @param request The file parsing upload request (contains file path, tool type, file + * type, etc.) + * @return FileParsingDownloadResponse containing the parsed content and status + */ + FileParsingDownloadResponse syncParse(FileParsingUploadReq request); + } \ No newline at end of file diff --git a/core/src/main/java/ai/z/openapi/service/fileparsing/FileParsingServiceImpl.java b/core/src/main/java/ai/z/openapi/service/fileparsing/FileParsingServiceImpl.java index c57cdd5..c1998b5 100644 --- a/core/src/main/java/ai/z/openapi/service/fileparsing/FileParsingServiceImpl.java +++ b/core/src/main/java/ai/z/openapi/service/fileparsing/FileParsingServiceImpl.java @@ -40,7 +40,7 @@ public class FileParsingServiceImpl implements FileParsingService { if (request.getToolType() == null) { throw new IllegalArgumentException("toolType cannot be null"); } - // 构建 multipart/form-data + // Construct multipart/form-data RequestSupplier supplier = params -> { try { File file = new File(params.getFilePath()); @@ -107,4 +107,55 @@ public class FileParsingServiceImpl implements FileParsingService { return this.zAiClient.executeRequest(request, supplier, FileParsingDownloadResponse.class); } + @Override + public FileParsingDownloadResponse syncParse(FileParsingUploadReq request) { + if (request == null) { + throw new IllegalArgumentException("request cannot be null"); + } + if (request.getFilePath() == null) { + throw new IllegalArgumentException("filePath cannot be null"); + } + if (request.getToolType() == null) { + throw new IllegalArgumentException("toolType cannot be null"); + } + + RequestSupplier supplier = params -> { + try { + File file = new File(params.getFilePath()); + if (!file.exists()) { + throw new RuntimeException("file not found at " + params.getFilePath()); + } + + String toolType = params.getToolType(); + String fileType = params.getFileType(); + + // Construct multipart/form-data + MultipartBody.Part filePart = MultipartBody.Part.createFormData("file", file.getName(), + RequestBody.create(MediaType.parse("application/octet-stream"), file)); + MultipartBody.Builder formBodyBuilder = new MultipartBody.Builder().setType(MultipartBody.FORM); + formBodyBuilder.addPart(filePart); + formBodyBuilder.addFormDataPart("tool_type", toolType); + formBodyBuilder.addFormDataPart("file_type", fileType); + + MultipartBody multipartBody = formBodyBuilder.build(); + + // Send a POST request + retrofit2.Call call = fileParsingApi.syncParse(multipartBody); + Response response = call.execute(); + if (!response.isSuccessful() || response.body() == null) { + throw new IOException( + "Failed to sync parse, code: " + response.code() + ", msg: " + response.message()); + } + + return Single.just(response.body()); + + } + catch (Exception e) { + throw new RuntimeException(e); + } + }; + + return this.zAiClient.executeRequest(request, supplier, FileParsingDownloadResponse.class); + } + } \ No newline at end of file diff --git a/core/src/test/java/ai/z/openapi/service/fileparsing/FileParsingServiceTest.java b/core/src/test/java/ai/z/openapi/service/fileparsing/FileParsingServiceTest.java index db58c68..8123520 100644 --- a/core/src/test/java/ai/z/openapi/service/fileparsing/FileParsingServiceTest.java +++ b/core/src/test/java/ai/z/openapi/service/fileparsing/FileParsingServiceTest.java @@ -218,11 +218,11 @@ public class FileParsingServiceTest { byte[] bytes = Files.readAllBytes(new File(file).toPath()); Base64.Encoder encoder = Base64.getEncoder(); String imageBase64 = encoder.encodeToString(bytes); - // 假设解析接口支持 imageBase64 字段 + // Assuming the parsing interface supports the imageBase64 field FileParsingUploadReq request = FileParsingUploadReq.builder() .toolType("image") .fileType("png") - .filePath(file) // 或文件路径 + .filePath(file) // file path .build(); FileParsingResponse response = fileParsingService.createParseTask(request); diff --git a/pom.xml b/pom.xml index 84dbede..2bb20dc 100644 --- a/pom.xml +++ b/pom.xml @@ -45,7 +45,7 @@ - 0.0.6.1 + 0.0.6.2 8 UTF-8 UTF-8 diff --git a/samples/src/main/ai.z.openapi.samples/FileParsingExample.java b/samples/src/main/ai.z.openapi.samples/FileParsingExample.java index 077fd99..90c3cad 100644 --- a/samples/src/main/ai.z.openapi.samples/FileParsingExample.java +++ b/samples/src/main/ai.z.openapi.samples/FileParsingExample.java @@ -10,84 +10,86 @@ import ai.z.openapi.utils.StringUtils; public class FileParsingExample { public static void main(String[] args) { - // 建议通过环境变量设置 API Key - // export ZAI_API_KEY=your.api_key - // ZaiClient client = ZaiClient.builder().build(); +// It's recommended to set the API Key via environment variable +// export ZAI_API_KEY=your.api_key +// ZaiClient client = ZaiClient.builder().build(); + +// You can also specify the API Key directly in code + - // 也可在代码中直接指定 API Key ZaiClient client = ZaiClient.builder() .apiKey("API Key") .build(); try { - // 示例1: 创建解析任务 - System.out.println("=== 文件解析任务创建示例 ==="); + // Example 1: Create a file parsing task + System.out.println("=== Example: Create file parsing task ==="); String filePath = "your file path"; String taskId = createFileParsingTaskExample(client, filePath, "pdf", "lite"); - // 示例2: 获取解析结果 - System.out.println("\n=== 获取解析结果示例 ==="); + // Example 2: Get parsing result + System.out.println("\n=== Example: Get parsing result ==="); getFileParsingResultExample(client, taskId); } catch (Exception e) { - System.err.println("发生异常: " + e.getMessage()); + System.err.println("Exception occurred: " + e.getMessage()); e.printStackTrace(); } } /** - * 示例:创建解析任务(上传文件并解析) + * Example: Create parsing task (upload file and parse) * - * @param client ZaiClient 实例 - * @return 解析任务的 taskId + * @param client ZaiClient instance + * @return TaskId of the parsing task */ private static String createFileParsingTaskExample(ZaiClient client, String filePath, String fileType, String toolType) { if (StringUtils.isEmpty(filePath)) { - System.err.println("无效的文件路径。"); + System.err.println("Invalid file path."); return null; } try { FileParsingUploadReq uploadReq = FileParsingUploadReq.builder() .filePath(filePath) - .fileType(fileType) // 支持: pdf, docx 等 - .toolType(toolType) // 解析工具类型: lite, prime, expert + .fileType(fileType) // support: pdf, docx etc. + .toolType(toolType) // tool type: lite, prime, expert .build(); - System.out.println("正在上传并创建解析任务..."); + System.out.println("Uploading file and creating parsing task..."); FileParsingResponse response = client.fileParsing().createParseTask(uploadReq); if (response.isSuccess()) { if (null != response.getData().getTaskId()) { String taskId = response.getData().getTaskId(); - System.out.println("解析任务创建成功,TaskId: " + taskId); + System.out.println("Parsing task created successfully, TaskId: " + taskId); return taskId; } else { - System.err.println("解析任务创建失败: " + response.getData().getMessage()); + System.err.println("Failed to create parsing task: " + response.getData().getMessage()); } } else { - System.err.println("解析任务创建失败: " + response.getMsg()); + System.err.println("Failed to create parsing task: " + response.getMsg()); } } catch (Exception e) { - System.err.println("文件解析任务错误: " + e.getMessage()); + System.err.println("File parsing task error: " + e.getMessage()); } - // 返回 null 表示创建失败 + // Return null indicates task creation failed return null; } /** - * 示例:获取解析结果 + * Example: Get parsing result * - * @param client ZaiClient 实例 - * @param taskId 解析任务ID + * @param client ZaiClient instance + * @param taskId ID of the parsing task */ private static void getFileParsingResultExample(ZaiClient client, String taskId) { if (taskId == null || taskId.isEmpty()) { - System.err.println("无效的任务ID,无法获取解析结果。"); + System.err.println("Invalid task ID. Cannot get parsing result."); return; } try { - int maxRetry = 100; // 最多轮询100次 - int intervalMs = 3000; // 每次间隔3秒 + int maxRetry = 100; // Maximum 100 polling attempts + int intervalMs = 3000; // 3 seconds interval between each polling for (int i = 0; i < maxRetry; i++) { FileParsingDownloadReq downloadReq = FileParsingDownloadReq.builder() .taskId(taskId) @@ -98,28 +100,28 @@ public class FileParsingExample { if (response.isSuccess()) { String status = response.getData().getStatus(); - System.out.println("当前任务状态: " + status); + System.out.println("Current task status: " + status); if ("succeeded".equalsIgnoreCase(status)) { - System.out.println("解析结果获取成功!"); - System.out.println("解析内容: " + response.getData().getContent()); - System.out.println("内容下载链接: " + response.getData().getParsingResultUrl()); + System.out.println("Parsing result obtained successfully!"); + System.out.println("Parsed content: " + response.getData().getContent()); + System.out.println("Download link: " + response.getData().getParsingResultUrl()); return; } else if ("processing".equalsIgnoreCase(status)) { - System.out.println("解析进行中,请稍候..."); + System.out.println("Parsing in progress, please wait..."); Thread.sleep(intervalMs); } else { - System.out.println("解析任务异常,状态: " + status + ",消息: " + response.getData().getMessage()); + System.out.println("Parsing task exception, status: " + status + ", message: " + response.getData().getMessage()); return; } } else { - System.err.println("解析结果获取失败: " + response.getMsg()); + System.err.println("Failed to get parsing result: " + response.getMsg()); return; } } - System.out.println("等待超时,请稍后自行查询解析结果。"); + System.out.println("Wait timeout, please check the parsing result later."); } catch (Exception e) { - System.err.println("获取解析结果时异常: " + e.getMessage()); + System.err.println("Exception occurred while getting parsing result: " + e.getMessage()); } } } diff --git a/samples/src/main/ai.z.openapi.samples/FileParsingSyncExample.java b/samples/src/main/ai.z.openapi.samples/FileParsingSyncExample.java new file mode 100644 index 0000000..6e51bea --- /dev/null +++ b/samples/src/main/ai.z.openapi.samples/FileParsingSyncExample.java @@ -0,0 +1,64 @@ +package ai.z.openapi.samples; + +import ai.z.openapi.ZaiClient; +import ai.z.openapi.service.fileparsing.FileParsingDownloadResponse; +import ai.z.openapi.service.fileparsing.FileParsingUploadReq; +import ai.z.openapi.utils.StringUtils; + +public class FileParsingSyncExample { + + public static void main(String[] args) { + // It is recommended to set the API Key using an environment variable + // export ZAI_API_KEY=your.api_key + // ZaiClient client = ZaiClient.builder().build(); + + // Alternatively, the API Key can be specified directly in the code + ZaiClient client = ZaiClient.builder() + .apiKey("API Key") + .build(); + + try { + System.out.println("=== Example: Creating file parsing task ==="); + + String filePath = "your file path"; + FileParsingDownloadResponse result = syncFileParsingTaskExample(client, filePath, "pdf", "prime-sync"); + + System.out.println("Parsing task created successfully, TaskId: " + result.getData().getTaskId()); + System.out.println("File content: " + result.getData().getContent()); + System.out.println("Download link: " + result.getData().getParsingResultUrl()); + + } catch (Exception e) { + System.err.println("Exception occurred: " + e.getMessage()); + e.printStackTrace(); + } + } + + /** + * Example: Create parsing task (upload file and parse) + * + * @param client ZaiClient instance + * @return Parsing task's taskId + */ + private static FileParsingDownloadResponse syncFileParsingTaskExample(ZaiClient client, String filePath, String fileType, String toolType) { + if (StringUtils.isEmpty(filePath)) { + System.err.println("Invalid file path."); + return null; + } + try { + FileParsingUploadReq uploadReq = FileParsingUploadReq.builder() + .filePath(filePath) + .fileType(fileType) // Supported types: pdf, docx, etc. + .toolType(toolType) // Parsing tool type: lite, prime, expert + .build(); + + System.out.println("Uploading file and creating parsing task..."); + return client.fileParsing().syncParse(uploadReq); + } catch (Exception e) { + System.err.println("File parsing task error: " + e.getMessage()); + } + // Returning null means task creation failed + return null; + } + + +} \ No newline at end of file