jp.terasoluna.fw.web.struts.actions.FileDownloadUtil.java Source code

Java tutorial

Introduction

Here is the source code for jp.terasoluna.fw.web.struts.actions.FileDownloadUtil.java

Source

/*
 * Copyright (c) 2007 NTT DATA Corporation
 *
 * 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 jp.terasoluna.fw.web.struts.actions;

import java.beans.PropertyDescriptor;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.lang.reflect.Method;
import java.net.SocketException;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.Map.Entry;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import jp.terasoluna.fw.exception.SystemException;

import org.apache.commons.fileupload.util.Streams;
import org.apache.commons.lang.StringUtils;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.springframework.beans.BeanWrapper;
import org.springframework.beans.BeanWrapperImpl;

/**
 * t@C_E??[h?s?[eBeBNX?B
 * <p>
 * <h5>_E??[ht@CGR?[fBO?X</h5>
 * _E??[hwt@C?iuEU?\t@C?j
 * GR?[fBOftHgInternet Explorer?B
 * GR?[fBO?X?A{@link DownloadFileNameEncoder}NX
 * ???ABean`t@C??sKv?B
 *
 * <h5><code>DownloadFileNameEncoder</code></h5>
 * <code>User-Agent</code>uEU?A
 * FireFox??commons-codecNXpGR?[fBO?s?B
 * <pre><code>
 * public class MyEncoder implements DownloadFileNameEncoder {
 *
 *     public String encode(String original, HttpServletRequest request,
 *             HttpServletResponse response) {
 *         String userAgent = request.getHeader("User-Agent");
 *         if (StringUtils.contains(userAgent, "MSIE")) {
 *             return encodeForIE(original);
 *         } else if (StringUtils.contains(userAgent, "Gecko")) {
 *             return encodeForGecko(original);
 *         }
 *         return encodeForIE(original);
 *     }
 *
 *     protected String encodeForGecko(String original) {
 *         try {
 *             return new BCodec().encode(original);
 *         } catch (EncoderException e) {
 *             return original;
 *         }
 *     }
 *
 *     protected String encodeForIE(String original) {
 *         try {
 *             return URLEncoder.encode(original,
 *                     AbstractDownloadObject.DEFAULT_CHARSET);
 *         } catch (UnsupportedEncodingException e) {
 *             return original;
 *         }
 *     }
 * }
 * </code></pre>
 *
 * <h5>Bean`t@C?</h5>
 * <pre><code>
 * &lt;bean class=&quot;jp.terasoluna.fw.web.struts.actions.FileDownloadUtil&quot;&gt;
 *   &lt;property name=&quot;encoder&quot; ref=&quot;encoder&quot;/&gt;
 * &lt;/bean&gt;
 * &lt;bean name=&quot;encoder&quot; class=&quot;sample.MyEncoder&quot;/&gt;
 * </code></pre>
 */
public class FileDownloadUtil {

    /**
     * ?ONX?B
     */
    private final static Log log = LogFactory.getLog(FileDownloadUtil.class);

    /**
     * X|X<code>CONTENT-DISPOSITION</code>wb_?B
     */
    public static final String HEADER_CONTENT_DISPOSITION = "Content-Disposition";

    /**
     * _E??[h?CX^X1???G?[R?[h?B
     */
    public static final String TOO_MANY_DOWNLOAD_ERROR = "errors.too.many.download";

    /**
     * wt@CGR?[_?B
     */
    protected static DownloadFileNameEncoder encoder = new DownloadFileNameEncoderImpl();

    /**
     * wt@CGR?[_??B
     *
     * @param encoder wt@CGR?[_?B
     */
    public void setEncoder(DownloadFileNameEncoder encoder) {
        if (encoder == null) {
            throw new IllegalArgumentException("encoder must not be null.");
        }
        FileDownloadUtil.encoder = encoder;
    }

    /**
     * uEU_E??[h?B
     *
     * @param result _E??[hf?[^?CX^X?B
     * @param request NGXg?B
     * @param response X|X?B
     */
    @SuppressWarnings("unchecked")
    public static void download(Object result, HttpServletRequest request, HttpServletResponse response) {
        List<AbstractDownloadObject> downloadList = new ArrayList<AbstractDownloadObject>();

        if (result instanceof AbstractDownloadObject) {
            downloadList.add((AbstractDownloadObject) result);
        } else {
            BeanWrapper wrapper = new BeanWrapperImpl(result);
            PropertyDescriptor[] propertyDescriptors = wrapper.getPropertyDescriptors();
            for (PropertyDescriptor propertyDescriptor : propertyDescriptors) {
                Method readMethod = propertyDescriptor.getReadMethod();
                if (readMethod == null) {
                    continue;
                }
                Class type = readMethod.getReturnType();
                if (AbstractDownloadObject.class.isAssignableFrom(type)) {
                    downloadList
                            .add((AbstractDownloadObject) wrapper.getPropertyValue(propertyDescriptor.getName()));
                }
            }
        }

        if (downloadList.isEmpty()) {
            return;
        }
        // _E??[hIuWFNg???O
        if (downloadList.size() != 1) {
            throw new SystemException(new IllegalStateException("Too many AbstractDownloadObject properties."),
                    TOO_MANY_DOWNLOAD_ERROR);
        }

        try {
            download(downloadList.get(0), request, response, true);
        } catch (SocketException e) {
            if (log.isDebugEnabled()) {
                log.debug(e.getMessage(), e);
            }
        } catch (IOException e) {
            if (log.isErrorEnabled()) {
                log.error("IOException has occurred while downloading", e);
            }
        }
    }

    /**
     * uEU_E??[h?B
     * @param downloadObject _E??[h??B
     * @param request NGXg?B
     * @param response X|X?B
     *
     * @throws IOException _E??[h?oO????B
     */
    public static void download(AbstractDownloadObject downloadObject, HttpServletRequest request,
            HttpServletResponse response, boolean forceDownload) throws IOException {

        // downloadObjectnull???A??
        if (downloadObject == null) {
            if (log.isWarnEnabled()) {
                log.warn("No download object.");
            }
            return;
        }

        // wb_??B
        Map<String, List<String>> additionalHeaders = downloadObject.getAdditionalHeaders();

        // wb_?null???A??
        if (additionalHeaders == null) {
            if (log.isWarnEnabled()) {
                log.warn("Header must not be null.");
            }
            return;
        }

        // wb_??B
        Set<Entry<String, List<String>>> entrySet = additionalHeaders.entrySet();
        for (Entry<String, List<String>> entry : entrySet) {
            String headerName = entry.getKey();
            List<String> headerValues = entry.getValue();

            // wb_?L?[lXgnull???A??
            if (headerValues == null || headerName == null) {
                if (log.isWarnEnabled()) {
                    log.warn("Header name and value must not be null.");
                }
                return;
            }
            for (String headerValue : headerValues) {
                // wb_?lnull
                if (headerValue == null) {
                    headerValue = "";
                }
                response.addHeader(headerName, headerValue);
            }
        }

        // GR?[fBO?
        String charSet = downloadObject.getCharset();
        if (StringUtils.isNotEmpty(charSet)) {
            response.setCharacterEncoding(downloadObject.getCharset());
        }

        // Reg^Cv?
        String contentType = downloadObject.getContentType();
        if (StringUtils.isNotEmpty(contentType)) {
            response.setContentType(downloadObject.getContentType());
        }

        // f?[^TCY?
        int contentLength = downloadObject.getLengthOfData();
        if (contentLength > 0) {
            response.setContentLength(downloadObject.getLengthOfData());
        }

        // t@C????A??B
        // ?????B
        String name = downloadObject.getName();
        if (name != null) {
            name = encoder.encode(name, request, response);
        } else {
            name = encoder.encode("", request, response);
        }
        setFileName(response, name, forceDownload);

        InputStream inputStream = downloadObject.getStream();
        OutputStream outputStream = null;

        try {
            // _E??[h???s
            outputStream = response.getOutputStream();
            Streams.copy(inputStream, outputStream, false);
        } finally {
            if (inputStream != null) {
                inputStream.close();
            }
            if (outputStream != null) {
                outputStream.flush();
                outputStream.close();
            }
        }

    }

    /**
     * t@C?
     *
     * @param response X|X?B
     * @param name _E??[h?B
     * @param forceDownload ?_E??[h?B<code>true</code>???A??B
     */
    protected static void setFileName(HttpServletResponse response, String name, boolean forceDownload) {

        if (forceDownload) {
            // LbV?IE?
            String contentDispositionValue = "attachment;" + " filename=" + name;
            response.setHeader(HEADER_CONTENT_DISPOSITION, contentDispositionValue);
        } else {
            String contentDispositionValue = "inline; filename=" + name;
            response.setHeader(HEADER_CONTENT_DISPOSITION, contentDispositionValue);
        }
    }
}