package com.mcb; import com.mcb.base.SparkFilter; import org.apache.commons.fileupload.FileItem; import org.apache.commons.fileupload.disk.DiskFileItemFactory; import org.apache.commons.fileupload.servlet.ServletFileUpload; import org.apache.commons.io.FilenameUtils; import spark.Response; import spark.utils.StringUtils; import javax.activation.FileTypeMap; import javax.activation.MimetypesFileTypeMap; import javax.servlet.http.HttpServletResponse; import java.io.IOException; import java.io.OutputStream; import java.nio.file.Files; import java.nio.file.Path; import java.nio.file.Paths; import java.util.List; import java.util.logging.Level; import java.util.stream.Collectors; import java.util.stream.Stream; import static spark.Spark.*; /** * Created by matthewb on 10/13/15. */ public class HttpFiles extends SparkFilter { public void setup() { DiskFileItemFactory factory = new DiskFileItemFactory(); ServletFileUpload fileUpload = new ServletFileUpload(factory); String httpFilesRoute = "/" + this.getCfg().routeName() + "/files"; log().info("Adding route: " + httpFilesRoute); final Path filesRoot = Paths.get(this.getCfg().filesRoot()); get(httpFilesRoute, (req, res) -> { if (lazyCheck(filesRoot)) { List<File> v = Files.walk(filesRoot) .map(a -> { return filesRoot.relativize(a).toString(); }) .filter(a -> spark.utils.StringUtils.isNotEmpty(a)) .map(a -> { log().info(a); File f = new File(); f.setPath(a); return f; }) .collect(Collectors.toList()); res.body(this.getGson().toJson(v)); return res.body(); } return errorPathNotExist(filesRoot, res).body(); }); put(httpFilesRoute + "/*", (req, res) -> { if (lazyCheck(filesRoot)) { String part = Stream.of(req.splat()) .distinct() .findFirst() .get(); if (!StringUtils.isEmpty(part)) { Path path = filesRoot.resolve(part); String ext = FilenameUtils.getExtension(path.toString()); if (!StringUtils.isEmpty(ext)) { //Is directory path path = path.getParent(); } StringBuilder outBody = new StringBuilder(); List<FileItem> items = fileUpload.parseRequest(req.raw()); final Path dir = path; items.stream() .forEach(file -> { log().info(file.getName()); final Path savePath = dir.resolve(file.getName()); if (!Files.exists(savePath.getParent())) { try { Files.createDirectories(savePath.getParent()); log().info("Created directory " + savePath.getParent().toString()); outBody.append("Created directory " + savePath.getParent().toString()); outBody.append(System.lineSeparator()); } catch (IOException e) { e.printStackTrace(); } } try { Files.write(savePath, file.get()); log().info("Saved file " + savePath.toString() + "."); outBody.append("Saved file " + savePath.toString() + "."); outBody.append(System.lineSeparator()); } catch (IOException e) { e.printStackTrace(); } }); res.body(outBody.toString()); return res.body(); } } return errorPathNotExist(filesRoot, res).body(); }); post(httpFilesRoute + "/*", (req, res) -> { if (lazyCheck(filesRoot)) { String part = Stream.of(req.splat()) .distinct() .findFirst() .get(); if (!StringUtils.isEmpty(part)) { Path path = filesRoot.resolve(part); String ext = FilenameUtils.getExtension(path.toString()); if (!StringUtils.isEmpty(ext)) { //Is directory path path = path.getParent(); } StringBuilder outBody = new StringBuilder(); List<FileItem> items = fileUpload.parseRequest(req.raw()); final Path dir = path; items.stream() .forEach(file -> { log().info(file.getName()); final Path savePath = dir.resolve(file.getName()); if (!Files.exists(savePath.getParent())) { try { Files.createDirectories(savePath.getParent()); log().info("Created directory " + savePath.getParent().toString()); outBody.append("Created directory " + savePath.getParent().toString()); outBody.append(System.lineSeparator()); } catch (IOException e) { e.printStackTrace(); } } try { Files.write(savePath, file.get()); log().info("Saved file " + savePath.toString() + "."); outBody.append("Saved file " + savePath.toString() + "."); outBody.append(System.lineSeparator()); } catch (IOException e) { e.printStackTrace(); } }); res.body(outBody.toString()); return res.body(); } } return errorPathNotExist(filesRoot, res).body(); }); get(httpFilesRoute + "/*", (req, res) -> { if (lazyCheck(filesRoot)) { String part = Stream.of(req.splat()) .distinct() .findFirst() .get(); byte[] bytes = null; if (!StringUtils.isEmpty(part)) { Path path = Paths.get(part); if (Files.exists(filesRoot.resolve(path))) { bytes = Files.readAllBytes(filesRoot.resolve(path)); String ct = MimetypesFileTypeMap.getDefaultFileTypeMap().getContentType(filesRoot.resolve(path).toFile()); FileTypeMap map = MimetypesFileTypeMap.getDefaultFileTypeMap(); log().info("Content-Type: " + ct); res.type(ct); } } if (bytes != null) { try (OutputStream os = res.raw().getOutputStream()) { os.write(bytes); } catch (IOException e) { halt(HttpServletResponse.SC_INTERNAL_SERVER_ERROR); } return res.raw(); } } return errorPathNotExist(filesRoot, res).body(); }); } private Response errorPathNotExist(Path path, Response res) { res.status(HttpServletResponse.SC_EXPECTATION_FAILED); res.body(path.toString() + " does not exist."); return res; } private boolean lazyCheck(Path dir) { boolean result = false; if (Files.isDirectory(dir)) { result = true; } else if (!Files.exists(dir)) { try { Path createdDir = Files.createDirectories(dir); if (Files.isDirectory(createdDir)) { result = true; } } catch (IOException e) { if (log().isLoggable(Level.FINER)) { log().log(Level.FINER, e.getLocalizedMessage(), e); } else { log().log(Level.WARNING, e.getLocalizedMessage()); } } } return result; } private static class File { private String path; public String getPath() { return path; } public void setPath(String path) { this.path = path; } } }