feat: support file delete api (#45)

This commit is contained in:
tomsun28 2025-08-28 10:33:11 +08:00 committed by GitHub
parent ffa57e420f
commit 838c847d6c
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
10 changed files with 113 additions and 26 deletions

View file

@ -33,6 +33,7 @@ import ai.z.openapi.core.model.FlowableClientResponse;
import ai.z.openapi.utils.FlowableRequestSupplier;
import ai.z.openapi.utils.OkHttps;
import ai.z.openapi.utils.RequestSupplier;
import ai.z.openapi.utils.StringUtils;
import io.reactivex.rxjava3.core.Flowable;
import io.reactivex.rxjava3.core.Single;
import okhttp3.OkHttpClient;
@ -318,7 +319,9 @@ public abstract class AbstractAiClient extends AbstractClientBaseService {
tResp.setMsg("Call Failed");
tResp.setSuccess(false);
ChatError chatError = new ChatError();
chatError.setCode(Integer.parseInt(e.code));
if (StringUtils.isNotEmpty(e.code)) {
chatError.setCode(Integer.parseInt(e.code));
}
chatError.setMessage(e.getMessage());
tResp.setError(chatError);
}

View file

@ -31,15 +31,6 @@ public interface FileApi {
@POST("files")
Single<File> uploadFile(@Body MultipartBody multipartBody);
/**
* Retrieve file metadata and information Gets detailed information about a previously
* uploaded file
* @param fileId Unique identifier of the file to retrieve
* @return File metadata including name, size, purpose, and creation time
*/
@GET("files/{file_id}")
Single<File> retrieveFile(@Path("file_id") String fileId);
/**
* Delete a file from the platform Permanently removes the file and all associated
* data

View file

@ -12,6 +12,7 @@ import ai.z.openapi.service.model.ZAiHttpException;
import ai.z.openapi.utils.FlowableRequestSupplier;
import ai.z.openapi.utils.RequestSupplier;
import ai.z.openapi.utils.StringUtils;
import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.ObjectMapper;
import io.reactivex.rxjava3.core.BackpressureStrategy;
import io.reactivex.rxjava3.core.Flowable;
@ -117,10 +118,41 @@ public abstract class AbstractClientBaseService {
if (StringUtils.isEmpty(errorBody)) {
throw e;
}
ZAiError error = mapper.readValue(errorBody, ZAiError.class);
throw new ZAiHttpException(error, e, e.code());
// here not only the ZAiError, also has {"error": "message"} and others
JsonNode jsonNode = mapper.readTree(errorBody);
if (jsonNode.has("error")) {
JsonNode errorNode = jsonNode.get("error");
if (errorNode.isTextual()) {
JsonNode codeNode = jsonNode.get("code");
throw new ZAiHttpException(errorNode.asText(), codeNode == null ? null : codeNode.asText(), e,
e.code());
}
else {
ZAiError error = mapper.readValue(errorBody, ZAiError.class);
throw new ZAiHttpException(error, e, e.code());
}
}
else if (jsonNode.has("msg")) {
JsonNode msgNode = jsonNode.get("msg");
JsonNode codeNode = jsonNode.get("code");
throw new ZAiHttpException(msgNode.asText(), codeNode == null ? null : codeNode.asText(), e,
e.code());
}
else if (jsonNode.has("message")) {
JsonNode msgNode = jsonNode.get("message");
JsonNode codeNode = jsonNode.get("code");
throw new ZAiHttpException(msgNode.asText(), codeNode == null ? null : codeNode.asText(), e,
e.code());
}
else {
throw new ZAiHttpException(errorBody, null, e, e.code());
}
}
catch (IOException ex) {
catch (ZAiHttpException zAiHttpException) {
throw zAiHttpException;
}
catch (Exception ex) {
logger.error(ex.getMessage(), ex);
// couldn't parse ZAiError error
throw e;
}

View file

@ -0,0 +1,24 @@
package ai.z.openapi.service.file;
import ai.z.openapi.core.model.ClientRequest;
import ai.z.openapi.core.model.ClientResponse;
import ai.z.openapi.service.batches.BatchRequest;
import ai.z.openapi.service.model.ChatError;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.EqualsAndHashCode;
import lombok.NoArgsConstructor;
import lombok.experimental.SuperBuilder;
@EqualsAndHashCode(callSuper = false)
@SuperBuilder
@NoArgsConstructor
@AllArgsConstructor
@Data
@Builder
public class FileDelRequest implements ClientRequest<FileDelRequest> {
private String fileId;
}

View file

@ -1,9 +1,11 @@
package ai.z.openapi.service.file;
import ai.z.openapi.core.model.ClientResponse;
import ai.z.openapi.service.model.ChatError;
import lombok.Data;
@Data
public class FileDelResponse {
public class FileDelResponse implements ClientResponse<FileDeleted> {
private int code;
@ -13,4 +15,6 @@ public class FileDelResponse {
private FileDeleted data;
private ChatError error;
}

View file

@ -15,6 +15,13 @@ public interface FileService {
*/
FileApiResponse uploadFile(FileUploadParams request);
/**
* Delete file by file ID.
* @param request the file id to delete.
* @return FileDelResponse containing the delete result
*/
FileDelResponse deleteFile(FileDelRequest request);
/**
* Lists all files.
* @param queryFilesRequest FileListParams containing the query parameters for listing

View file

@ -70,6 +70,12 @@ public class FileServiceImpl implements FileService {
return this.zAiClient.executeRequest(request, supplier, FileApiResponse.class);
}
@Override
public FileDelResponse deleteFile(FileDelRequest request) {
RequestSupplier<FileDelRequest, FileDeleted> supplier = (params -> fileApi.deletedFile(params.getFileId()));
return this.zAiClient.executeRequest(request, supplier, FileDelResponse.class);
}
@Override
public QueryFileApiResponse listFiles(FileListParams queryFilesRequest) {
RequestSupplier<FileListParams, QueryFileResult> supplier = (params) -> fileApi.queryFileList(params.getAfter(),

View file

@ -30,12 +30,8 @@ public class ZAiError {
*/
String message;
String type;
String param;
/**
* ZAI error code, for example "invalid_api_key"
* ZAI error code, for example "401"
*/
String code;

View file

@ -8,23 +8,27 @@ public class ZAiHttpException extends RuntimeException {
public final int statusCode;
/**
* ZAI error code, for example "invalid_api_key"
* ZAI error code, for example "1233"
*/
public final String code;
public final String param;
/**
* ZAI error type, for example "invalid_request_error"
* ZAI error message
*/
public final String type;
public final String msg;
public ZAiHttpException(ZAiError error, Exception parent, int statusCode) {
super(error.error.message, parent);
this.statusCode = statusCode;
this.code = error.error.code;
this.param = error.error.param;
this.type = error.error.type;
this.msg = error.error.message;
}
public ZAiHttpException(String errorMsg, String errorCode, Exception parent, int statusCode) {
super(errorMsg, parent);
this.statusCode = statusCode;
this.code = errorCode;
this.msg = errorMsg;
}
}

View file

@ -174,6 +174,26 @@ public class FileServiceTest {
logger.info("List files response: {}", mapper.writeValueAsString(response));
}
@Test
@DisplayName("Test Delete File - Basic Functionality")
@EnabledIfEnvironmentVariable(named = "ZAI_API_KEY", matches = "^[^.]+\\.[^.]+$")
void testDeleteFile() throws JsonProcessingException {
String fileId = String.format(REQUEST_ID_TEMPLATE, System.currentTimeMillis());
FileDelRequest request = FileDelRequest.builder().fileId(fileId).build();
// Execute test
FileDelResponse response = fileService.deleteFile(request);
// Verify results
assertNotNull(response, "Response should not be null");
assertFalse(response.isSuccess(), "Response should be failed");
assertNull(response.getData(), "Response data should not be null");
assertNotNull(response.getError(), "Response error should be null");
logger.info("Delete file response: {}", mapper.writeValueAsString(response));
}
@Test
@DisplayName("Test List Files with Purpose Filter")
@EnabledIfEnvironmentVariable(named = "ZAI_API_KEY", matches = "^[^.]+\\.[^.]+$")