MNT-23103 - Downloading a document replaces filename having space with + character (#1327)

* MNT-23103 Change encoder for content disposition filename to be consistent with RFC5987.

Add test covering filename encoding.
This commit is contained in:
Kacper Magdziarz
2022-08-24 15:59:11 +02:00
committed by GitHub
parent 700fbce572
commit 3aac7be11c
3 changed files with 65 additions and 3 deletions

View File

@@ -30,6 +30,7 @@ import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.io.UnsupportedEncodingException;
import java.net.SocketException;
import java.net.URLEncoder;
import java.nio.charset.StandardCharsets;
@@ -59,6 +60,7 @@ import org.alfresco.service.namespace.QName;
import org.alfresco.util.TempFileProvider;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.apache.cxf.attachment.Rfc5987Util;
import org.springframework.context.ResourceLoaderAware;
import org.springframework.core.io.ResourceLoader;
import org.springframework.extensions.webscripts.Cache;
@@ -472,7 +474,7 @@ public class ContentStreamer implements ResourceLoaderAware
if (req == null)
{
headerValue += "; filename*=UTF-8''" + URLEncoder.encode(attachFileName, StandardCharsets.UTF_8)
headerValue += "; filename*=UTF-8''" + encodeFilename(attachFileName)
+ "; filename=\"" + filterNameForQuotedString(attachFileName) + "\"";
}
else
@@ -481,12 +483,12 @@ public class ContentStreamer implements ResourceLoaderAware
boolean isLegacy = (null != userAgent) && (userAgent.contains("MSIE 8") || userAgent.contains("MSIE 7"));
if (isLegacy)
{
headerValue += "; filename=\"" + URLEncoder.encode(attachFileName, StandardCharsets.UTF_8);
headerValue += "; filename=\"" + encodeFilename(attachFileName);
}
else
{
headerValue += "; filename=\"" + filterNameForQuotedString(attachFileName) + "\"; filename*=UTF-8''"
+ URLEncoder.encode(attachFileName, StandardCharsets.UTF_8);
+ encodeFilename(attachFileName);
}
}
}
@@ -496,6 +498,21 @@ public class ContentStreamer implements ResourceLoaderAware
res.setHeader("Content-Disposition", headerValue);
}
}
private String encodeFilename(String attachFileName)
{
try
{
return Rfc5987Util.encode(attachFileName);
}
catch (UnsupportedEncodingException e)
{
if (logger.isInfoEnabled())
logger.info(e.getMessage() + " Changing encoder from Rfc5987Util to java.net.URLEncoder.");
return URLEncoder.encode(attachFileName, StandardCharsets.UTF_8);
}
}
protected String filterNameForQuotedString(String s)
{

View File

@@ -3721,6 +3721,50 @@ public class NodeApiTest extends AbstractSingleNetworkSiteTest
getSingle(getNodeContentUrl(contentNodeId), null, null, headers, 304);
}
/**
* Tests download of file/content name.
* <p>GET:</p>
* {@literal <host>:<port>/alfresco/api/-default-/public/alfresco/versions/1/nodes/<nodeId>/content}
*/
@Test
public void testDownloadFileContentName() throws Exception
{
setRequestContext(user1);
//
// Test plain text
//
String fileName = "Test Download (1).txt";
File file = getResourceFile(fileName);
MultiPartBuilder multiPartBuilder = MultiPartBuilder.create()
.setFileData(new FileData(fileName, file));
MultiPartRequest reqBody = multiPartBuilder.build();
// Upload text content
HttpResponse response = post(getNodeChildrenUrl(Nodes.PATH_MY), reqBody.getBody(), null, reqBody.getContentType(), 201);
Document document = RestApiUtil.parseRestApiEntry(response.getJsonResponse(), Document.class);
String contentNodeId = document.getId();
// Check the upload response
assertEquals(fileName, document.getName());
ContentInfo contentInfo = document.getContent();
assertNotNull(contentInfo);
assertEquals(MimetypeMap.MIMETYPE_TEXT_PLAIN, contentInfo.getMimeType());
// Download text content - by default with Content-Disposition header
response = getSingle(NodesEntityResource.class, contentNodeId + "/content", null, 200);
String textContent = response.getResponse();
assertEquals("The quick brown fox jumps over the lazy dog", textContent);
Map<String, String> responseHeaders = response.getHeaders();
assertNotNull(responseHeaders);
assertEquals("attachment; filename=\"Test Download (1).txt\"; filename*=UTF-8''Test%20Download%20%281%29.txt", responseHeaders.get("Content-Disposition"));
}
/**
* Tests download of file/content using backed temp file for streaming.
* <p>

View File

@@ -0,0 +1 @@
The quick brown fox jumps over the lazy dog