diff --git a/src/main/java/org/olat/core/util/vfs/VFSManager.java b/src/main/java/org/olat/core/util/vfs/VFSManager.java
index 41133ae9454baffabfdc2682ce506e5f4e673a27..cb646c4ad7e682fb3be49dc7643487b4520afe93 100644
--- a/src/main/java/org/olat/core/util/vfs/VFSManager.java
+++ b/src/main/java/org/olat/core/util/vfs/VFSManager.java
@@ -533,6 +533,26 @@ public class VFSManager extends BasicManager {
 		return successful;
 	}
 	
+	/**
+	 * 
+	 * @param container
+	 * @param filename
+	 * @return
+	 */
+	public static String rename(VFSContainer container, String filename) {
+		String newName = filename;
+		VFSItem newFile = container.resolve(newName);
+		for(int count=0; newFile != null && count < 999 ; ) {
+			count++;
+			newName = appendNumberAtTheEndOfFilename(filename, count);
+		    newFile = container.resolve(newName);
+		}
+		if(newFile == null) {
+			return newName;
+		}
+		return null;
+	}
+	
 	/**
 	 * Check if the file exist or not
 	 * @param item
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 067ffcf4463bbb67691fcb7177ba98ec312d3d42..e535ce5b4e9eb81e8be1f28a6a3d58df546ddf12 100644
--- a/src/main/java/org/olat/modules/fo/restapi/ForumWebService.java
+++ b/src/main/java/org/olat/modules/fo/restapi/ForumWebService.java
@@ -25,6 +25,7 @@ import static org.olat.restapi.security.RestSecurityHelper.getIdentity;
 import static org.olat.restapi.security.RestSecurityHelper.isAdmin;
 
 import java.io.File;
+import java.io.IOException;
 import java.io.InputStream;
 import java.io.OutputStream;
 import java.util.ArrayList;
@@ -52,6 +53,7 @@ import javax.ws.rs.core.Response.Status;
 import javax.ws.rs.core.StreamingOutput;
 import javax.ws.rs.core.UriInfo;
 
+import org.apache.commons.io.IOUtils;
 import org.olat.basesecurity.BaseSecurity;
 import org.olat.basesecurity.BaseSecurityManager;
 import org.olat.core.id.Identity;
@@ -63,6 +65,7 @@ import org.olat.core.util.vfs.LocalFileImpl;
 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.VFSManager;
 import org.olat.core.util.vfs.restapi.SystemItemFilter;
 import org.olat.core.util.vfs.restapi.VFSStreamingOutput;
 import org.olat.modules.fo.Forum;
@@ -464,16 +467,23 @@ public class ForumWebService {
 		VFSLeaf attachment = null;
 		if(item == null) {
 			attachment = container.createChildLeaf(filename);
-		} else if (item instanceof VFSLeaf) {
-			attachment = (VFSLeaf)item;
 		} else {
-			return Response.serverError().status(Status.CONFLICT).build();
+			filename = VFSManager.rename(container, filename);
+			if(filename == null) {
+				return Response.serverError().status(Status.NOT_ACCEPTABLE).build();
+			}
+			attachment = container.createChildLeaf(filename);
 		}
 		
 		OutputStream out = attachment.getOutputStream(false);
-		FileUtils.copy(file, out);
-		FileUtils.closeSafely(out);
-		FileUtils.closeSafely(file);
+		try {
+			IOUtils.copy(file, out);
+		} catch (IOException e) {
+			return Response.serverError().status(Status.INTERNAL_SERVER_ERROR).build();
+		} finally {
+			FileUtils.closeSafely(out);
+			FileUtils.closeSafely(file);
+		}
 		return Response.ok().build();
 	}
 	
diff --git a/src/test/java/org/olat/restapi/ForumTest.java b/src/test/java/org/olat/restapi/ForumTest.java
index d7c9d46a532742f16bfc68eac662b0c10ca6fa51..041e5ecc45e2fc9c83c0818c4c0ac3fe061e17ca 100644
--- a/src/test/java/org/olat/restapi/ForumTest.java
+++ b/src/test/java/org/olat/restapi/ForumTest.java
@@ -26,9 +26,12 @@ import static org.junit.Assert.assertFalse;
 import static org.junit.Assert.assertNotNull;
 import static org.junit.Assert.assertTrue;
 
+import java.io.File;
 import java.io.IOException;
 import java.io.InputStream;
 import java.net.URI;
+import java.net.URISyntaxException;
+import java.net.URL;
 import java.util.List;
 
 import javax.ws.rs.core.MediaType;
@@ -36,7 +39,12 @@ import javax.ws.rs.core.UriBuilder;
 
 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.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.codehaus.jackson.map.ObjectMapper;
 import org.codehaus.jackson.type.TypeReference;
 import org.junit.Before;
@@ -48,6 +56,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.FileVO;
 import org.olat.test.JunitTestHelper;
 import org.olat.test.OlatJerseyTestCase;
 
@@ -220,6 +229,113 @@ public class ForumTest extends OlatJerseyTestCase {
 		assertTrue(saved);
 	}
 	
+	@Test
+	public void testGetAttachment() throws IOException, URISyntaxException {
+		HttpClient c = loginWithCookie("administrator", "olat");
+		
+		URI uri = getForumUriBuilder().path("posts").path(m1.getKey().toString()).path("attachments").build();
+		GetMethod method = createGet(uri, MediaType.APPLICATION_JSON, true);
+		int code = c.executeMethod(method);
+		assertEquals(200, code);
+		InputStream body = method.getResponseBodyAsStream();
+		List<FileVO> files = parseFileArray(body);
+		assertNotNull(files);
+	}
+	
+	@Test
+	public void testUploadAttachment() 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
+		URL portraitUrl = RepositoryEntriesTest.class.getResource("portrait.jpg");
+		assertNotNull(portraitUrl);
+		File portrait = new File(portraitUrl.toURI());
+		
+		//upload portrait
+		URI attachUri = getForumUriBuilder().path("posts").path(m1.getKey().toString()).path("attachments").build();
+		PostMethod attachMethod = createPost(attachUri, MediaType.APPLICATION_JSON, true);
+		attachMethod.addRequestHeader("Content-Type", MediaType.MULTIPART_FORM_DATA);
+		Part[] parts = { 
+			new FilePart("file", portrait),
+			new StringPart("filename","portrait.jpg")
+		};
+		attachMethod.setRequestEntity(new MultipartRequestEntity(parts, attachMethod.getParams()));
+		int attachCode = c.executeMethod(attachMethod);
+		assertEquals(200, attachCode);
+		attachMethod.releaseConnection();
+	}
+	
+	@Test
+	public void testUploadAttachmentAndRename() 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
+		URL portraitUrl = RepositoryEntriesTest.class.getResource("portrait.jpg");
+		assertNotNull(portraitUrl);
+		File portrait = new File(portraitUrl.toURI());
+		
+		//upload portrait
+		URI attachUri = getForumUriBuilder().path("posts").path(m1.getKey().toString()).path("attachments").build();
+		PostMethod attachMethod = createPost(attachUri, MediaType.APPLICATION_JSON, true);
+		attachMethod.addRequestHeader("Content-Type", MediaType.MULTIPART_FORM_DATA);
+		Part[] parts = { 
+			new FilePart("file", portrait),
+			new StringPart("filename","portrait.jpg")
+		};
+		attachMethod.setRequestEntity(new MultipartRequestEntity(parts, attachMethod.getParams()));
+		int attachCode = c.executeMethod(attachMethod);
+		assertEquals(200, attachCode);
+		attachMethod.releaseConnection();
+
+		//upload portrait a second time
+		URI attach2Uri = getForumUriBuilder().path("posts").path(m1.getKey().toString()).path("attachments").build();
+		PostMethod attach2Method = createPost(attach2Uri, MediaType.APPLICATION_JSON, true);
+		attach2Method.addRequestHeader("Content-Type", MediaType.MULTIPART_FORM_DATA);
+		Part[] parts2 = { 
+			new FilePart("file", portrait),
+			new StringPart("filename","portrait.jpg")
+		};
+		attach2Method.setRequestEntity(new MultipartRequestEntity(parts2, attach2Method.getParams()));
+		int attach2Code = c.executeMethod(attach2Method);
+		assertEquals(200, attach2Code);
+		attach2Method.releaseConnection();
+		
+		// load the attachments
+		
+		URI loadUri = getForumUriBuilder().path("posts").path(m1.getKey().toString()).path("attachments").build();
+		GetMethod loadMethod = createGet(loadUri, MediaType.APPLICATION_JSON, true);
+		int loadCode = c.executeMethod(loadMethod);
+		assertEquals(200, loadCode);
+		InputStream loadBody = loadMethod.getResponseBodyAsStream();
+		List<FileVO> files = parseFileArray(loadBody);
+		assertNotNull(files);
+		assertEquals(2, files.size());
+		loadMethod.releaseConnection();
+		
+	}
+	
 	private UriBuilder getForumUriBuilder() {
 		return UriBuilder.fromUri(getContextURI()).path("repo").path("forums").path(forum.getKey().toString());
 	}
diff --git a/src/test/java/org/olat/test/OlatJerseyTestCase.java b/src/test/java/org/olat/test/OlatJerseyTestCase.java
index f6054775ab52a3661c40e8f458e45ff3f0185593..95a4c6f148373e1a149db6c5ee67b4bc77b45808 100644
--- a/src/test/java/org/olat/test/OlatJerseyTestCase.java
+++ b/src/test/java/org/olat/test/OlatJerseyTestCase.java
@@ -55,6 +55,7 @@ import org.olat.restapi.security.RestApiLoginFilter;
 import org.olat.restapi.security.RestSecurityHelper;
 import org.olat.restapi.support.OlatRestApplication;
 import org.olat.restapi.support.vo.ErrorVO;
+import org.olat.restapi.support.vo.FileVO;
 import org.olat.restapi.support.vo.LinkVO;
 import org.springframework.beans.factory.annotation.Autowired;
 
@@ -381,4 +382,14 @@ public abstract class OlatJerseyTestCase extends OlatTestCase {
 			return null;
 		}
 	}
+	
+	protected List<FileVO> parseFileArray(InputStream body) {
+		try {
+			ObjectMapper mapper = new ObjectMapper(jsonFactory); 
+			return mapper.readValue(body, new TypeReference<List<FileVO>>(){/* */});
+		} catch (Exception e) {
+			e.printStackTrace();
+			return null;
+		}
+	}
 }
\ No newline at end of file