Revision: 1171
          http://stripes.svn.sourceforge.net/stripes/?rev=1171&view=rev
Author:   bengunter
Date:     2009-10-19 17:33:27 +0000 (Mon, 19 Oct 2009)

Log Message:
-----------
Applied fix for STS-583 from 1.5.x branch.

Modified Paths:
--------------
    trunk/stripes/src/net/sourceforge/stripes/action/StreamingResolution.java

Modified: 
trunk/stripes/src/net/sourceforge/stripes/action/StreamingResolution.java
===================================================================
--- trunk/stripes/src/net/sourceforge/stripes/action/StreamingResolution.java   
2009-10-19 17:30:35 UTC (rev 1170)
+++ trunk/stripes/src/net/sourceforge/stripes/action/StreamingResolution.java   
2009-10-19 17:33:27 UTC (rev 1171)
@@ -25,6 +25,8 @@
 import java.io.PrintWriter;
 import java.io.Reader;
 import java.io.StringReader;
+import java.text.SimpleDateFormat;
+import java.util.Date;
 
 /**
  * <p>Resolution for streaming data back to the client (in place of forwarding 
the user to
@@ -54,12 +56,17 @@
  * @author Tim Fennell
  */
 public class StreamingResolution implements Resolution {
+    /** Date format string for RFC 822 dates. */
+    private static final String RFC_822_DATE_FORMAT = "EEE, d MMM yyyy 
HH:mm:ss Z";
     private static final Log log = Log.getInstance(StreamingResolution.class);
     private InputStream inputStream;
     private Reader reader;
     private String filename;
     private String contentType;
     private String characterEncoding;
+    private long lastModified = -1;
+    private long length = -1;
+    private boolean attachment;
 
     /**
      * Constructor only to be used when subclassing the StreamingResolution 
(usually using
@@ -118,6 +125,7 @@
      */
     public StreamingResolution setFilename(String filename) {
         this.filename = filename;
+        setAttachment(filename != null);
         return this;
     }
 
@@ -133,6 +141,47 @@
     }
 
     /**
+     * Sets the modification-date timestamp. If this property is set, the 
browser may be able to
+     * apply it to the downloaded file. If this property is unset, the 
modification-date parameter
+     * will be omitted.
+     * 
+     * @param lastModified The date-time (as a long) that the file was last 
modified. Optional.
+     * @return StreamingResolution so that this method call can be chained to 
the constructor and
+     *         returned.
+     */
+    public StreamingResolution setLastModified(long lastModified) {
+        this.lastModified = lastModified;
+        return this;
+    }
+
+    /**
+     * Sets the file length. If this property is set, the file size will be 
reported in the HTTP
+     * header. This may help with file download progress indicators. If this 
property is unset, the
+     * size parameter will be omitted.
+     * 
+     * @param length The length of the file in bytes.
+     * @return StreamingResolution so that this method call can be chained to 
the constructor and
+     *         returned.
+     */
+    public StreamingResolution setLength(long length) {
+        this.length = length;
+        return this;
+    }
+
+    /**
+     * Indicates whether to use content-disposition attachment headers or not. 
(Defaults to true).
+     * 
+     * @param attachment Whether the content should be treated as an 
attachment, or a direct
+     *            download.
+     * @return StreamingResolution so that this method call can be chained to 
the constructor and
+     *         returned.
+     */
+    public StreamingResolution setAttachment(boolean attachment) {
+        this.attachment = attachment;
+        return this;
+    }
+
+    /**
      * Streams data from the InputStream or Reader to the response's 
OutputStream or PrinterWriter,
      * using a moderately sized buffer to ensure that the operation is 
reasonable efficient.
      * Once the InputStream or Reader signaled the end of the stream, close() 
is called on it.
@@ -142,19 +191,54 @@
      * @throws IOException if there is a problem accessing one of the streams 
or reader/writer
      *         objects used.
      */
-    final public void execute(HttpServletRequest request, HttpServletResponse 
response) throws Exception {
+    final public void execute(HttpServletRequest request, HttpServletResponse 
response)
+            throws Exception {
+        applyHeaders(response);
+        stream(response);
+    }
+
+    /**
+     * Sets the response headers, based on what is known about the file or 
stream being handled.
+     * 
+     * @param response the current HttpServletResponse
+     */
+    protected void applyHeaders(HttpServletResponse response) {
         response.setContentType(this.contentType);
-        if (this.characterEncoding != null) 
response.setCharacterEncoding(characterEncoding);
+        if (this.characterEncoding != null) {
+            response.setCharacterEncoding(characterEncoding);
+        }
 
-        // If a filename was specified, set the appropriate header
-        if (this.filename != null) {
+        // Set Content-Length header
+        if (length >= 0) {
+            // Odd that ServletResponse.setContentLength is limited to int.
+            // requires downcast from long to int e.g.
+            // response.setContentLength((int)length);
+            // Workaround to allow large files:
+            response.addHeader("Content-Length", Long.toString(length));
+        }
+
+        // Set Last-Modified header
+        if (lastModified >= 0) {
+            response.setDateHeader("Last-Modified", lastModified);
+        }
+
+        // For Content-Disposition spec, see 
http://www.ietf.org/rfc/rfc2183.txt
+        if (attachment || filename != null) {
             // Value of filename should be RFC 2047 encoded here (see RFC 
2616) but few browsers
             // support that, so just escape the quote for now
             String escaped = this.filename.replace("\"", "\\\"");
-            response.setHeader("Content-Disposition", "attachment; 
filename=\"" + escaped + "\"");
+            StringBuilder header = new StringBuilder(attachment ? "attachment" 
: "inline").append(
+                    ";filename=\"").append(escaped).append("\"");
+            if (lastModified >= 0) {
+                SimpleDateFormat format = new 
SimpleDateFormat(RFC_822_DATE_FORMAT);
+                String value = format.format(new Date(lastModified));
+                
header.append(";modification-date=\"").append(value).append("\"");
+            }
+            if (length >= 0) {
+                header.append(";size=").append(length);
+            }
+            response.setHeader("Content-Disposition", header.toString());
         }
-
-        stream(response);
     }
 
     /**


This was sent by the SourceForge.net collaborative development platform, the 
world's largest Open Source development site.

------------------------------------------------------------------------------
Come build with us! The BlackBerry(R) Developer Conference in SF, CA
is the only developer event you need to attend this year. Jumpstart your
developing skills, take BlackBerry mobile applications to market and stay 
ahead of the curve. Join us from November 9 - 12, 2009. Register now!
http://p.sf.net/sfu/devconference
_______________________________________________
Stripes-development mailing list
[email protected]
https://lists.sourceforge.net/lists/listinfo/stripes-development

Reply via email to