summaryrefslogtreecommitdiffstats
path: root/server/src
diff options
context:
space:
mode:
authorAnna Miroshnik <anna.miroshnik@arcadia.spb.ru>2015-03-12 18:56:10 +0300
committerVaadin Code Review <review@vaadin.com>2015-06-05 14:03:47 +0000
commitd7284ccfe40f7028e880328566bb825ea31ad619 (patch)
tree6f1f4b4a676aa7e2bd57ed12162ab1860bd959ea /server/src
parentc4d006d0c6098b1047adb56c0fc7df6f71fe620c (diff)
downloadvaadin-framework-d7284ccfe40f7028e880328566bb825ea31ad619.tar.gz
vaadin-framework-d7284ccfe40f7028e880328566bb825ea31ad619.zip
Format UTF-8 filenames correctly for download (#16556)
The code is the same for both FileDownloader and DownloadStream except that FileDownloader forces the content-type to be an "attachment". Change-Id: I50abf3b0f019b773bc0a44b16536a9479f9f472f
Diffstat (limited to 'server/src')
-rw-r--r--server/src/com/vaadin/server/DownloadStream.java44
-rw-r--r--server/src/com/vaadin/server/FileDownloader.java14
2 files changed, 45 insertions, 13 deletions
diff --git a/server/src/com/vaadin/server/DownloadStream.java b/server/src/com/vaadin/server/DownloadStream.java
index 681c438967..0dfd9e42c3 100644
--- a/server/src/com/vaadin/server/DownloadStream.java
+++ b/server/src/com/vaadin/server/DownloadStream.java
@@ -20,9 +20,12 @@ import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.io.Serializable;
+import java.io.UnsupportedEncodingException;
+import java.net.URLEncoder;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
+import java.util.logging.Logger;
import javax.servlet.http.HttpServletResponse;
@@ -40,6 +43,8 @@ import javax.servlet.http.HttpServletResponse;
@SuppressWarnings("serial")
public class DownloadStream implements Serializable {
+ public static final String CONTENT_DISPOSITION = "Content-Disposition";
+
/**
* Maximum cache time.
*/
@@ -280,17 +285,14 @@ public class DownloadStream implements Serializable {
}
}
- // suggest local filename from DownloadStream if
- // Content-Disposition
- // not explicitly set
- String contentDispositionValue = getParameter("Content-Disposition");
- if (contentDispositionValue == null) {
- contentDispositionValue = "filename=\"" + getFileName()
- + "\"";
- response.setHeader("Content-Disposition",
- contentDispositionValue);
+ // Content-Disposition: attachment generally forces download
+ String contentDisposition = getParameter(CONTENT_DISPOSITION);
+ if (contentDisposition == null) {
+ contentDisposition = getContentDispositionFilename(getFileName());
}
+ response.setHeader(CONTENT_DISPOSITION, contentDisposition);
+
int bufferSize = getBufferSize();
if (bufferSize <= 0 || bufferSize > Constants.MAX_BUFFER_SIZE) {
bufferSize = Constants.DEFAULT_BUFFER_SIZE;
@@ -318,6 +320,30 @@ public class DownloadStream implements Serializable {
}
/**
+ * Returns the filename formatted for inclusion in a Content-Disposition
+ * header. Includes both a plain version of the name and a UTF-8 version
+ *
+ * @since
+ * @param filename
+ * The filename to include
+ * @return A value for inclusion in a Content-Disposition header
+ */
+ public static String getContentDispositionFilename(String filename) {
+ try {
+ String encodedFilename = URLEncoder.encode(filename, "UTF-8");
+ return String.format("filename=\"%s\"; filename*=utf-8''%s",
+ encodedFilename, encodedFilename);
+ } catch (UnsupportedEncodingException e) {
+ return null;
+ }
+
+ }
+
+ public static Logger getLogger() {
+ return Logger.getLogger(DownloadStream.class.getName());
+ }
+
+ /**
* Helper method that tries to close an output stream and ignores any
* exceptions.
*
diff --git a/server/src/com/vaadin/server/FileDownloader.java b/server/src/com/vaadin/server/FileDownloader.java
index 42c2f76e1a..b0c3bb1120 100644
--- a/server/src/com/vaadin/server/FileDownloader.java
+++ b/server/src/com/vaadin/server/FileDownloader.java
@@ -141,12 +141,17 @@ public class FileDownloader extends AbstractExtension {
}
stream = ((ConnectorResource) resource).getStream();
- if (stream.getParameter("Content-Disposition") == null) {
- // Content-Disposition: attachment generally forces download
- stream.setParameter("Content-Disposition",
- "attachment; filename=\"" + stream.getFileName() + "\"");
+ String contentDisposition = stream
+ .getParameter(DownloadStream.CONTENT_DISPOSITION);
+ if (contentDisposition == null) {
+ contentDisposition = "attachment; "
+ + DownloadStream.getContentDispositionFilename(stream
+ .getFileName());
}
+ stream.setParameter(DownloadStream.CONTENT_DISPOSITION,
+ contentDisposition);
+
// Content-Type to block eager browser plug-ins from hijacking
// the file
if (isOverrideContentType()) {
@@ -158,4 +163,5 @@ public class FileDownloader extends AbstractExtension {
stream.writeResponse(request, response);
return true;
}
+
}