diff --git a/docs-core/src/main/java/com/sismics/util/mime/MimeTypeUtil.java b/docs-core/src/main/java/com/sismics/util/mime/MimeTypeUtil.java index f87f01a2..a8c1565b 100644 --- a/docs-core/src/main/java/com/sismics/util/mime/MimeTypeUtil.java +++ b/docs-core/src/main/java/com/sismics/util/mime/MimeTypeUtil.java @@ -1,7 +1,6 @@ package com.sismics.util.mime; import java.io.InputStream; -import java.io.PushbackInputStream; /** * Utility to check MIME types. @@ -18,9 +17,9 @@ public class MimeTypeUtil { */ public static String guessMimeType(InputStream is) throws Exception { byte[] headerBytes = new byte[64]; - PushbackInputStream pb = new PushbackInputStream(is, headerBytes.length); - int readCount = pb.read(headerBytes); - pb.unread(headerBytes); + is.mark(headerBytes.length); + int readCount = is.read(headerBytes); + is.reset(); if (readCount <= 0) { throw new Exception("Cannot read input file"); diff --git a/docs-web/src/main/java/com/sismics/docs/rest/resource/DocumentResource.java b/docs-web/src/main/java/com/sismics/docs/rest/resource/DocumentResource.java index 342a99b3..40fc896c 100644 --- a/docs-web/src/main/java/com/sismics/docs/rest/resource/DocumentResource.java +++ b/docs-web/src/main/java/com/sismics/docs/rest/resource/DocumentResource.java @@ -46,9 +46,10 @@ public class DocumentResource extends BaseResource { * @throws JSONException */ @GET + @Path("{id: [a-z0-9\\-]+}") @Produces(MediaType.APPLICATION_JSON) public Response get( - @QueryParam("id") String id) throws JSONException { + @PathParam("id") String id) throws JSONException { if (!authenticate()) { throw new ForbiddenClientException(); } @@ -190,7 +191,7 @@ public class DocumentResource extends BaseResource { // Always return ok JSONObject response = new JSONObject(); - response.put("status", "ok"); + response.put("id", id); return Response.ok().entity(response).build(); } diff --git a/docs-web/src/main/java/com/sismics/docs/rest/resource/FileResource.java b/docs-web/src/main/java/com/sismics/docs/rest/resource/FileResource.java index 317ef3f8..e75f4683 100644 --- a/docs-web/src/main/java/com/sismics/docs/rest/resource/FileResource.java +++ b/docs-web/src/main/java/com/sismics/docs/rest/resource/FileResource.java @@ -1,6 +1,11 @@ package com.sismics.docs.rest.resource; +import java.io.BufferedInputStream; +import java.io.FileInputStream; +import java.io.FilenameFilter; +import java.io.IOException; import java.io.InputStream; +import java.io.OutputStream; import java.nio.file.Files; import java.nio.file.Paths; import java.text.MessageFormat; @@ -18,10 +23,12 @@ import javax.ws.rs.Produces; import javax.ws.rs.QueryParam; import javax.ws.rs.core.MediaType; import javax.ws.rs.core.Response; +import javax.ws.rs.core.StreamingOutput; import org.codehaus.jettison.json.JSONException; import org.codehaus.jettison.json.JSONObject; +import com.google.common.io.ByteStreams; import com.sismics.docs.core.dao.jpa.DocumentDao; import com.sismics.docs.core.dao.jpa.FileDao; import com.sismics.docs.core.model.jpa.Document; @@ -42,61 +49,6 @@ import com.sun.jersey.multipart.FormDataParam; */ @Path("/file") public class FileResource extends BaseResource { - /** - * Add a file to a document. - * - * @param id Document ID - * @param fileBodyPart File to add - * @return Response - * @throws JSONException - */ - @PUT - @Consumes("multipart/form-data") - @Produces(MediaType.APPLICATION_JSON) - public Response add( - @FormDataParam("id") String documentId, - @FormDataParam("file") FormDataBodyPart fileBodyPart) throws JSONException { - if (!authenticate()) { - throw new ForbiddenClientException(); - } - - // Validate input data - ValidationUtil.validateRequired(documentId, "id"); - ValidationUtil.validateRequired(fileBodyPart, "file"); - - // Get the document - DocumentDao documentDao = new DocumentDao(); - Document document = null; - try { - document = documentDao.getDocument(documentId, principal.getId()); - } catch (NoResultException e) { - throw new ClientException("DocumentNotFound", MessageFormat.format("Document not found: {0}", documentId)); - } - - - FileDao fileDao = new FileDao(); - - InputStream is = fileBodyPart.getValueAs(InputStream.class); - try { - // Create the file - File file = new File(); - file.setDocumentId(document.getId()); - file.setMimeType(MimeTypeUtil.guessMimeType(is)); - String fileId = fileDao.create(file); - - // Copy the incoming stream content into the storage directory - Files.copy(is, Paths.get(DirectoryUtil.getStorageDirectory().getPath(), fileId)); - - // Always return ok - JSONObject response = new JSONObject(); - response.put("status", "ok"); - response.put("id", fileId); - return Response.ok().entity(response).build(); - } catch (Exception e) { - throw new ServerException("FileError", "Error adding a file", e); - } - } - /** * Returns a file. * @@ -129,6 +81,71 @@ public class FileResource extends BaseResource { return Response.ok().entity(file).build(); } + /** + * Add a file to a document. + * + * @param id Document ID + * @param fileBodyPart File to add + * @return Response + * @throws JSONException + */ + @PUT + @Consumes("multipart/form-data") + @Produces(MediaType.APPLICATION_JSON) + public Response add( + @FormDataParam("id") String documentId, + @FormDataParam("file") FormDataBodyPart fileBodyPart) throws JSONException { + if (!authenticate()) { + throw new ForbiddenClientException(); + } + + // Validate input data + ValidationUtil.validateRequired(documentId, "id"); + ValidationUtil.validateRequired(fileBodyPart, "file"); + + // Get the document + DocumentDao documentDao = new DocumentDao(); + Document document = null; + try { + document = documentDao.getDocument(documentId, principal.getId()); + } catch (NoResultException e) { + throw new ClientException("DocumentNotFound", MessageFormat.format("Document not found: {0}", documentId)); + } + + FileDao fileDao = new FileDao(); + + // Validate mime type + InputStream is = new BufferedInputStream(fileBodyPart.getValueAs(InputStream.class)); + String mimeType = null; + try { + mimeType = MimeTypeUtil.guessMimeType(is); + } catch (Exception e) { + throw new ServerException("ErrorGuessMime", "Error guessing mime type", e); + } + if (mimeType == null) { + throw new ClientException("InvalidFileType", "File type not recognized"); + } + + try { + // Create the file + File file = new File(); + file.setDocumentId(document.getId()); + file.setMimeType(mimeType); + String fileId = fileDao.create(file); + + // Copy the incoming stream content into the storage directory + Files.copy(is, Paths.get(DirectoryUtil.getStorageDirectory().getPath(), fileId)); + + // Always return ok + JSONObject response = new JSONObject(); + response.put("status", "ok"); + response.put("id", fileId); + return Response.ok().entity(response).build(); + } catch (Exception e) { + throw new ServerException("FileError", "Error adding a file", e); + } + } + /** * Returns files linked to a document. * @@ -197,4 +214,42 @@ public class FileResource extends BaseResource { response.put("status", "ok"); return Response.ok().entity(response).build(); } + + /** + * Returns a file. + * + * @param id File ID + * @return Response + * @throws JSONException + */ + @GET + @Path("{id: [a-z0-9\\-]+}/data") + @Produces(MediaType.APPLICATION_OCTET_STREAM) + public Response data( + @PathParam("id") final String id) throws JSONException { + if (!authenticate()) { + throw new ForbiddenClientException(); + } + + // Get the file + java.io.File storageDirectory = DirectoryUtil.getStorageDirectory(); + java.io.File[] matchingFiles = storageDirectory.listFiles(new FilenameFilter() { + @Override + public boolean accept(java.io.File dir, String name) { + return name.startsWith(id); + } + }); + final java.io.File storageFile = matchingFiles[0]; + + // Stream the file to the response + StreamingOutput stream = new StreamingOutput() { + @Override + public void write(OutputStream os) throws IOException { + ByteStreams.copy(new FileInputStream(storageFile), os); + } + }; + return Response.ok(stream) + .header("Content-Disposition", MessageFormat.format("attachment; filename=\"{0}\"", storageFile.getName())) + .build(); + } } diff --git a/docs-web/src/main/webapp/.gitignore b/docs-web/src/main/webapp/.gitignore new file mode 100644 index 00000000..3fcc60d9 --- /dev/null +++ b/docs-web/src/main/webapp/.gitignore @@ -0,0 +1 @@ +/sismicsdocs diff --git a/docs-web/src/main/webapp/index.html b/docs-web/src/main/webapp/index.html index f1a3e315..72da63f3 100644 --- a/docs-web/src/main/webapp/index.html +++ b/docs-web/src/main/webapp/index.html @@ -18,16 +18,21 @@ + + + + +