diff --git a/src/main/java/org/olat/core/util/vfs/restapi/VFSWebservice.java b/src/main/java/org/olat/core/util/vfs/restapi/VFSWebservice.java index 338fb9cb8d41d8c21a8f0caa7d4066c33b6cf575..f40fd510c6b62812cdd03fa8764f0c99e26a9037 100644 --- a/src/main/java/org/olat/core/util/vfs/restapi/VFSWebservice.java +++ b/src/main/java/org/olat/core/util/vfs/restapi/VFSWebservice.java @@ -20,6 +20,7 @@ */ package org.olat.core.util.vfs.restapi; +import java.io.ByteArrayInputStream; import java.io.InputStream; import java.io.OutputStream; import java.text.Normalizer; @@ -46,6 +47,7 @@ import javax.ws.rs.core.Response.Status; import javax.ws.rs.core.UriBuilder; import javax.ws.rs.core.UriInfo; +import org.apache.commons.codec.binary.Base64; import org.olat.core.util.FileUtils; import org.olat.core.util.StringHelper; import org.olat.core.util.WebappHelper; @@ -134,6 +136,27 @@ public class VFSWebservice { return putFile(foldername, filename, file, uriInfo, Collections.<PathSegment>emptyList()); } + /** + * Upload a file to the root folder or create a new folder. One of the two sets + * of parameters must be set: foldername to create + * @response.representation.200.doc The link to the created file + * @response.representation.200.qname {http://www.example.com}linkVO + * @param foldername The name of the new folder (optional) + * @param filename The name of the file (optional) + * @param file The content of the file (encoded with Base64) + * @param uriInfo The uri infos + * @return The link to the created file + */ + @POST + @Consumes(MediaType.APPLICATION_FORM_URLENCODED) + @Produces({MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML}) + public Response postFile64ToRoot(@FormParam("foldername") String foldername, @FormParam("filename") String filename, + @FormParam("file") String file, @Context UriInfo uriInfo) { + byte[] fileAsBytes = Base64.decodeBase64(file); + InputStream in = new ByteArrayInputStream(fileAsBytes); + return putFile(foldername, filename, in, uriInfo, Collections.<PathSegment>emptyList()); + } + /** * Upload a file to the specified folder or create a new folder * @response.representation.200.doc The link to the created file @@ -154,6 +177,28 @@ public class VFSWebservice { return putFile(foldername, filename, file, uriInfo, path); } + /** + * Upload a file to the specified folder or create a new folder + * @response.representation.200.doc The link to the created file + * @response.representation.200.qname {http://www.example.com}linkVO + * @param foldername The name of the new folder (optional) + * @param filename The name of the file (optional) + * @param file The content of the file (encoded with Base64) + * @param uriInfo The uri infos + * @param path The path to the folder + * @return The link to the created file + */ + @POST + @Path("{path:.*}") + @Consumes(MediaType.APPLICATION_FORM_URLENCODED) + @Produces({"*/*", MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML}) + public Response postFile64ToFolder(@FormParam("foldername") String foldername, @FormParam("filename") String filename, + @FormParam("file") String file, @Context UriInfo uriInfo, @PathParam("path") List<PathSegment> path) { + byte[] fileAsBytes = Base64.decodeBase64(file); + InputStream in = new ByteArrayInputStream(fileAsBytes); + return putFile(foldername, filename, in, uriInfo, path); + } + /** * Upload a file to the root folder or create a new folder * @response.representation.200.doc The link to the created file diff --git a/src/main/java/org/olat/modules/fo/restapi/ForumWebService.java b/src/main/java/org/olat/modules/fo/restapi/ForumWebService.java index e535ce5b4e9eb81e8be1f28a6a3d58df546ddf12..97e4710c44b4a69507ec107b90b3c3ac3f2dbf3b 100644 --- a/src/main/java/org/olat/modules/fo/restapi/ForumWebService.java +++ b/src/main/java/org/olat/modules/fo/restapi/ForumWebService.java @@ -24,6 +24,7 @@ package org.olat.modules.fo.restapi; import static org.olat.restapi.security.RestSecurityHelper.getIdentity; import static org.olat.restapi.security.RestSecurityHelper.isAdmin; +import java.io.ByteArrayInputStream; import java.io.File; import java.io.IOException; import java.io.InputStream; @@ -53,6 +54,7 @@ import javax.ws.rs.core.Response.Status; import javax.ws.rs.core.StreamingOutput; import javax.ws.rs.core.UriInfo; +import org.apache.commons.codec.binary.Base64; import org.apache.commons.io.IOUtils; import org.olat.basesecurity.BaseSecurity; import org.olat.basesecurity.BaseSecurityManager; @@ -440,6 +442,28 @@ public class ForumWebService { return attachToPost(messageKey, filename, file, request); } + /** + * Upload the attachment of a message + * @response.representation.200.mediaType application/json, application/xml + * @response.representation.200.doc Ok + * @response.representation.404.doc The identity or the portrait not found + * @param messageKey The key of the message + * @param filename The name of the attachment + * @file file64 The attachment (encoded as Base64) + * @param request The HTTP request + * @return Ok + */ + @POST + @Path("posts/{messageKey}/attachments") + @Consumes(MediaType.APPLICATION_FORM_URLENCODED) + @Produces({MediaType.APPLICATION_XML, MediaType.APPLICATION_JSON}) + public Response replyToPostAttachment(@PathParam("messageKey") Long messageKey, @FormParam("filename") String filename, + @FormParam("file") String file, @Context HttpServletRequest request) { + byte[] fileAsBytes = Base64.decodeBase64(file); + InputStream in = new ByteArrayInputStream(fileAsBytes); + return attachToPost(messageKey, filename, in, request); + } + protected Response attachToPost(Long messageKey, String filename, InputStream file, HttpServletRequest request) { //load message Message mess = fom.loadMessage(messageKey); diff --git a/src/test/java/org/olat/restapi/ForumTest.java b/src/test/java/org/olat/restapi/ForumTest.java index 041e5ecc45e2fc9c83c0818c4c0ac3fe061e17ca..c85c7a141911ab646ad0945aabbfa11a4fb79b46 100644 --- a/src/test/java/org/olat/restapi/ForumTest.java +++ b/src/test/java/org/olat/restapi/ForumTest.java @@ -26,6 +26,7 @@ import static org.junit.Assert.assertFalse; import static org.junit.Assert.assertNotNull; import static org.junit.Assert.assertTrue; +import java.awt.image.BufferedImage; import java.io.File; import java.io.IOException; import java.io.InputStream; @@ -34,9 +35,11 @@ import java.net.URISyntaxException; import java.net.URL; import java.util.List; +import javax.imageio.ImageIO; import javax.ws.rs.core.MediaType; import javax.ws.rs.core.UriBuilder; +import org.apache.commons.codec.binary.Base64; import org.apache.commons.httpclient.HttpClient; import org.apache.commons.httpclient.methods.GetMethod; import org.apache.commons.httpclient.methods.PostMethod; @@ -45,12 +48,17 @@ import org.apache.commons.httpclient.methods.multipart.FilePart; import org.apache.commons.httpclient.methods.multipart.MultipartRequestEntity; import org.apache.commons.httpclient.methods.multipart.Part; import org.apache.commons.httpclient.methods.multipart.StringPart; +import org.apache.commons.io.IOUtils; import org.codehaus.jackson.map.ObjectMapper; import org.codehaus.jackson.type.TypeReference; import org.junit.Before; import org.junit.Test; import org.olat.core.commons.persistence.DBFactory; import org.olat.core.id.Identity; +import org.olat.core.util.FileUtils; +import org.olat.core.util.vfs.VFSContainer; +import org.olat.core.util.vfs.VFSItem; +import org.olat.core.util.vfs.VFSLeaf; import org.olat.modules.fo.Forum; import org.olat.modules.fo.ForumManager; import org.olat.modules.fo.Message; @@ -263,7 +271,7 @@ public class ForumTest extends OlatJerseyTestCase { File portrait = new File(portraitUrl.toURI()); //upload portrait - URI attachUri = getForumUriBuilder().path("posts").path(m1.getKey().toString()).path("attachments").build(); + URI attachUri = getForumUriBuilder().path("posts").path(message.getKey().toString()).path("attachments").build(); PostMethod attachMethod = createPost(attachUri, MediaType.APPLICATION_JSON, true); attachMethod.addRequestHeader("Content-Type", MediaType.MULTIPART_FORM_DATA); Part[] parts = { @@ -274,6 +282,67 @@ public class ForumTest extends OlatJerseyTestCase { int attachCode = c.executeMethod(attachMethod); assertEquals(200, attachCode); attachMethod.releaseConnection(); + + + //check if the file exists + ForumManager fm = ForumManager.getInstance(); + VFSContainer container = fm.getMessageContainer(message.getForumKey(), message.getKey()); + VFSItem uploadedFile = container.resolve("portrait.jpg"); + assertNotNull(uploadedFile); + assertTrue(uploadedFile instanceof VFSLeaf); + + //check if the image is still an image + VFSLeaf uploadedImage = (VFSLeaf)uploadedFile; + InputStream uploadedStream = uploadedImage.getInputStream(); + BufferedImage image = ImageIO.read(uploadedStream); + FileUtils.closeSafely(uploadedStream); + assertNotNull(image); + } + + @Test + public void testUpload64Attachment() throws IOException, URISyntaxException { + HttpClient c = loginWithCookie(id1.getName(), "A6B7C8"); + + URI uri = getForumUriBuilder().path("posts").path(m1.getKey().toString()) + .queryParam("authorKey", id1.getKey()) + .queryParam("title", "New message with attachment ") + .queryParam("body", "A very interesting response in Thread-1 with an attachment").build(); + PutMethod method = createPut(uri, MediaType.APPLICATION_JSON, true); + int code = c.executeMethod(method); + assertEquals(200, code); + InputStream body = method.getResponseBodyAsStream(); + MessageVO message = parse(body, MessageVO.class); + assertNotNull(message); + + //attachment + InputStream portraitStream = RepositoryEntriesTest.class.getResourceAsStream("portrait.jpg"); + assertNotNull(portraitStream); + //upload portrait + URI attachUri = getForumUriBuilder().path("posts").path(message.getKey().toString()).path("attachments").build(); + byte[] portraitBytes = IOUtils.toByteArray(portraitStream); + byte[] portrait64 = Base64.encodeBase64(portraitBytes, true); + PostMethod attachMethod = createPost(attachUri, MediaType.APPLICATION_JSON, true); + attachMethod.addRequestHeader("Content-Type", MediaType.APPLICATION_FORM_URLENCODED); + attachMethod.addParameter("file", new String(portrait64)); + attachMethod.addParameter("filename", "portrait64.jpg"); + + int attachCode = c.executeMethod(attachMethod); + assertEquals(200, attachCode); + attachMethod.releaseConnection(); + + //check if the file exists + ForumManager fm = ForumManager.getInstance(); + VFSContainer container = fm.getMessageContainer(message.getForumKey(), message.getKey()); + VFSItem uploadedFile = container.resolve("portrait64.jpg"); + assertNotNull(uploadedFile); + assertTrue(uploadedFile instanceof VFSLeaf); + + //check if the image is still an image + VFSLeaf uploadedImage = (VFSLeaf)uploadedFile; + InputStream uploadedStream = uploadedImage.getInputStream(); + BufferedImage image = ImageIO.read(uploadedStream); + FileUtils.closeSafely(uploadedStream); + assertNotNull(image); } @Test