vaadin / framework

Vaadin 6, 7, 8 is a Java framework for modern Java web applications.
http://vaadin.com/
Other
1.78k stars 729 forks source link

Non-ascii filenames cause unreadable names when downloading via IE from FileResource #2016

Closed vaadin-bot closed 9 years ago

vaadin-bot commented 12 years ago

Originally by darton


Steps to reproduce:

-*Possible cause:**

When downloading a resource, the filename gets passed to the client twice: first, in a json structure that apparently initiates the download, then in Content-Disposition header of the actual resource stream. Json data is properly URL-coded, but the header contains filename as-is. However, Java Servlet Specification requires the value passed to HttpServletResponse.addHeader(String, String) to be URL-coded, and Tomcat quietly replaces the non-latin chars. Finally, IE seems to get downloaded blob name from content-disposition, which contains cryptic string (while e.g. FF seems to get resource name from URL which is ok).

-*Workaround:**

Don't use FileResource when passing files which may have non-latin names to the client. Copypaste it into some HackedFileResource and replace its getStream() implementation with something like:

     public DownloadStream getStream() {
        try {
            final DownloadStream ds = new DownloadStream(
                    new FileInputStream( sourceFile ), 
                    getMIMEType(), 
    // {{ this is the only difference from FileResource's implementation
                    URLEncoder.encode( getFilename(), "UTF-8" ) );
    // }} the only difference ends here
            ds.setParameter("Content-Length", String.valueOf(sourceFile.length()));

            ds.setCacheTime(cacheTime);
            return ds;
        } catch (final FileNotFoundException e) {
            // Log the exception using the application error handler
            getApplication().getErrorHandler().terminalError(new ErrorEvent() {

                public Throwable getThrowable() {
                    return e;
                }

            });

            return null;
        } catch ( UnsupportedEncodingException e ) {
            throw new RuntimeException( "Impossible, UTF8 must always be supported!", e );
        }
    }

Imported from https://dev.vaadin.com/ issue #8155

vaadin-bot commented 12 years ago

Originally by darton


Update: the workaround above works only in IE, other browsers display %-encoded names as is. Thus we had to look at the user-agent string, and encode the filename only if it contains "MSIE" substring.

The correct way to solve the issue is probably to patch AbstractApplicationServlet.handleDownload() to encode the name before putting it into Content-Disposition header.

vaadin-bot commented 12 years ago

Originally by @Artur-


I could not reproduce the problem as described using Tomcat 6/7 on Windows 7. Sending a file named "special åäö#$ chars in name.txt" (using a FileResource) to the browser results in:

For IE9 - both are wrong, either " " is converted to "+" or "#" to "_". For Chrome, it does not matter as it does not seem to use the header but instead the URL and gets it wrong with Tomcat (works fine with Jetty). Firefox is wrong when using URL encoding and correct otherwise.

HttpServletResponse.addHeader javadoc actually says "the additional header value If it contains octet string, it should be encoded according to RFC 2047 (http://www.ietf.org/rfc/rfc2047.txt)". RFC 2047 is MIME encoding and not URL encoding.

vaadin-bot commented 9 years ago

Originally by @Artur-


A lot of tickets have been left hanging in the issue tracker through the years. Some of them are still relevant, some of them have been fixed a long time ago and some are no longer valid. To get a better look on what is important and still relevant, we are closing old tickets which have not been touched in a long time.

No further work will be done on this ticket unless someone indicates that it's still relevant.

If this ticket is still relevant to you, please reopen it.