diff --git a/src/main/java/org/olat/core/gui/components/form/flexible/impl/elements/FileElementImpl.java b/src/main/java/org/olat/core/gui/components/form/flexible/impl/elements/FileElementImpl.java
index 5ffe5ec91015936a5ead6de4b96929aa921beece..440333c442a63eb4c1c2338532a4a9233ac1ed2f 100644
--- a/src/main/java/org/olat/core/gui/components/form/flexible/impl/elements/FileElementImpl.java
+++ b/src/main/java/org/olat/core/gui/components/form/flexible/impl/elements/FileElementImpl.java
@@ -182,6 +182,8 @@ public class FileElementImpl extends FormItemImpl
 				previewEl.setCropSelectionEnabled(cropSelectionEnabled);
 				previewEl.setMaxWithAndHeightToFitWithin(300, 200);
 				previewEl.setVisible(true);
+			} else {
+				previewEl.setVisible(false);
 			}
 			// Mark associated component dirty, that it gets rerendered
 			component.setDirty(true);
diff --git a/src/main/java/org/olat/core/gui/components/image/ImageComponent.java b/src/main/java/org/olat/core/gui/components/image/ImageComponent.java
index 970735bfde1b16c951591430081e02e97eb8f0b5..e3bcaa75e9b10dcf2e5681e05d87207a81f8b11f 100644
--- a/src/main/java/org/olat/core/gui/components/image/ImageComponent.java
+++ b/src/main/java/org/olat/core/gui/components/image/ImageComponent.java
@@ -30,20 +30,16 @@ import java.io.File;
 import java.util.Collections;
 import java.util.UUID;
 
-import javax.servlet.http.HttpServletRequest;
-
 import org.olat.core.CoreSpringFactory;
 import org.olat.core.commons.services.image.ImageService;
 import org.olat.core.commons.services.image.Size;
 import org.olat.core.commons.services.video.MovieService;
-import org.olat.core.dispatcher.mapper.Mapper;
 import org.olat.core.dispatcher.mapper.MapperService;
 import org.olat.core.dispatcher.mapper.manager.MapperKey;
 import org.olat.core.gui.UserRequest;
 import org.olat.core.gui.components.AbstractComponent;
 import org.olat.core.gui.components.ComponentRenderer;
 import org.olat.core.gui.control.Disposable;
-import org.olat.core.gui.media.MediaResource;
 import org.olat.core.gui.render.ValidationResult;
 import org.olat.core.logging.OLog;
 import org.olat.core.logging.Tracing;
@@ -52,7 +48,7 @@ import org.olat.core.util.UserSession;
 import org.olat.core.util.WebappHelper;
 import org.olat.core.util.vfs.LocalFileImpl;
 import org.olat.core.util.vfs.VFSLeaf;
-import org.olat.core.util.vfs.VFSMediaResource;
+import org.olat.core.util.vfs.VFSMediaMapper;
 
 /**
  * Description: <br>
@@ -68,12 +64,12 @@ public class ImageComponent extends AbstractComponent implements Disposable {
 
 	private String alt;
 	private final MapperKey mapperUrl;
-	private final MediaMapper mapper;
+	private final VFSMediaMapper mapper;
 
 	// optional in case of video: poster image
 	private VFSLeaf poster;
 	private MapperKey posterMapperUrl;
-	private MediaMapper posterMapper;
+	private VFSMediaMapper posterMapper;
 
 	private Size realSize;
 	private Size scaledSize;
@@ -86,11 +82,11 @@ public class ImageComponent extends AbstractComponent implements Disposable {
 	 */
 	public ImageComponent(UserSession usess, String name) {
 		super(name);
-		mapper = new MediaMapper();
+		mapper = new VFSMediaMapper();
 		String mapperId = UUID.randomUUID().toString();
 		mapperUrl = CoreSpringFactory.getImpl(MapperService.class).register(usess, mapperId, mapper);
 		// optional poster frame for videos
-		posterMapper = new MediaMapper();
+		posterMapper = new VFSMediaMapper();
 		mapperId = UUID.randomUUID().toString();
 		posterMapperUrl = CoreSpringFactory.getImpl(MapperService.class).register(usess, mapperId, posterMapper);		
 		// renderer provides own DOM ID
@@ -313,16 +309,4 @@ public class ImageComponent extends AbstractComponent implements Disposable {
 		return null;
 	}
 	
-	private static class MediaMapper implements Mapper {
-		private VFSLeaf mediaFile;
-
-		public void setMediaFile(VFSLeaf mediaFile) {
-			this.mediaFile = mediaFile;
-		}
-
-		@Override
-		public MediaResource handle(String relPath, HttpServletRequest request) {
-			return new VFSMediaResource(mediaFile);
-		}
-	}
 }
\ No newline at end of file
diff --git a/src/main/java/org/olat/core/util/vfs/VFSLeafMapper.java b/src/main/java/org/olat/core/util/vfs/VFSMediaMapper.java
similarity index 85%
rename from src/main/java/org/olat/core/util/vfs/VFSLeafMapper.java
rename to src/main/java/org/olat/core/util/vfs/VFSMediaMapper.java
index 888c8d3efe790cef2e995dee28bc94506647edc7..ef0af8f2a6b17f7762d766182ba3c74c5c4d817d 100644
--- a/src/main/java/org/olat/core/util/vfs/VFSLeafMapper.java
+++ b/src/main/java/org/olat/core/util/vfs/VFSMediaMapper.java
@@ -30,11 +30,18 @@ import org.olat.core.gui.media.MediaResource;
  * @author uhensler, urs.hensler@frentix.com, http://www.frentix.com
  *
  */
-public class VFSLeafMapper implements Mapper {
+public class VFSMediaMapper implements Mapper {
 	
-	private final VFSLeaf file;
+	private VFSLeaf file;
 	
-	public VFSLeafMapper(VFSLeaf file) {
+	public VFSMediaMapper() {
+	}
+
+	public VFSMediaMapper(VFSLeaf file) {
+		this.file = file;
+	}
+
+	public void setMediaFile(VFSLeaf file) {
 		this.file = file;
 	}
 
diff --git a/src/main/java/org/olat/modules/forms/EvaluationFormResponse.java b/src/main/java/org/olat/modules/forms/EvaluationFormResponse.java
index da23d5d3817e182e8cbd7a02db9c6be65b118edd..5b3cae360b6f06c1862eacf58bf1593ada0ef385 100644
--- a/src/main/java/org/olat/modules/forms/EvaluationFormResponse.java
+++ b/src/main/java/org/olat/modules/forms/EvaluationFormResponse.java
@@ -35,6 +35,12 @@ public interface EvaluationFormResponse extends CreateInfo, ModifiedInfo {
 	
 	public Long getKey();
 	
+	/**
+	 * The identifier of the evaluation form part / element. Several responses may
+	 * have the same identifier.
+	 * 
+	 * @return
+	 */
 	public String getResponseIdentifier();
 	
 	public BigDecimal getNumericalResponse();
diff --git a/src/main/java/org/olat/modules/forms/manager/EvaluationFormManagerImpl.java b/src/main/java/org/olat/modules/forms/manager/EvaluationFormManagerImpl.java
index 78a7f6f212426ddc4a1ac6a4727a4215b1a12bca..b7a10357c7088d439db464e73553ed857332519f 100644
--- a/src/main/java/org/olat/modules/forms/manager/EvaluationFormManagerImpl.java
+++ b/src/main/java/org/olat/modules/forms/manager/EvaluationFormManagerImpl.java
@@ -88,7 +88,7 @@ public class EvaluationFormManagerImpl implements EvaluationFormManager {
 	@Override
 	public EvaluationFormResponse createResponseForPortfolioEvaluation(String responseIdentifier, File file,
 			String filename, EvaluationFormSession session) throws IOException {
-		Path relativePath = evaluationFormStorage.save(file, filename, responseIdentifier);
+		Path relativePath = evaluationFormStorage.save(file, filename);
 		return evaluationFormResponseDao.createResponse(responseIdentifier, null, filename, relativePath,
 				session);
 	}
@@ -107,7 +107,7 @@ public class EvaluationFormManagerImpl implements EvaluationFormManager {
 		Path relativePath = null;
 		String filenameToSave = null;
 		if (file != null) {
-			relativePath = evaluationFormStorage.save(file, filename, response.getResponseIdentifier());
+			relativePath = evaluationFormStorage.save(file, filename);
 			filenameToSave = filename;
 		}
 		return evaluationFormResponseDao.updateResponse(null, filenameToSave, relativePath, response);
diff --git a/src/main/java/org/olat/modules/forms/manager/EvaluationFormStorage.java b/src/main/java/org/olat/modules/forms/manager/EvaluationFormStorage.java
index 0c007e091e11b2c8dfbbc75d33b38f8f1a5118b7..3670329a824ba34c0d0218ff023eedef0821e49f 100644
--- a/src/main/java/org/olat/modules/forms/manager/EvaluationFormStorage.java
+++ b/src/main/java/org/olat/modules/forms/manager/EvaluationFormStorage.java
@@ -25,6 +25,8 @@ import java.nio.file.Files;
 import java.nio.file.Path;
 import java.nio.file.Paths;
 import java.nio.file.StandardCopyOption;
+import java.util.Comparator;
+import java.util.UUID;
 
 import javax.annotation.PostConstruct;
 
@@ -42,7 +44,7 @@ import org.springframework.stereotype.Service;
  *
  */
 @Service
-public class EvaluationFormStorage {
+class EvaluationFormStorage {
 	
 	private static final OLog log = Tracing.createLoggerFor(EvaluationFormStorage.class);
 	
@@ -74,44 +76,48 @@ public class EvaluationFormStorage {
 	 * 
 	 * @param file the file to save
 	 * @param filename the filename of the new file
-	 * @param responseIdentifier the identifier of the evaluation form response
 	 * @return the relative path of the saved file
 	 */
-	public Path save(File file, String filename, String responseIdentifier) throws IOException {
-		Path responsePath = getResponsePath(responseIdentifier, filename);
+	Path save(File file, String filename) throws IOException {
+		Path responsePath = getResponsePath(filename);
 		Path sourcePath = file.toPath();
 		Files.createDirectories(responsePath.getParent());
 		Files.copy(sourcePath, responsePath, StandardCopyOption.REPLACE_EXISTING);
 		return getRelativePath(responsePath);
 	}
 
-	public File load(Path relativePath) {
+	File load(Path relativePath) {
 		return getAbsolutePath(relativePath).toFile();
 	}
 	
-	public VFSLeaf resolve(Path relativePath) {
+	VFSLeaf resolve(Path relativePath) {
 		return new OlatRootFileImpl("/" + relativePath.toString(), null);
 	}
 
-	public void delete(Path relativePath) {
-		Path absolutePath = getAbsolutePath(relativePath);
+	void delete(Path relativePath) {
+		Path parentDir = relativePath.getParent();
+		Path absolutePath = getAbsolutePath(parentDir);
 		try {
-			Files.deleteIfExists(absolutePath);
+		    Files.walk(absolutePath)
+		      .sorted(Comparator.reverseOrder())
+		      .map(Path::toFile)
+		      .forEach(File::delete);
 		} catch (IOException e) {
 			log.warn("Cannot properly delete evaluation form response file. Path: " + absolutePath, e);
 		}
 	}
 	
-	private Path getResponsePath(String responseIdentifier, String filename) {
+	private Path getResponsePath(String filename) {
+		String responseDirectory = UUID.randomUUID().toString().replace("-", "").toLowerCase();
 		return Paths.get(
 				responsesDirectory.toString(),
-				getIndexTooken(responseIdentifier),
-				responseIdentifier,
+				getIndexTooken(responseDirectory),
+				responseDirectory,
 				filename);
 	}
 	
-	private String getIndexTooken(String responseIdentifier) {
-		return responseIdentifier.replace("-", "").substring(0, 2).toLowerCase();
+	private String getIndexTooken(String responseDirectory) {
+		return responseDirectory.substring(0, 3);
 	}
 	
 	private Path getRelativePath(Path path) {
diff --git a/src/main/java/org/olat/modules/forms/ui/CompareEvaluationsFormController.java b/src/main/java/org/olat/modules/forms/ui/CompareEvaluationsFormController.java
index 34ee49689bed34cae22efc3cd7f434b9c33df90f..f78d1880c4f5497aa772d8fde814fb75b41a46ff 100644
--- a/src/main/java/org/olat/modules/forms/ui/CompareEvaluationsFormController.java
+++ b/src/main/java/org/olat/modules/forms/ui/CompareEvaluationsFormController.java
@@ -45,7 +45,7 @@ import org.olat.core.id.Identity;
 import org.olat.core.util.Formatter;
 import org.olat.core.util.StringHelper;
 import org.olat.core.util.vfs.VFSLeaf;
-import org.olat.core.util.vfs.VFSLeafMapper;
+import org.olat.core.util.vfs.VFSMediaMapper;
 import org.olat.core.util.xml.XStreamHelper;
 import org.olat.fileresource.FileResourceManager;
 import org.olat.modules.forms.EvaluationFormManager;
@@ -225,7 +225,7 @@ public class CompareEvaluationsFormController extends FormBasicController {
 		if (leaf != null) {
 			filename = leaf.getName();
 			filesize = Formatter.formatBytes((leaf).getSize());
-			mapperUri = registerCacheableMapper(ureq, "file-upload-" + element.getId() + "-" + leaf.getLastModified(), new VFSLeafMapper(leaf));
+			mapperUri = registerCacheableMapper(ureq, "file-upload-" + element.getId() + "-" + leaf.getLastModified(), new VFSMediaMapper(leaf));
 			iconCss = CSSHelper.createFiletypeIconCssClassFor(leaf.getName());
 			if (leaf instanceof MetaTagged) {
 				MetaTagged metaTaggedLeaf = (MetaTagged) leaf;
@@ -233,7 +233,7 @@ public class CompareEvaluationsFormController extends FormBasicController {
 				if (meta != null && meta.isThumbnailAvailable()) {
 					VFSLeaf thumb = meta.getThumbnail(200, 200, false);
 					if (thumb != null) {
-						thumbUri = registerCacheableMapper(ureq, "file-upload-thumb" + element.getId() + "-" + leaf.getLastModified(), new VFSLeafMapper(thumb));;
+						thumbUri = registerCacheableMapper(ureq, "file-upload-thumb" + element.getId() + "-" + leaf.getLastModified(), new VFSMediaMapper(thumb));;
 					}
 				}
 			}
diff --git a/src/main/java/org/olat/modules/forms/ui/EvaluationFormController.java b/src/main/java/org/olat/modules/forms/ui/EvaluationFormController.java
index 9a728cdc77ea1514fee73f8a8c50bf2593910ef6..1b5357376933ea450221821f16bb5e244d02f1f0 100644
--- a/src/main/java/org/olat/modules/forms/ui/EvaluationFormController.java
+++ b/src/main/java/org/olat/modules/forms/ui/EvaluationFormController.java
@@ -60,7 +60,6 @@ import org.olat.modules.forms.EvaluationFormManager;
 import org.olat.modules.forms.EvaluationFormResponse;
 import org.olat.modules.forms.EvaluationFormSession;
 import org.olat.modules.forms.EvaluationFormSessionStatus;
-import org.olat.modules.forms.manager.EvaluationFormStorage;
 import org.olat.modules.forms.model.xml.AbstractElement;
 import org.olat.modules.forms.model.xml.FileUpload;
 import org.olat.modules.forms.model.xml.Form;
@@ -88,7 +87,7 @@ import org.springframework.beans.factory.annotation.Autowired;
  */
 public class EvaluationFormController extends FormBasicController implements ValidatingController {
 	
-	private static final OLog log = Tracing.createLoggerFor(EvaluationFormStorage.class);
+	private static final OLog log = Tracing.createLoggerFor(EvaluationFormController.class);
 
 	private int count = 0;
 	private final Form form;
diff --git a/src/main/java/org/olat/modules/forms/ui/MimeTypeSetFactory.java b/src/main/java/org/olat/modules/forms/ui/MimeTypeSetFactory.java
index ca91a1ae728aa068203c423053a1bb52dd32b7f8..0109cd857c8551b2a8ee61019a84955a453120a9 100644
--- a/src/main/java/org/olat/modules/forms/ui/MimeTypeSetFactory.java
+++ b/src/main/java/org/olat/modules/forms/ui/MimeTypeSetFactory.java
@@ -19,6 +19,7 @@
  */
 package org.olat.modules.forms.ui;
 
+import java.util.Collections;
 import java.util.HashSet;
 import java.util.LinkedHashMap;
 import java.util.Map;
@@ -26,13 +27,14 @@ import java.util.Set;
 
 import org.olat.core.gui.translator.Translator;
 
+
 /**
  * 
  * Initial date: 07.02.2018<br>
  * @author uhensler, urs.hensler@frentix.com, http://www.frentix.com
  *
  */
-class MimeTypeSetFactory {
+final class MimeTypeSetFactory {
 	
 	private static final String TYPE_ALL_KEY = "file.upload.mime.type.all";
 	
@@ -41,13 +43,13 @@ class MimeTypeSetFactory {
 		mimeTypeSets.put(TYPE_ALL_KEY, null);
 		Set<String> pdf = new HashSet<>();
 		pdf.add("application/pdf");
-		mimeTypeSets.put("file.upload.mime.type.pdf", pdf);
+		mimeTypeSets.put("file.upload.mime.type.pdf", Collections.unmodifiableSet(pdf));
 		Set<String> images = new HashSet<>();
 		images.add("image/gif");
 		images.add("image/jpg");
 		images.add("image/jpeg");
 		images.add("image/png");
-		mimeTypeSets.put("file.upload.mime.type.image", images);
+		mimeTypeSets.put("file.upload.mime.type.image", Collections.unmodifiableSet(images));
 		Set<String> audios = new HashSet<>();
 		audios.add("audio/aac");
 		audios.add("audio/mp4");
@@ -55,10 +57,14 @@ class MimeTypeSetFactory {
 		audios.add("audio/ogg");
 		audios.add("audio/wav");
 		audios.add("audio/webm");
-		mimeTypeSets.put("file.upload.mime.type.audio", audios);
+		mimeTypeSets.put("file.upload.mime.type.audio", Collections.unmodifiableSet(audios));
 		Set<String> videos = new HashSet<>();
 		videos.add("video/mp4");
-		mimeTypeSets.put("file.upload.mime.type.video", videos);
+		mimeTypeSets.put("file.upload.mime.type.video", Collections.unmodifiableSet(videos));
+	}
+	
+	private MimeTypeSetFactory() {
+		// noninstantiable
 	}
 	
 	static String[] getKeys() {
diff --git a/src/main/java/org/olat/modules/portfolio/ui/media/FileMediaController.java b/src/main/java/org/olat/modules/portfolio/ui/media/FileMediaController.java
index 78bc4b2c9e2bdac8fc2c87b6fbdc0c1440c63914..23775cb2f539c75684fc760b42b0e19eab88e606 100644
--- a/src/main/java/org/olat/modules/portfolio/ui/media/FileMediaController.java
+++ b/src/main/java/org/olat/modules/portfolio/ui/media/FileMediaController.java
@@ -32,7 +32,7 @@ import org.olat.core.util.Util;
 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.VFSLeafMapper;
+import org.olat.core.util.vfs.VFSMediaMapper;
 import org.olat.modules.portfolio.Media;
 import org.olat.modules.portfolio.MediaRenderingHints;
 import org.olat.modules.portfolio.manager.PortfolioFileStorage;
@@ -73,7 +73,7 @@ public class FileMediaController extends BasicController {
 		VFSItem item = container.resolve(media.getRootFilename());
 		if(item instanceof VFSLeaf) {
 			VFSLeaf leaf = (VFSLeaf)item;
-			String mapperUri = registerCacheableMapper(ureq, "File-Media-" + media.getKey() + "-" + leaf.getLastModified(), new VFSLeafMapper(leaf));
+			String mapperUri = registerCacheableMapper(ureq, "File-Media-" + media.getKey() + "-" + leaf.getLastModified(), new VFSMediaMapper(leaf));
 			mainVC.contextPut("mapperUri", mapperUri);
 			String iconCss = CSSHelper.createFiletypeIconCssClassFor(leaf.getName());
 			mainVC.contextPut("fileIconCss", iconCss);
diff --git a/src/test/java/org/olat/modules/forms/manager/EvaluationFormStorageTest.java b/src/test/java/org/olat/modules/forms/manager/EvaluationFormStorageTest.java
index 21df65f8d9ab99c3839714d4d97da31b3319fb6f..1e875c1fcceae58e10352e7caf8e98b55a7ac8f0 100644
--- a/src/test/java/org/olat/modules/forms/manager/EvaluationFormStorageTest.java
+++ b/src/test/java/org/olat/modules/forms/manager/EvaluationFormStorageTest.java
@@ -62,14 +62,14 @@ public class EvaluationFormStorageTest extends OlatTestCase {
 	public void shouldSaveNewFile() throws Exception {
 		File file = getExistingFile();
 		
-		Path relativePath = sut.save(file, getRandomFilename(), getRandomIdentifier());
+		Path relativePath = sut.save(file, getRandomFilename());
 		
 		assertThat(relativePath).isNotNull();
 	}
 
 	@Test
 	public void shouldLoadFile() throws Exception {
-		Path relativePath = sut.save(getExistingFile(), getRandomFilename(), getRandomIdentifier());
+		Path relativePath = sut.save(getExistingFile(), getRandomFilename());
 		
 		File loadedFile = sut.load(relativePath);
 		
@@ -79,7 +79,7 @@ public class EvaluationFormStorageTest extends OlatTestCase {
 	@Test
 	public void shouldDeleteFile() throws Exception {
 		assertThat(getExistingFile()).exists();
-		Path relativePath = sut.save(getExistingFile(), getRandomFilename(), getRandomIdentifier());
+		Path relativePath = sut.save(getExistingFile(), getRandomFilename());
 		File loadedFile = sut.load(relativePath);
 		assertThat(loadedFile).exists();
 		
@@ -97,8 +97,4 @@ public class EvaluationFormStorageTest extends OlatTestCase {
 		return UUID.randomUUID().toString();
 	}
 
-	private String getRandomIdentifier() {
-		return UUID.randomUUID().toString();
-	}
-
 }