From b254ca7706e90d4ab08b0e36f3204d205bd77f1d Mon Sep 17 00:00:00 2001 From: CalDescent Date: Fri, 3 Mar 2023 15:39:37 +0000 Subject: [PATCH] Added support for optional Base64 encoding in FETCH_QDN_RESOURCE. --- Q-Apps.md | 17 +++++++++-------- .../qortal/api/resource/ArbitraryResource.java | 16 +++++++++++++--- src/main/resources/q-apps/q-apps.js | 1 + 3 files changed, 23 insertions(+), 11 deletions(-) diff --git a/Q-Apps.md b/Q-Apps.md index b551239e..566112fd 100644 --- a/Q-Apps.md +++ b/Q-Apps.md @@ -116,7 +116,8 @@ async function myfunction() { action: "FETCH_QDN_RESOURCE", name: "QortalDemo", service: "THUMBNAIL", - identifier: "qortal_avatar" + identifier: "qortal_avatar", + encoding: "base64" }, timeout); // Do something with the avatar here @@ -225,13 +226,13 @@ let res = await qortalRequest({ ``` ### Fetch QDN single file resource -Data is returned in the base64 format ``` let res = await qortalRequest({ action: "FETCH_QDN_RESOURCE", name: "QortalDemo", service: "THUMBNAIL", identifier: "qortal_avatar", // Optional. If omitted, the default resource is returned, or you can alternatively use the keyword "default" + encoding: "base64", // Optional. If omitted, data is returned in raw form rebuild: false }); ``` @@ -548,26 +549,26 @@ Here is a sample application to display the logged-in user's avatar: return; } - // Download the avatar of the first registered name + // Download base64-encoded avatar of the first registered name let avatar = await qortalRequest({ action: "FETCH_QDN_RESOURCE", name: names[0].name, service: "THUMBNAIL", - identifier: "qortal_avatar" + identifier: "qortal_avatar", + encoding: "base64" }); - console.log("avatar: " + JSON.stringify(avatar)); + console.log("Avatar size: " + avatar.length + " bytes"); // Display the avatar image on the screen - document.getElementsById("avatar").src = "data:image/png;base64," + avatar; + document.getElementById("avatar").src = "data:image/png;base64," + avatar; } catch(e) { console.log("Error: " + JSON.stringify(e)); } } - showAvatar(); - + diff --git a/src/main/java/org/qortal/api/resource/ArbitraryResource.java b/src/main/java/org/qortal/api/resource/ArbitraryResource.java index 79efc55f..2abc07e8 100644 --- a/src/main/java/org/qortal/api/resource/ArbitraryResource.java +++ b/src/main/java/org/qortal/api/resource/ArbitraryResource.java @@ -17,6 +17,7 @@ import java.nio.file.Paths; import java.util.ArrayList; import java.util.Arrays; import java.util.List; +import java.util.Objects; import javax.servlet.ServletContext; import javax.servlet.http.HttpServletRequest; @@ -646,6 +647,7 @@ public class ArbitraryResource { @PathParam("service") Service service, @PathParam("name") String name, @QueryParam("filepath") String filepath, + @QueryParam("encoding") String encoding, @QueryParam("rebuild") boolean rebuild, @QueryParam("async") boolean async, @QueryParam("attempts") Integer attempts) { @@ -655,7 +657,7 @@ public class ArbitraryResource { Security.checkApiCallAllowed(request); } - return this.download(service, name, null, filepath, rebuild, async, attempts); + return this.download(service, name, null, filepath, encoding, rebuild, async, attempts); } @GET @@ -681,6 +683,7 @@ public class ArbitraryResource { @PathParam("name") String name, @PathParam("identifier") String identifier, @QueryParam("filepath") String filepath, + @QueryParam("encoding") String encoding, @QueryParam("rebuild") boolean rebuild, @QueryParam("async") boolean async, @QueryParam("attempts") Integer attempts) { @@ -690,7 +693,7 @@ public class ArbitraryResource { Security.checkApiCallAllowed(request, apiKey); } - return this.download(service, name, identifier, filepath, rebuild, async, attempts); + return this.download(service, name, identifier, filepath, encoding, rebuild, async, attempts); } @@ -1239,7 +1242,7 @@ public class ArbitraryResource { } } - private HttpServletResponse download(Service service, String name, String identifier, String filepath, boolean rebuild, boolean async, Integer maxAttempts) { + private HttpServletResponse download(Service service, String name, String identifier, String filepath, String encoding, boolean rebuild, boolean async, Integer maxAttempts) { ArbitraryDataReader arbitraryDataReader = new ArbitraryDataReader(name, ArbitraryDataFile.ResourceIdType.NAME, service, identifier); try { @@ -1298,7 +1301,14 @@ public class ArbitraryResource { String message = String.format("No file exists at filepath: %s", filepath); throw ApiExceptionFactory.INSTANCE.createCustomException(request, ApiError.INVALID_CRITERIA, message); } + byte[] data = Files.readAllBytes(path); + + // Encode the data if requested + if (encoding != null && Objects.equals(encoding.toLowerCase(), "base64")) { + data = Base64.encode(data); + } + response.setContentType(context.getMimeType(path.toString())); response.setContentLength(data.length); response.getOutputStream().write(data); diff --git a/src/main/resources/q-apps/q-apps.js b/src/main/resources/q-apps/q-apps.js index afaa2986..8315c6c4 100644 --- a/src/main/resources/q-apps/q-apps.js +++ b/src/main/resources/q-apps/q-apps.js @@ -173,6 +173,7 @@ window.addEventListener("message", (event) => { url = url.concat("?"); if (data.filepath != null) url = url.concat("&filepath=" + data.filepath); if (data.rebuild != null) url = url.concat("&rebuild=" + new Boolean(data.rebuild).toString()) + if (data.encoding != null) url = url.concat("&encoding=" + data.encoding); response = httpGet(url); break;