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;
}
}
- // 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
+ response.setHeader("Content-Disposition",
+ getContentDispositionValue());
int bufferSize = getBufferSize();
if (bufferSize <= 0 || bufferSize > Constants.MAX_BUFFER_SIZE) {
}
}
+ private String getContentDispositionValue()
+ throws UnsupportedEncodingException {
+ String contentDispositionValue = getParameter("Content-Disposition");
+
+ if (contentDispositionValue == null) {
+ String encodedFilename = URLEncoder.encode(getFileName(), "utf-8");
+
+ contentDispositionValue = String.format(
+ "attachment; filename=\"%s\"; filename*=utf-8''%s",
+ encodedFilename, encodedFilename);
+ }
+
+ return contentDispositionValue;
+ }
+
/**
* Helper method that tries to close an output stream and ignores any
* exceptions.
}
stream = ((ConnectorResource) resource).getStream();
- if (stream.getParameter("Content-Disposition") == null) {
- // Content-Disposition: attachment generally forces download
- stream.setParameter("Content-Disposition",
- "attachment; filename=\"" + stream.getFileName() + "\"");
- }
-
// Content-Type to block eager browser plug-ins from hijacking
// the file
if (isOverrideContentType()) {
--- /dev/null
+package com.vaadin.server;
+
+import static org.mockito.Matchers.contains;
+import static org.mockito.Matchers.eq;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.verify;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.net.URLEncoder;
+
+import org.junit.Before;
+import org.junit.Test;
+
+public class FileDownloaderTests {
+ private String filename = "日本語.png";
+ private DownloadStream stream;
+
+ @Before
+ public void setup() {
+ stream = new DownloadStream(mock(InputStream.class), "", filename);
+ }
+
+ @Test
+ public void contentDispositionFilenameIsUtf8Encoded() throws IOException {
+ VaadinResponse response = mock(VaadinResponse.class);
+
+ stream.writeResponse(mock(VaadinRequest.class), response);
+
+ verify(response).setHeader(eq("Content-Disposition"),
+ contains("attachment;"));
+ String encodedFileName = URLEncoder.encode(filename, "utf-8");
+ verify(response).setHeader(eq("Content-Disposition"),
+ contains(String.format("filename=\"%s\";", encodedFileName)));
+ verify(response)
+ .setHeader(
+ eq("Content-Disposition"),
+ contains(String.format("filename*=utf-8''%s",
+ encodedFileName)));
+ }
+}