Skip to content
Snippets Groups Projects
Commit ce46834f authored by srosse's avatar srosse
Browse files

FXOLAT-296: add upload with file encoded as Base64 and add unit tests

parent d113fae1
No related branches found
No related tags found
No related merge requests found
...@@ -20,6 +20,7 @@ ...@@ -20,6 +20,7 @@
*/ */
package org.olat.core.util.vfs.restapi; package org.olat.core.util.vfs.restapi;
import java.io.ByteArrayInputStream;
import java.io.InputStream; import java.io.InputStream;
import java.io.OutputStream; import java.io.OutputStream;
import java.text.Normalizer; import java.text.Normalizer;
...@@ -46,6 +47,7 @@ import javax.ws.rs.core.Response.Status; ...@@ -46,6 +47,7 @@ import javax.ws.rs.core.Response.Status;
import javax.ws.rs.core.UriBuilder; import javax.ws.rs.core.UriBuilder;
import javax.ws.rs.core.UriInfo; import javax.ws.rs.core.UriInfo;
import org.apache.commons.codec.binary.Base64;
import org.olat.core.util.FileUtils; import org.olat.core.util.FileUtils;
import org.olat.core.util.StringHelper; import org.olat.core.util.StringHelper;
import org.olat.core.util.WebappHelper; import org.olat.core.util.WebappHelper;
...@@ -134,6 +136,27 @@ public class VFSWebservice { ...@@ -134,6 +136,27 @@ public class VFSWebservice {
return putFile(foldername, filename, file, uriInfo, Collections.<PathSegment>emptyList()); 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 * 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.doc The link to the created file
...@@ -154,6 +177,28 @@ public class VFSWebservice { ...@@ -154,6 +177,28 @@ public class VFSWebservice {
return putFile(foldername, filename, file, uriInfo, path); 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 * 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.doc The link to the created file
......
...@@ -24,6 +24,7 @@ package org.olat.modules.fo.restapi; ...@@ -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.getIdentity;
import static org.olat.restapi.security.RestSecurityHelper.isAdmin; import static org.olat.restapi.security.RestSecurityHelper.isAdmin;
import java.io.ByteArrayInputStream;
import java.io.File; import java.io.File;
import java.io.IOException; import java.io.IOException;
import java.io.InputStream; import java.io.InputStream;
...@@ -53,6 +54,7 @@ import javax.ws.rs.core.Response.Status; ...@@ -53,6 +54,7 @@ import javax.ws.rs.core.Response.Status;
import javax.ws.rs.core.StreamingOutput; import javax.ws.rs.core.StreamingOutput;
import javax.ws.rs.core.UriInfo; import javax.ws.rs.core.UriInfo;
import org.apache.commons.codec.binary.Base64;
import org.apache.commons.io.IOUtils; import org.apache.commons.io.IOUtils;
import org.olat.basesecurity.BaseSecurity; import org.olat.basesecurity.BaseSecurity;
import org.olat.basesecurity.BaseSecurityManager; import org.olat.basesecurity.BaseSecurityManager;
...@@ -440,6 +442,28 @@ public class ForumWebService { ...@@ -440,6 +442,28 @@ public class ForumWebService {
return attachToPost(messageKey, filename, file, request); 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) { protected Response attachToPost(Long messageKey, String filename, InputStream file, HttpServletRequest request) {
//load message //load message
Message mess = fom.loadMessage(messageKey); Message mess = fom.loadMessage(messageKey);
......
...@@ -26,6 +26,7 @@ import static org.junit.Assert.assertFalse; ...@@ -26,6 +26,7 @@ import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertNotNull; import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertTrue; import static org.junit.Assert.assertTrue;
import java.awt.image.BufferedImage;
import java.io.File; import java.io.File;
import java.io.IOException; import java.io.IOException;
import java.io.InputStream; import java.io.InputStream;
...@@ -34,9 +35,11 @@ import java.net.URISyntaxException; ...@@ -34,9 +35,11 @@ import java.net.URISyntaxException;
import java.net.URL; import java.net.URL;
import java.util.List; import java.util.List;
import javax.imageio.ImageIO;
import javax.ws.rs.core.MediaType; import javax.ws.rs.core.MediaType;
import javax.ws.rs.core.UriBuilder; import javax.ws.rs.core.UriBuilder;
import org.apache.commons.codec.binary.Base64;
import org.apache.commons.httpclient.HttpClient; import org.apache.commons.httpclient.HttpClient;
import org.apache.commons.httpclient.methods.GetMethod; import org.apache.commons.httpclient.methods.GetMethod;
import org.apache.commons.httpclient.methods.PostMethod; import org.apache.commons.httpclient.methods.PostMethod;
...@@ -45,12 +48,17 @@ import org.apache.commons.httpclient.methods.multipart.FilePart; ...@@ -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.MultipartRequestEntity;
import org.apache.commons.httpclient.methods.multipart.Part; import org.apache.commons.httpclient.methods.multipart.Part;
import org.apache.commons.httpclient.methods.multipart.StringPart; import org.apache.commons.httpclient.methods.multipart.StringPart;
import org.apache.commons.io.IOUtils;
import org.codehaus.jackson.map.ObjectMapper; import org.codehaus.jackson.map.ObjectMapper;
import org.codehaus.jackson.type.TypeReference; import org.codehaus.jackson.type.TypeReference;
import org.junit.Before; import org.junit.Before;
import org.junit.Test; import org.junit.Test;
import org.olat.core.commons.persistence.DBFactory; import org.olat.core.commons.persistence.DBFactory;
import org.olat.core.id.Identity; 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.Forum;
import org.olat.modules.fo.ForumManager; import org.olat.modules.fo.ForumManager;
import org.olat.modules.fo.Message; import org.olat.modules.fo.Message;
...@@ -263,7 +271,7 @@ public class ForumTest extends OlatJerseyTestCase { ...@@ -263,7 +271,7 @@ public class ForumTest extends OlatJerseyTestCase {
File portrait = new File(portraitUrl.toURI()); File portrait = new File(portraitUrl.toURI());
//upload portrait //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); PostMethod attachMethod = createPost(attachUri, MediaType.APPLICATION_JSON, true);
attachMethod.addRequestHeader("Content-Type", MediaType.MULTIPART_FORM_DATA); attachMethod.addRequestHeader("Content-Type", MediaType.MULTIPART_FORM_DATA);
Part[] parts = { Part[] parts = {
...@@ -274,6 +282,67 @@ public class ForumTest extends OlatJerseyTestCase { ...@@ -274,6 +282,67 @@ public class ForumTest extends OlatJerseyTestCase {
int attachCode = c.executeMethod(attachMethod); int attachCode = c.executeMethod(attachMethod);
assertEquals(200, attachCode); assertEquals(200, attachCode);
attachMethod.releaseConnection(); 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 @Test
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment