You are viewing a plain text version of this content. The canonical link for it is here.
Posted to dev@struts.apache.org by ma...@apache.org on 2004/10/30 04:50:56 UTC
svn commit: rev 56011 - struts/trunk/src/share/org/apache/struts/actions
Author: martinc
Date: Fri Oct 29 19:50:56 2004
New Revision: 56011
Added:
struts/trunk/src/share/org/apache/struts/actions/DownloadAction.java
Log:
New abstract action that provides the nuts and bolts for downloading files from a Struts application.
Added: struts/trunk/src/share/org/apache/struts/actions/DownloadAction.java
==============================================================================
--- (empty file)
+++ struts/trunk/src/share/org/apache/struts/actions/DownloadAction.java Fri Oct 29 19:50:56 2004
@@ -0,0 +1,273 @@
+/*
+ * $Id$
+ *
+ * Copyright 2004 The Apache Software Foundation.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+
+package org.apache.struts.actions;
+
+import java.io.BufferedInputStream;
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStream;
+
+import javax.servlet.ServletContext;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+
+import org.apache.struts.action.Action;
+import org.apache.struts.action.ActionForm;
+import org.apache.struts.action.ActionForward;
+import org.apache.struts.action.ActionMapping;
+
+
+/**
+ * This is an abstract base class that minimizes the amount of special coding
+ * that needs to be written to download a file. All that is required to use
+ * this class is to extend it and implement the <code>getStreamInfo()</code>
+ * method so that it returns the relevant information for the file (or other
+ * stream) to be downloaded. Optionally, the <code>getBufferSize()</code>
+ * method may be overridden to customize the size of the buffer used to
+ * transfer the file.
+ *
+ * @since Struts 1.2.6
+ */
+public abstract class DownloadAction extends Action {
+
+ /**
+ * If the <code>getBufferSize()</code> method is not overridden, this is
+ * the buffer size that will be used to transfer the data to the servlet
+ * output stream.
+ */
+ protected static final int DEFAULT_BUFFER_SIZE = 1024 * 4;
+
+ /**
+ * Returns the information on the file, or other stream, to be downloaded
+ * by this action. This method must be implemented by an extending class.
+ *
+ * @param mapping The ActionMapping used to select this instance.
+ * @param form The optional ActionForm bean for this request (if any).
+ * @param request The HTTP request we are processing.
+ * @param response The HTTP response we are creating.
+ *
+ * @return The information for the file to be downloaded.
+ *
+ * @throws Exception if an exception occurs.
+ */
+ protected abstract StreamInfo getStreamInfo(ActionMapping mapping,
+ ActionForm form, HttpServletRequest request,
+ HttpServletResponse response)
+ throws Exception;
+
+ /**
+ * Returns the size of the buffer to be used in transferring the data to
+ * the servlet output stream. This method may be overridden by an extending
+ * class in order to customize the buffer size.
+ *
+ * @return The size of the transfer buffer, in bytes.
+ */
+ protected int getBufferSize() {
+ return DEFAULT_BUFFER_SIZE;
+ }
+
+ /**
+ * Process the specified HTTP request, and create the corresponding HTTP
+ * response (or forward to another web component that will create it).
+ * Return an <code>ActionForward</code> instance describing where and how
+ * control should be forwarded, or <code>null</code> if the response has
+ * already been completed.
+ *
+ * @param mapping The ActionMapping used to select this instance.
+ * @param form The optional ActionForm bean for this request (if any).
+ * @param request The HTTP request we are processing.
+ * @param response The HTTP response we are creating.
+ *
+ * @throws Exception if an exception occurs.
+ */
+ public ActionForward execute(ActionMapping mapping, ActionForm form,
+ HttpServletRequest request, HttpServletResponse response)
+ throws Exception {
+
+ StreamInfo info = getStreamInfo(mapping, form, request, response);
+ String contentType = info.getContentType();
+ InputStream stream = info.getInputStream();
+
+ try {
+ response.setContentType(contentType);
+ copy(stream, response.getOutputStream());
+ } finally {
+ if (stream != null) {
+ stream.close();
+ }
+ }
+
+ // Tell Struts that we are done with the response.
+ return null;
+ }
+
+ /**
+ * Copy bytes from an <code>InputStream</code> to an
+ * <code>OutputStream</code>.
+ *
+ * @param input The <code>InputStream</code> to read from.
+ * @param output The <code>OutputStream</code> to write to.
+ *
+ * @return the number of bytes copied
+ *
+ * @throws IOException In case of an I/O problem
+ */
+ public static int copy(InputStream input, OutputStream output)
+ throws IOException {
+ byte[] buffer = new byte[DEFAULT_BUFFER_SIZE];
+ int count = 0;
+ int n = 0;
+ while (-1 != (n = input.read(buffer))) {
+ output.write(buffer, 0, n);
+ count += n;
+ }
+ return count;
+ }
+
+ /**
+ * The information on a file, or other stream, to be downloaded by the
+ * <code>DownloadAction</code>.
+ */
+ public static interface StreamInfo {
+
+ /**
+ * Returns the content type of the stream to be downloaded.
+ *
+ * @return The content type of the stream.
+ */
+ public abstract String getContentType();
+
+ /**
+ * Returns an input stream on the content to be downloaded. This stream
+ * will be closed by the <code>DownloadAction</code>.
+ *
+ * @return The input stream for the content to be downloaded.
+ */
+ public abstract InputStream getInputStream() throws IOException;
+ }
+
+ /**
+ * A concrete implementation of the <code>StreamInfo</code> interface which
+ * simplifies the downloading of a file from the disk.
+ */
+ public static class FileStreamInfo implements StreamInfo {
+
+ /**
+ * The content type for this stream.
+ */
+ private String contentType;
+
+ /**
+ * The file to be downloaded.
+ */
+ private File file;
+
+ /**
+ * Constructs an instance of this class, based on the supplied
+ * parameters.
+ *
+ * @param contentType The content type of the file.
+ * @param file The file to be downloaded.
+ */
+ public FileStreamInfo(String contentType, File file) {
+ this.contentType = contentType;
+ this.file = file;
+ }
+
+ /**
+ * Returns the content type of the stream to be downloaded.
+ *
+ * @return The content type of the stream.
+ */
+ public String getContentType() {
+ return this.contentType;
+ }
+
+ /**
+ * Returns an input stream on the file to be downloaded. This stream
+ * will be closed by the <code>DownloadAction</code>.
+ *
+ * @return The input stream for the file to be downloaded.
+ */
+ public InputStream getInputStream() throws IOException {
+ FileInputStream fis = new FileInputStream(file);
+ BufferedInputStream bis = new BufferedInputStream(fis);
+ return bis;
+ }
+ }
+
+ /**
+ * A concrete implementation of the <code>StreamInfo</code> interface which
+ * simplifies the downloading of a web application resource.
+ */
+ public static class ResourceStreamInfo implements StreamInfo {
+
+ /**
+ * The content type for this stream.
+ */
+ private String contentType;
+
+ /**
+ * The servlet context for the resource to be downloaded.
+ */
+ private ServletContext context;
+
+ /**
+ * The path to the resource to be downloaded.
+ */
+ private String path;
+
+ /**
+ * Constructs an instance of this class, based on the supplied
+ * parameters.
+ *
+ * @param contentType The content type of the file.
+ * @param context The servlet context for the resource.
+ * @param path The path to the resource to be downloaded.
+ */
+ public ResourceStreamInfo(String contentType, ServletContext context,
+ String path) {
+ this.contentType = contentType;
+ this.context = context;
+ this.path = path;
+ }
+
+ /**
+ * Returns the content type of the stream to be downloaded.
+ *
+ * @return The content type of the stream.
+ */
+ public String getContentType() {
+ return this.contentType;
+ }
+
+ /**
+ * Returns an input stream on the resource to be downloaded. This stream
+ * will be closed by the <code>DownloadAction</code>.
+ *
+ * @return The input stream for the resource to be downloaded.
+ */
+ public InputStream getInputStream() throws IOException {
+ return context.getResourceAsStream(path);
+ }
+ }
+}
---------------------------------------------------------------------
To unsubscribe, e-mail: dev-unsubscribe@struts.apache.org
For additional commands, e-mail: dev-help@struts.apache.org