From 4ce3b2a7862f3c14fa89c154253070e3135def75 Mon Sep 17 00:00:00 2001 From: CalDescent Date: Sat, 18 Mar 2023 15:16:41 +0000 Subject: [PATCH] Added `GET /resource/filename/{service}/{name}/{identifier}` endpoint. This allows the filename of single file resources to be returned via the API. Useful to help determine to file format of the data. --- .../api/resource/ArbitraryResource.java | 53 +++++++++++++++++++ 1 file changed, 53 insertions(+) diff --git a/src/main/java/org/qortal/api/resource/ArbitraryResource.java b/src/main/java/org/qortal/api/resource/ArbitraryResource.java index 3d21042e..499b4874 100644 --- a/src/main/java/org/qortal/api/resource/ArbitraryResource.java +++ b/src/main/java/org/qortal/api/resource/ArbitraryResource.java @@ -278,6 +278,33 @@ public class ArbitraryResource { return ArbitraryTransactionUtils.getStatus(service, name, null, build); } + @GET + @Path("/resource/filename/{service}/{name}/{identifier}") + @Operation( + summary = "Get filename in published data", + description = "This causes a download of the data if it's not local. A filename will only be returned for single file resources.", + responses = { + @ApiResponse( + content = @Content(mediaType = MediaType.TEXT_PLAIN, + schema = @Schema( + type = "string" + ) + ) + ) + } + ) + @SecurityRequirement(name = "apiKey") + public String getResourceFilename(@HeaderParam(Security.API_KEY_HEADER) String apiKey, + @PathParam("service") Service service, + @PathParam("name") String name, + @PathParam("identifier") String identifier) { + + if (!Settings.getInstance().isQDNAuthBypassEnabled()) + Security.requirePriorAuthorizationOrApiKey(request, name, service, identifier, apiKey); + + return this.getFilename(service, name, identifier); + } + @GET @Path("/resource/status/{service}/{name}/{identifier}") @Operation( @@ -1350,4 +1377,30 @@ public class ArbitraryResource { throw ApiExceptionFactory.INSTANCE.createCustomException(request, ApiError.FILE_NOT_FOUND, e.getMessage()); } } + + private String getFilename(Service service, String name, String identifier) { + + ArbitraryDataReader arbitraryDataReader = new ArbitraryDataReader(name, ArbitraryDataFile.ResourceIdType.NAME, service, identifier); + try { + arbitraryDataReader.loadSynchronously(false); + java.nio.file.Path outputPath = arbitraryDataReader.getFilePath(); + if (outputPath == null) { + // Assume the resource doesn't exist + throw ApiExceptionFactory.INSTANCE.createCustomException(request, ApiError.FILE_NOT_FOUND, "File not found"); + } + + String[] files = ArrayUtils.removeElement(outputPath.toFile().list(), ".qortal"); + if (files.length == 1) { + LOGGER.info("File: {}", files[0]); + return files[0]; + } + else { + throw ApiExceptionFactory.INSTANCE.createCustomException(request, ApiError.INVALID_CRITERIA, "Filename not available for multi file resources"); + } + + } catch (Exception e) { + LOGGER.debug(String.format("Unable to load %s %s: %s", service, name, e.getMessage())); + throw ApiExceptionFactory.INSTANCE.createCustomException(request, ApiError.FILE_NOT_FOUND, e.getMessage()); + } + } }