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 f40fd510c6b62812cdd03fa8764f0c99e26a9037..4bf224f624594b47d704ba4952cf69204adb2271 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 @@ -56,6 +56,7 @@ import org.olat.core.util.vfs.VFSContainer; import org.olat.core.util.vfs.VFSItem; import org.olat.core.util.vfs.VFSLeaf; import org.olat.core.util.vfs.VFSStatus; +import org.olat.restapi.support.vo.File64VO; import org.olat.restapi.support.vo.FileVO; public class VFSWebservice { @@ -217,6 +218,25 @@ public class VFSWebservice { return putFile(foldername, filename, file, uriInfo, Collections.<PathSegment>emptyList()); } + /** + * Upload a file to the root 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 (optional) + * @param uriInfo The uri infos + * @return The link to the created file + */ + @PUT + @Consumes({MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML}) + @Produces({MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML}) + public Response putFile64VOToRoot(File64VO file, @Context UriInfo uriInfo) { + byte[] fileAsBytes = Base64.decodeBase64(file.getFile()); + InputStream in = new ByteArrayInputStream(fileAsBytes); + return putFile(null, file.getFilename(), 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 @@ -237,6 +257,27 @@ 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 (optional) + * @param uriInfo The uri infos + * @param path The path to the folder + * @return The link to the created file + */ + @PUT + @Path("{path:.*}") + @Consumes({MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML}) + @Produces({MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML}) + public Response putFile64ToFolder(File64VO file, @Context UriInfo uriInfo, @PathParam("path") List<PathSegment> path) { + byte[] fileAsBytes = Base64.decodeBase64(file.getFile()); + InputStream in = new ByteArrayInputStream(fileAsBytes); + return putFile(null, file.getFilename(), in, uriInfo, path); + } + /** * Create folders * @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 97e4710c44b4a69507ec107b90b3c3ac3f2dbf3b..86f2ca05d082e3b478f4ceb2e16deeca5ec9b1c1 100644 --- a/src/main/java/org/olat/modules/fo/restapi/ForumWebService.java +++ b/src/main/java/org/olat/modules/fo/restapi/ForumWebService.java @@ -74,6 +74,7 @@ import org.olat.modules.fo.Forum; import org.olat.modules.fo.ForumManager; import org.olat.modules.fo.Message; import org.olat.restapi.support.MediaTypeVariants; +import org.olat.restapi.support.vo.File64VO; import org.olat.restapi.support.vo.FileVO; /** @@ -464,6 +465,18 @@ public class ForumWebService { return attachToPost(messageKey, filename, in, request); } + @PUT + @Path("posts/{messageKey}/attachments") + @Consumes({MediaType.APPLICATION_XML, MediaType.APPLICATION_JSON}) + @Produces({MediaType.APPLICATION_XML, MediaType.APPLICATION_JSON}) + public Response replyToPostAttachment(@PathParam("messageKey") Long messageKey, File64VO file64, @Context HttpServletRequest request) { + String file = file64.getFile(); + String filename = file64.getFilename(); + 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/main/java/org/olat/restapi/support/vo/File64VO.java b/src/main/java/org/olat/restapi/support/vo/File64VO.java new file mode 100644 index 0000000000000000000000000000000000000000..ec8362e3d3db8596119d5b0ea7daa9933c337f39 --- /dev/null +++ b/src/main/java/org/olat/restapi/support/vo/File64VO.java @@ -0,0 +1,65 @@ +/** + * OLAT - Online Learning and Training<br> + * http://www.olat.org + * <p> + * Licensed under the Apache License, Version 2.0 (the "License"); <br> + * you may not use this file except in compliance with the License.<br> + * You may obtain a copy of the License at + * <p> + * http://www.apache.org/licenses/LICENSE-2.0 + * <p> + * Unless required by applicable law or agreed to in writing,<br> + * software distributed under the License is distributed on an "AS IS" BASIS, <br> + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. <br> + * See the License for the specific language governing permissions and <br> + * limitations under the License. + * <p> + * Copyright (c) frentix GmbH<br> + * http://www.frentix.com<br> + * <p> + */ + +package org.olat.restapi.support.vo; + +import javax.xml.bind.annotation.XmlAccessType; +import javax.xml.bind.annotation.XmlAccessorType; +import javax.xml.bind.annotation.XmlRootElement; + + +/** + * + * Description:<br> + * Use the upload or download files encoded with Base64 + * + * <P> + * Initial Date: 6 déc. 2011 <br> + * + * @author srosse, stephane.rosse@frentix.com, http://www.frentix.com + */ +@XmlAccessorType(XmlAccessType.FIELD) +@XmlRootElement(name = "fileUpload") +public class File64VO { + + private String file; + private String filename; + + public File64VO() { + //make JAXB happy + } + + public String getFile() { + return file; + } + + public void setFile(String file) { + this.file = file; + } + + public String getFilename() { + return filename; + } + + public void setFilename(String filename) { + this.filename = filename; + } +} diff --git a/src/test/java/org/olat/restapi/ForumTest.java b/src/test/java/org/olat/restapi/ForumTest.java index c85c7a141911ab646ad0945aabbfa11a4fb79b46..64d96b0299eca1d06b51031570fb9166f44786f5 100644 --- a/src/test/java/org/olat/restapi/ForumTest.java +++ b/src/test/java/org/olat/restapi/ForumTest.java @@ -44,6 +44,8 @@ import org.apache.commons.httpclient.HttpClient; import org.apache.commons.httpclient.methods.GetMethod; import org.apache.commons.httpclient.methods.PostMethod; import org.apache.commons.httpclient.methods.PutMethod; +import org.apache.commons.httpclient.methods.RequestEntity; +import org.apache.commons.httpclient.methods.StringRequestEntity; import org.apache.commons.httpclient.methods.multipart.FilePart; import org.apache.commons.httpclient.methods.multipart.MultipartRequestEntity; import org.apache.commons.httpclient.methods.multipart.Part; @@ -64,6 +66,7 @@ import org.olat.modules.fo.ForumManager; import org.olat.modules.fo.Message; import org.olat.modules.fo.restapi.MessageVO; import org.olat.modules.fo.restapi.MessageVOes; +import org.olat.restapi.support.vo.File64VO; import org.olat.restapi.support.vo.FileVO; import org.olat.test.JunitTestHelper; import org.olat.test.OlatJerseyTestCase; @@ -345,6 +348,61 @@ public class ForumTest extends OlatJerseyTestCase { assertNotNull(image); } + + @Test + public void testUploadAttachmentWithFile64VO() 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(); + PutMethod attachMethod = createPut(attachUri, MediaType.APPLICATION_JSON, true); + attachMethod.addRequestHeader("Content-Type", MediaType.APPLICATION_JSON); + + byte[] portraitBytes = IOUtils.toByteArray(portraitStream); + byte[] portrait64 = Base64.encodeBase64(portraitBytes, true); + File64VO fileVo = new File64VO(); + fileVo.setFile(new String(portrait64)); + fileVo.setFilename("portrait64vo.jpg"); + String stringuifiedFileVo = stringuified(fileVo); + RequestEntity entity = new StringRequestEntity(stringuifiedFileVo, MediaType.APPLICATION_JSON, "UTF-8"); + attachMethod.setRequestEntity(entity); + 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("portrait64vo.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 testUploadAttachmentAndRename() throws IOException, URISyntaxException { HttpClient c = loginWithCookie(id1.getName(), "A6B7C8");