diff --git a/static/js/vue-cdr-access/src/mixins/fileDownloadUtils.js b/static/js/vue-cdr-access/src/mixins/fileDownloadUtils.js index 0773a0ab7f..e69b1f0813 100644 --- a/static/js/vue-cdr-access/src/mixins/fileDownloadUtils.js +++ b/static/js/vue-cdr-access/src/mixins/fileDownloadUtils.js @@ -63,7 +63,7 @@ export default { } - html += `${this.$t('full_record.full_size')} JPG`; + html += `${this.$t('full_record.full_size')} JPG`; html += ''; html += `${this.$t('full_record.original_file')}`; diff --git a/web-services-app/src/main/java/edu/unc/lib/boxc/web/services/processing/DownloadImageService.java b/web-services-app/src/main/java/edu/unc/lib/boxc/web/services/processing/DownloadImageService.java index 278f94ebe5..7df5fbc5ce 100644 --- a/web-services-app/src/main/java/edu/unc/lib/boxc/web/services/processing/DownloadImageService.java +++ b/web-services-app/src/main/java/edu/unc/lib/boxc/web/services/processing/DownloadImageService.java @@ -5,6 +5,7 @@ import edu.unc.lib.boxc.model.api.DatastreamType; import edu.unc.lib.boxc.search.api.models.ContentObjectRecord; import edu.unc.lib.boxc.search.api.models.Datastream; +import edu.unc.lib.boxc.web.services.utils.ImageServerUtil; import org.apache.commons.io.FilenameUtils; import org.springframework.core.io.InputStreamResource; import org.springframework.http.HttpHeaders; @@ -22,13 +23,13 @@ */ public class DownloadImageService { private String iiifBasePath; - public static final String FULL_SIZE = "full"; + public static final String FULL_SIZE = "max"; public static final String INVALID_SIZE_MESSAGE = "Unable to determine size for access copy download"; /** * Method contacts the IIIF server for the requested access copy image and returns it * @param contentObjectRecord solr record of the file - * @param size a string which is either "full" for full size or a pixel length like "1200" + * @param size a string which is either "max" for full size or a pixel length like "1200" * @param pidString the UUID of the file * @return a response entity which contains headers and content of the access copy image * @throws IOException @@ -54,13 +55,12 @@ public ResponseEntity streamImage(ContentObjectRecord conte /** * A method that builds the IIIF URL based on an assumption of full region, 0 rotation, and default quality. * @param id the UUID of the file - * @param size a string which is either "full" for full size or a pixel length like "1200" + * @param size a string which is either "max" for full size or a pixel length like "1200" * @return a string which is the URL to request the IIIF server for the image */ private String buildURL(String id, String size) { var formattedSize = size; - var hash = idToPath(id, 4, 2); - var formattedId = hash + id + ".jp2"; + var formattedId = ImageServerUtil.getImageServerEncodedId(id); if (!Objects.equals(size, FULL_SIZE)) { // pixel length should be in !123,123 format formattedSize = "!" + size + "," + size; diff --git a/web-services-app/src/main/java/edu/unc/lib/boxc/web/services/processing/ImageServerProxyService.java b/web-services-app/src/main/java/edu/unc/lib/boxc/web/services/processing/ImageServerProxyService.java index 2aff700f9c..b923793c4e 100644 --- a/web-services-app/src/main/java/edu/unc/lib/boxc/web/services/processing/ImageServerProxyService.java +++ b/web-services-app/src/main/java/edu/unc/lib/boxc/web/services/processing/ImageServerProxyService.java @@ -5,6 +5,7 @@ import edu.unc.lib.boxc.common.util.URIUtil; import edu.unc.lib.boxc.web.common.exceptions.ClientAbortException; import edu.unc.lib.boxc.web.common.utils.FileIOUtil; +import edu.unc.lib.boxc.web.services.utils.ImageServerUtil; import org.apache.http.HttpEntity; import org.apache.http.HttpStatus; import org.apache.http.client.config.RequestConfig; @@ -59,7 +60,7 @@ public void getMetadata(String id, OutputStream outStream, HttpServletResponse response, int retryServerError) { var path = new StringBuilder(getImageServerProxyBasePath()); - path.append(getImageServerEncodedId(id)).append(".jp2").append("/info.json"); + path.append(ImageServerUtil.getImageServerEncodedId(id)).append("/info.json"); int statusCode = -1; String statusLine = null; @@ -115,7 +116,7 @@ public void streamJP2(String id, String region, String size, String rotation, St int retryServerError) { StringBuilder path = new StringBuilder(getImageServerProxyBasePath()); - path.append(getImageServerEncodedId(id)).append(".jp2") + path.append(ImageServerUtil.getImageServerEncodedId(id)) .append("/" + region).append("/" + size) .append("/" + rotation).append("/" + quality + "." + format); @@ -149,17 +150,6 @@ public void streamJP2(String id, String region, String size, String rotation, St } } - /** - * Returns the image server base path with encoded IDs - * @param id - * @return - */ - public String getImageServerEncodedId(String id) { - var idPathEncoded = URLEncoder.encode(idToPath(id, 4, 2), StandardCharsets.UTF_8); - var idEncoded = URLEncoder.encode(id, StandardCharsets.UTF_8); - return idPathEncoded + idEncoded; - } - public void setImageServerProxyBasePath(String fullPath) { this.imageServerProxyBasePath = fullPath; } diff --git a/web-services-app/src/main/java/edu/unc/lib/boxc/web/services/utils/ImageServerUtil.java b/web-services-app/src/main/java/edu/unc/lib/boxc/web/services/utils/ImageServerUtil.java new file mode 100644 index 0000000000..c8e029e572 --- /dev/null +++ b/web-services-app/src/main/java/edu/unc/lib/boxc/web/services/utils/ImageServerUtil.java @@ -0,0 +1,22 @@ +package edu.unc.lib.boxc.web.services.utils; + +import java.net.URLEncoder; +import java.nio.charset.StandardCharsets; + +import static edu.unc.lib.boxc.model.fcrepo.ids.RepositoryPaths.idToPath; + +/** + * @author snluong + */ +public class ImageServerUtil { + /** + * Returns the object ID in proper encoded format with .jp2 extension + * @param id + * @return + */ + public static String getImageServerEncodedId(String id) { + var idPathEncoded = URLEncoder.encode(idToPath(id, 4, 2), StandardCharsets.UTF_8); + var idEncoded = URLEncoder.encode(id, StandardCharsets.UTF_8); + return idPathEncoded + idEncoded + ".jp2"; + } +} diff --git a/web-services-app/src/test/java/edu/unc/lib/boxc/web/services/rest/DownloadImageControllerIT.java b/web-services-app/src/test/java/edu/unc/lib/boxc/web/services/rest/DownloadImageControllerIT.java index 923e0234f2..c1496c3226 100644 --- a/web-services-app/src/test/java/edu/unc/lib/boxc/web/services/rest/DownloadImageControllerIT.java +++ b/web-services-app/src/test/java/edu/unc/lib/boxc/web/services/rest/DownloadImageControllerIT.java @@ -14,7 +14,9 @@ import edu.unc.lib.boxc.search.solr.models.ContentObjectSolrRecord; import edu.unc.lib.boxc.web.common.services.SolrQueryLayerService; import edu.unc.lib.boxc.web.services.processing.DownloadImageService; +import edu.unc.lib.boxc.web.services.processing.ImageServerProxyService; import edu.unc.lib.boxc.web.services.rest.modify.AbstractAPIIT; +import edu.unc.lib.boxc.web.services.utils.ImageServerUtil; import org.apache.commons.io.FileUtils; import org.junit.jupiter.api.Test; import org.junit.jupiter.api.extension.ExtendWith; @@ -64,7 +66,7 @@ public class DownloadImageControllerIT extends AbstractAPIIT { public void testGetImageAtFullSize() throws Exception { var pid = makePid(); var pidString = pid.getId(); - var formattedPid = idToPath(pidString, 4, 2) + pidString + ".jp2"; + var formattedPid = ImageServerUtil.getImageServerEncodedId(pidString); var filename = "bunny.jpg"; ContentObjectSolrRecord contentObjectSolrRecord = mock(ContentObjectSolrRecord.class); Datastream originalDatastream = mock(Datastream.class); @@ -77,25 +79,25 @@ public void testGetImageAtFullSize() throws Exception { when(contentObjectSolrRecord.getPid()).thenReturn(pid); - stubFor(WireMock.get(urlMatching("/" + formattedPid + "/full/full/0/default.jpg")) + stubFor(WireMock.get(urlMatching("/" + formattedPid + "/full/max/0/default.jpg")) .willReturn(aResponse() .withStatus(HttpStatus.OK.value()) .withBodyFile(filename) .withHeader("Content-Type", "image/jpeg"))); - MvcResult result = mvc.perform(get("/downloadImage/" + pidString + "/full")) + MvcResult result = mvc.perform(get("/downloadImage/" + pidString + "/max")) .andExpect(status().is2xxSuccessful()) .andReturn(); var response = result.getResponse(); - assertEquals("attachment; filename=bunny_full.jpg", response.getHeader(CONTENT_DISPOSITION)); + assertEquals("attachment; filename=bunny_max.jpg", response.getHeader(CONTENT_DISPOSITION)); } @Test public void testGetImageAtPixelSizeSmallerThanFull() throws Exception { var pid = makePid(); var pidString = pid.getId(); - var formattedPid = idToPath(pidString, 4, 2) + pidString + ".jp2"; + var formattedPid = ImageServerUtil.getImageServerEncodedId(pidString); var filename = "bunny.jpg"; ContentObjectSolrRecord contentObjectSolrRecord = mock(ContentObjectSolrRecord.class); Datastream originalDatastream = mock(Datastream.class); @@ -128,13 +130,13 @@ public void testGetImageAtPixelSizeSmallerThanFull() throws Exception { public void testGetImageAtPixelSizeBiggerThanFull() throws Exception { var pid = makePid(); var pidString = pid.getId(); - var formattedPid = idToPath(pidString, 4, 2) + pidString + ".jp2"; + var formattedPid = ImageServerUtil.getImageServerEncodedId(pidString); var filename = "bunny.jpg"; ContentObjectSolrRecord contentObjectSolrRecord = mock(ContentObjectSolrRecord.class); Datastream originalDatastream = mock(Datastream.class); Datastream jp2Datastream = mock(Datastream.class); - stubFor(WireMock.get(urlMatching("/" + formattedPid + "/full/full/0/default.jpg")) + stubFor(WireMock.get(urlMatching("/" + formattedPid + "/full/max/0/default.jpg")) .willReturn(aResponse() .withStatus(HttpStatus.OK.value()) .withBodyFile(filename) @@ -153,7 +155,7 @@ public void testGetImageAtPixelSizeBiggerThanFull() throws Exception { var response = result.getResponse(); - assertEquals("attachment; filename=bunny_full.jpg", response.getHeader(CONTENT_DISPOSITION)); + assertEquals("attachment; filename=bunny_max.jpg", response.getHeader(CONTENT_DISPOSITION)); assertCorrectImageReturned(response); } @@ -165,7 +167,7 @@ public void testFullSizeAccessImageNoFullSizePermissions() throws Exception { doThrow(new AccessRestrictionException()).when(accessControlService) .assertHasAccess(anyString(), eq(filePid), any(AccessGroupSetImpl.class), eq(viewOriginal)); - MvcResult result = mvc.perform(get("/downloadImage/" + filePid.getId() + "/full")) + MvcResult result = mvc.perform(get("/downloadImage/" + filePid.getId() + "/max")) .andExpect(status().isForbidden()) .andReturn(); @@ -276,7 +278,7 @@ public void testGetImageNoJP2() throws Exception { ContentObjectSolrRecord contentObjectSolrRecord = mock(ContentObjectSolrRecord.class); when(solrSearchService.getObjectById(any(SimpleIdRequest.class))).thenReturn(contentObjectSolrRecord); - mvc.perform(get("/downloadImage/" + filePid.getId() + "/full")) + mvc.perform(get("/downloadImage/" + filePid.getId() + "/max")) .andExpect(status().is4xxClientError()) .andReturn(); } diff --git a/web-services-app/src/test/java/edu/unc/lib/boxc/web/services/rest/ImageServerProxyControllerTest.java b/web-services-app/src/test/java/edu/unc/lib/boxc/web/services/rest/ImageServerProxyControllerTest.java index 18c9b21da6..3f1bebb2c8 100644 --- a/web-services-app/src/test/java/edu/unc/lib/boxc/web/services/rest/ImageServerProxyControllerTest.java +++ b/web-services-app/src/test/java/edu/unc/lib/boxc/web/services/rest/ImageServerProxyControllerTest.java @@ -8,6 +8,7 @@ import edu.unc.lib.boxc.auth.fcrepo.models.AccessGroupSetImpl; import edu.unc.lib.boxc.web.services.processing.ImageServerProxyService; import edu.unc.lib.boxc.web.services.rest.modify.AbstractAPIIT; +import edu.unc.lib.boxc.web.services.utils.ImageServerUtil; import org.apache.http.impl.client.CloseableHttpClient; import org.junit.Assert; import org.junit.jupiter.api.AfterEach; @@ -44,8 +45,6 @@ @WireMockTest(httpPort = 46887) public class ImageServerProxyControllerTest extends AbstractAPIIT { - @Autowired - private ImageServerProxyService imageServerProxyService; @Autowired private AccessControlService accessControlService; @@ -78,7 +77,7 @@ void getRegionTestNoAccess() throws Exception { void getRegionTest() throws Exception { var pid = makePid(); var pidString = pid.getId(); - var formattedBasePath = "/iiif/v3/" + imageServerProxyService.getImageServerEncodedId(pidString) + ".jp2"; + var formattedBasePath = "/iiif/v3/" + ImageServerUtil.getImageServerEncodedId(pidString); var filename = "bunny.jpg"; when(accessControlService.hasAccess(any(), any(), any())).thenReturn(true); stubFor(WireMock.get(urlMatching(formattedBasePath + "/full/max/0/default.jpg")) @@ -111,7 +110,7 @@ void getMetadataTestNoAccess() throws Exception { void getMetadataTest() throws Exception { var pid = makePid(); var pidString = pid.getId(); - var formattedBasePath = "/iiif/v3/" + imageServerProxyService.getImageServerEncodedId(pidString) + ".jp2"; + var formattedBasePath = "/iiif/v3/" + ImageServerUtil.getImageServerEncodedId(pidString); var json = "{\"@context\":\"http://iiif.io/api/image/3/context.json\",\"id\":\"http://example.com/iiif/v3/" + pidString + "\",\"type\":\"ImageService3\",\"protocol\":\"http://iiif.io/api/image\"}"; when(accessControlService.hasAccess(any(), any(), any())).thenReturn(true);