Loading pom.xml +3 −0 Original line number Diff line number Diff line Loading @@ -148,6 +148,9 @@ <plugin> <artifactId>maven-surefire-plugin</artifactId> <version>2.22.2</version> <configuration> <trimStackTrace>false</trimStackTrace> </configuration> </plugin> <plugin> <groupId>org.springframework.boot</groupId> Loading src/main/java/it/inaf/ia2/transfer/controller/ArchiveFileController.java +32 −11 Original line number Diff line number Diff line Loading @@ -7,15 +7,21 @@ package it.inaf.ia2.transfer.controller; import it.inaf.ia2.transfer.auth.TokenPrincipal; import it.inaf.ia2.transfer.service.ArchiveJob; import it.inaf.ia2.transfer.service.ArchiveJob.Type; import it.inaf.ia2.transfer.service.ArchiveService; import java.util.List; import java.io.File; import java.util.concurrent.CompletableFuture; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.http.HttpHeaders; import org.springframework.http.HttpStatus; import org.springframework.http.MediaType; import org.springframework.http.ResponseEntity; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.PathVariable; import org.springframework.web.bind.annotation.PostMapping; import org.springframework.web.bind.annotation.RequestBody; import org.springframework.web.bind.annotation.RequestParam; import org.springframework.web.bind.annotation.RestController; @RestController Loading @@ -27,21 +33,36 @@ public class ArchiveFileController { @Autowired private HttpServletRequest request; @PostMapping(value = "/tar", consumes = MediaType.APPLICATION_JSON_VALUE) public void createTarArchive(@RequestParam(value = "jobId", required = true) String jobId, @RequestBody List<String> vosPaths) { @Autowired private HttpServletResponse response; @PostMapping(value = "/archive", consumes = MediaType.APPLICATION_JSON_VALUE) public ResponseEntity<?> createArchiveFile(@RequestBody ArchiveRequest archiveRequest) { Type type = Type.valueOf(archiveRequest.getType()); ArchiveJob job = new ArchiveJob(); job.setPrincipal((TokenPrincipal) request.getUserPrincipal()); job.setJobId(jobId); job.setType(ArchiveJob.Type.TAR); job.setVosPaths(vosPaths); job.setJobId(archiveRequest.getJobId()); job.setType(type); job.setVosPaths(archiveRequest.getPaths()); startArchiveJob(job); } private void startArchiveJob(ArchiveJob job) { CompletableFuture.runAsync(() -> { archiveService.createArchive(job); }); HttpHeaders headers = new HttpHeaders(); headers.set("Location", request.getRequestURL() + "/" + archiveRequest.getJobId() + "." + type.getExtension()); return new ResponseEntity<>(headers, HttpStatus.SEE_OTHER); } @GetMapping(value = "/archive/{fileName}") public ResponseEntity<?> getArchiveFile(@PathVariable("fileName") String fileName) { TokenPrincipal principal = (TokenPrincipal) request.getUserPrincipal(); File file = archiveService.getArchiveParentDir(principal).toPath().resolve(fileName).toFile(); return FileResponseUtil.getFileResponse(response, file); } } src/main/java/it/inaf/ia2/transfer/controller/ArchiveRequest.java +27 −4 Original line number Diff line number Diff line Loading @@ -3,14 +3,37 @@ * Copyright (C) 2021 Istituto Nazionale di Astrofisica * SPDX-License-Identifier: GPL-3.0-or-later */ package it.inaf.ia2.transfer.controller; import java.util.List; public class ArchiveRequest { private List<String> vosPaths; String jobId; String type; private String type; private String jobId; private List<String> paths; public String getType() { return type; } public void setType(String type) { this.type = type; } public String getJobId() { return jobId; } public void setJobId(String jobId) { this.jobId = jobId; } public List<String> getPaths() { return paths; } public void setPaths(List<String> paths) { this.paths = paths; } } src/main/java/it/inaf/ia2/transfer/controller/FileResponseUtil.java 0 → 100644 +59 −0 Original line number Diff line number Diff line /* * This file is part of vospace-file-service * Copyright (C) 2021 Istituto Nazionale di Astrofisica * SPDX-License-Identifier: GPL-3.0-or-later */ package it.inaf.ia2.transfer.controller; import java.io.File; import java.io.FileInputStream; import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; import java.io.UncheckedIOException; import java.net.URLEncoder; import java.nio.charset.StandardCharsets; import javax.servlet.http.HttpServletResponse; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import static org.springframework.http.HttpStatus.INTERNAL_SERVER_ERROR; import static org.springframework.http.HttpStatus.NOT_FOUND; import org.springframework.http.ResponseEntity; public class FileResponseUtil { private static final Logger LOG = LoggerFactory.getLogger(FileResponseUtil.class); public static ResponseEntity<?> getFileResponse(HttpServletResponse response, File file) { return getFileResponse(response, file, null); } public static ResponseEntity<?> getFileResponse(HttpServletResponse response, File file, String fileName) { if (!file.exists()) { LOG.error("File not found: " + file.getAbsolutePath()); return new ResponseEntity<>("File " + file.getName() + " not found", NOT_FOUND); } if (!file.canRead()) { LOG.error("File not readable: " + file.getAbsolutePath()); return new ResponseEntity<>("File " + file.getName() + " is not readable", INTERNAL_SERVER_ERROR); } response.setHeader("Content-Disposition", "attachment; filename=" + URLEncoder.encode(fileName == null ? file.getName() : fileName, StandardCharsets.UTF_8)); response.setHeader("Content-Length", String.valueOf(file.length())); response.setCharacterEncoding("UTF-8"); byte[] bytes = new byte[1024]; try ( OutputStream out = response.getOutputStream(); InputStream is = new FileInputStream(file)) { int read; while ((read = is.read(bytes)) != -1) { out.write(bytes, 0, read); } } catch (IOException ex) { throw new UncheckedIOException(ex); } return null; } } src/main/java/it/inaf/ia2/transfer/controller/GetFileController.java +3 −35 Original line number Diff line number Diff line Loading @@ -10,19 +10,11 @@ import it.inaf.ia2.transfer.auth.TokenPrincipal; import it.inaf.ia2.transfer.persistence.FileDAO; import it.inaf.ia2.transfer.service.AuthorizationService; import java.io.File; import java.io.FileInputStream; import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; import java.io.UncheckedIOException; import java.net.URLEncoder; import java.nio.charset.StandardCharsets; import java.util.Optional; import javax.servlet.http.HttpServletResponse; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.beans.factory.annotation.Autowired; import static org.springframework.http.HttpStatus.INTERNAL_SERVER_ERROR; import static org.springframework.http.HttpStatus.NOT_FOUND; import static org.springframework.http.HttpStatus.UNAUTHORIZED; import org.springframework.http.ResponseEntity; Loading Loading @@ -69,33 +61,9 @@ public class GetFileController extends FileController { private ResponseEntity<?> getFileResponse(FileInfo fileInfo) { File file = new File(fileInfo.getOsPath()); String vosName = fileInfo.getVirtualPath() == null ? null : fileInfo.getVirtualPath().substring(fileInfo.getVirtualPath().lastIndexOf("/") + 1); if (!file.exists()) { LOG.error("File not found: " + file.getAbsolutePath()); return new ResponseEntity<>("File " + file.getName() + " not found", NOT_FOUND); } if (!file.canRead()) { LOG.error("File not readable: " + file.getAbsolutePath()); return new ResponseEntity<>("File " + file.getName() + " is not readable", INTERNAL_SERVER_ERROR); } String vosName = fileInfo.getVirtualPath().substring(fileInfo.getVirtualPath().lastIndexOf("/") + 1); response.setHeader("Content-Disposition", "attachment; filename=" + URLEncoder.encode(vosName, StandardCharsets.UTF_8)); response.setHeader("Content-Length", String.valueOf(file.length())); response.setCharacterEncoding("UTF-8"); byte[] bytes = new byte[1024]; try (OutputStream out = response.getOutputStream(); InputStream is = new FileInputStream(file)) { int read; while ((read = is.read(bytes)) != -1) { out.write(bytes, 0, read); } } catch (IOException ex) { throw new UncheckedIOException(ex); } return null; return FileResponseUtil.getFileResponse(response, file, vosName); } } Loading
pom.xml +3 −0 Original line number Diff line number Diff line Loading @@ -148,6 +148,9 @@ <plugin> <artifactId>maven-surefire-plugin</artifactId> <version>2.22.2</version> <configuration> <trimStackTrace>false</trimStackTrace> </configuration> </plugin> <plugin> <groupId>org.springframework.boot</groupId> Loading
src/main/java/it/inaf/ia2/transfer/controller/ArchiveFileController.java +32 −11 Original line number Diff line number Diff line Loading @@ -7,15 +7,21 @@ package it.inaf.ia2.transfer.controller; import it.inaf.ia2.transfer.auth.TokenPrincipal; import it.inaf.ia2.transfer.service.ArchiveJob; import it.inaf.ia2.transfer.service.ArchiveJob.Type; import it.inaf.ia2.transfer.service.ArchiveService; import java.util.List; import java.io.File; import java.util.concurrent.CompletableFuture; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.http.HttpHeaders; import org.springframework.http.HttpStatus; import org.springframework.http.MediaType; import org.springframework.http.ResponseEntity; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.PathVariable; import org.springframework.web.bind.annotation.PostMapping; import org.springframework.web.bind.annotation.RequestBody; import org.springframework.web.bind.annotation.RequestParam; import org.springframework.web.bind.annotation.RestController; @RestController Loading @@ -27,21 +33,36 @@ public class ArchiveFileController { @Autowired private HttpServletRequest request; @PostMapping(value = "/tar", consumes = MediaType.APPLICATION_JSON_VALUE) public void createTarArchive(@RequestParam(value = "jobId", required = true) String jobId, @RequestBody List<String> vosPaths) { @Autowired private HttpServletResponse response; @PostMapping(value = "/archive", consumes = MediaType.APPLICATION_JSON_VALUE) public ResponseEntity<?> createArchiveFile(@RequestBody ArchiveRequest archiveRequest) { Type type = Type.valueOf(archiveRequest.getType()); ArchiveJob job = new ArchiveJob(); job.setPrincipal((TokenPrincipal) request.getUserPrincipal()); job.setJobId(jobId); job.setType(ArchiveJob.Type.TAR); job.setVosPaths(vosPaths); job.setJobId(archiveRequest.getJobId()); job.setType(type); job.setVosPaths(archiveRequest.getPaths()); startArchiveJob(job); } private void startArchiveJob(ArchiveJob job) { CompletableFuture.runAsync(() -> { archiveService.createArchive(job); }); HttpHeaders headers = new HttpHeaders(); headers.set("Location", request.getRequestURL() + "/" + archiveRequest.getJobId() + "." + type.getExtension()); return new ResponseEntity<>(headers, HttpStatus.SEE_OTHER); } @GetMapping(value = "/archive/{fileName}") public ResponseEntity<?> getArchiveFile(@PathVariable("fileName") String fileName) { TokenPrincipal principal = (TokenPrincipal) request.getUserPrincipal(); File file = archiveService.getArchiveParentDir(principal).toPath().resolve(fileName).toFile(); return FileResponseUtil.getFileResponse(response, file); } }
src/main/java/it/inaf/ia2/transfer/controller/ArchiveRequest.java +27 −4 Original line number Diff line number Diff line Loading @@ -3,14 +3,37 @@ * Copyright (C) 2021 Istituto Nazionale di Astrofisica * SPDX-License-Identifier: GPL-3.0-or-later */ package it.inaf.ia2.transfer.controller; import java.util.List; public class ArchiveRequest { private List<String> vosPaths; String jobId; String type; private String type; private String jobId; private List<String> paths; public String getType() { return type; } public void setType(String type) { this.type = type; } public String getJobId() { return jobId; } public void setJobId(String jobId) { this.jobId = jobId; } public List<String> getPaths() { return paths; } public void setPaths(List<String> paths) { this.paths = paths; } }
src/main/java/it/inaf/ia2/transfer/controller/FileResponseUtil.java 0 → 100644 +59 −0 Original line number Diff line number Diff line /* * This file is part of vospace-file-service * Copyright (C) 2021 Istituto Nazionale di Astrofisica * SPDX-License-Identifier: GPL-3.0-or-later */ package it.inaf.ia2.transfer.controller; import java.io.File; import java.io.FileInputStream; import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; import java.io.UncheckedIOException; import java.net.URLEncoder; import java.nio.charset.StandardCharsets; import javax.servlet.http.HttpServletResponse; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import static org.springframework.http.HttpStatus.INTERNAL_SERVER_ERROR; import static org.springframework.http.HttpStatus.NOT_FOUND; import org.springframework.http.ResponseEntity; public class FileResponseUtil { private static final Logger LOG = LoggerFactory.getLogger(FileResponseUtil.class); public static ResponseEntity<?> getFileResponse(HttpServletResponse response, File file) { return getFileResponse(response, file, null); } public static ResponseEntity<?> getFileResponse(HttpServletResponse response, File file, String fileName) { if (!file.exists()) { LOG.error("File not found: " + file.getAbsolutePath()); return new ResponseEntity<>("File " + file.getName() + " not found", NOT_FOUND); } if (!file.canRead()) { LOG.error("File not readable: " + file.getAbsolutePath()); return new ResponseEntity<>("File " + file.getName() + " is not readable", INTERNAL_SERVER_ERROR); } response.setHeader("Content-Disposition", "attachment; filename=" + URLEncoder.encode(fileName == null ? file.getName() : fileName, StandardCharsets.UTF_8)); response.setHeader("Content-Length", String.valueOf(file.length())); response.setCharacterEncoding("UTF-8"); byte[] bytes = new byte[1024]; try ( OutputStream out = response.getOutputStream(); InputStream is = new FileInputStream(file)) { int read; while ((read = is.read(bytes)) != -1) { out.write(bytes, 0, read); } } catch (IOException ex) { throw new UncheckedIOException(ex); } return null; } }
src/main/java/it/inaf/ia2/transfer/controller/GetFileController.java +3 −35 Original line number Diff line number Diff line Loading @@ -10,19 +10,11 @@ import it.inaf.ia2.transfer.auth.TokenPrincipal; import it.inaf.ia2.transfer.persistence.FileDAO; import it.inaf.ia2.transfer.service.AuthorizationService; import java.io.File; import java.io.FileInputStream; import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; import java.io.UncheckedIOException; import java.net.URLEncoder; import java.nio.charset.StandardCharsets; import java.util.Optional; import javax.servlet.http.HttpServletResponse; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.beans.factory.annotation.Autowired; import static org.springframework.http.HttpStatus.INTERNAL_SERVER_ERROR; import static org.springframework.http.HttpStatus.NOT_FOUND; import static org.springframework.http.HttpStatus.UNAUTHORIZED; import org.springframework.http.ResponseEntity; Loading Loading @@ -69,33 +61,9 @@ public class GetFileController extends FileController { private ResponseEntity<?> getFileResponse(FileInfo fileInfo) { File file = new File(fileInfo.getOsPath()); String vosName = fileInfo.getVirtualPath() == null ? null : fileInfo.getVirtualPath().substring(fileInfo.getVirtualPath().lastIndexOf("/") + 1); if (!file.exists()) { LOG.error("File not found: " + file.getAbsolutePath()); return new ResponseEntity<>("File " + file.getName() + " not found", NOT_FOUND); } if (!file.canRead()) { LOG.error("File not readable: " + file.getAbsolutePath()); return new ResponseEntity<>("File " + file.getName() + " is not readable", INTERNAL_SERVER_ERROR); } String vosName = fileInfo.getVirtualPath().substring(fileInfo.getVirtualPath().lastIndexOf("/") + 1); response.setHeader("Content-Disposition", "attachment; filename=" + URLEncoder.encode(vosName, StandardCharsets.UTF_8)); response.setHeader("Content-Length", String.valueOf(file.length())); response.setCharacterEncoding("UTF-8"); byte[] bytes = new byte[1024]; try (OutputStream out = response.getOutputStream(); InputStream is = new FileInputStream(file)) { int read; while ((read = is.read(bytes)) != -1) { out.write(bytes, 0, read); } } catch (IOException ex) { throw new UncheckedIOException(ex); } return null; return FileResponseUtil.getFileResponse(response, file, vosName); } }