用于文件下载的Servlet

    今天在处理jar下载被IE自动将后缀修改为zip的时候,写了这么一个servlet;后面才发现原来是jboss中的mime.types中少了jar的配置,走了一大段弯路;这个Servlet在mime.types中即使没有配置的类型,大部份的浏览器都可以支持正常下载的,我的测试过程中使用七个浏览器,只有Opera在下载jar的时候会将其后缀恐怖的修改为exe。要使用这个Servlet,需要做的辅助工作就是要在web.xml中配置它,包括Servlet及servlet-mapping的配置,可参考以下内容:

   

<servlet>  
    <servlet-name>downloadServer</servlet-name>  
    <servlet-class>***.DownloadServlet</servlet-class>  
</servlet>  
<servlet-mapping>  
    <servlet-name>downloadServer</servlet-name>  
    <url-pattern>/download_center.do</url-pattern>  
</servlet-mapping>  

 

,下载文件的时候,将链接使用如下形式:

http://****.com/download_center.do?file=myfile.jar

 

,就可以调用该DownloadServlet进行文件的下载了,详细的可以参考一下网络上其它的资料,以下是DownloadServlet.java的完整源码:

/**
 * 类DownloadServlet.java的实现描述:TODO 类实现描述 文件下载Servlet
 * 
 * @author root 2010-7-28 上午11:25:58
 */
/**
 * 
 */

import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;

import javax.servlet.ServletConfig;
import javax.servlet.ServletException;
import javax.servlet.ServletOutputStream;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;

public class DownloadServlet extends HttpServlet {

    private static final long  serialVersionUID = 8228591081694973459L;
    protected final static Log logger           = LogFactory.getLog(DownloadServlet.class);

    /*
     * (non-Javadoc)
     * @see javax.servlet.http.HttpServlet#doGet(javax.servlet.http.HttpServletRequest,
     * javax.servlet.http.HttpServletResponse)
     */
    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        File path = new File("");
        String file = request.getParameter("file");// 通过该参数传入文件名
        if (!fileSafeCheck(file)) {
            StringBuilder sb = new StringBuilder("filename:").append(file).append(" is invalid");
            if (logger.isDebugEnabled()) {
                logger.debug(sb.toString());
            }
            response.setCharacterEncoding("gbk");
            response.setContentLength(sb.length());
            response.getWriter().write(sb.toString());
        }
        // 以下是文件名的完整路径,具体根据情况需要自己在这里处理一下了
        String filePath = path.getAbsoluteFile().getParent() + file;
        if (logger.isDebugEnabled()) {
            StringBuilder sb = new StringBuilder("filename:").append(file).append(",file absolute path:").append(
                                                                                                                 filePath);
            logger.debug(sb.toString());
        }
        if (filePath != null && filePath.length() > 0) {
            try {
                downloadFile(response, filePath);
            } catch (Exception e) {
                StringBuilder sb = new StringBuilder("download file exception,filename:").append(file).append(
                                                                                                              ",file absolute path:").append(
                                                                                                                                             filePath);
                logger.error(sb.toString(), e);
                sb.delete(0, sb.length());
                // sb.append("<script language=\"javascript\">alert('文件下载异常,请确定文件名是否正确.');</script>");
                sb.append("<script language=\"javascript\">alert('download file err.');</script>");
                response.setCharacterEncoding("gbk");
                response.setContentLength(sb.length());
                response.getWriter().write(sb.toString());
            }
        }
    }

    /*
     * (non-Javadoc)
     * @see javax.servlet.http.HttpServlet#doPost(javax.servlet.http.HttpServletRequest,
     * javax.servlet.http.HttpServletResponse)
     */
    protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException,
                                                                                   IOException {
        doGet(request, response);
    }

    /*
     * (non-Javadoc)
     * @see javax.servlet.GenericServlet#init(javax.servlet.ServletConfig)
     */
    public void init(ServletConfig conf) throws ServletException {
        // TODO Auto-generated method stub
        super.init(conf);
    }

    /**
     * 下载文件
     * 
     * @param response
     * @param filePath
     * @throws RuntimeException
     * @throws IOException
     */
    private void downloadFile(HttpServletResponse response, String filePath) throws RuntimeException, IOException {
        File file = new File(filePath);
        if (!file.exists() || !file.canRead()) {
            throw new RuntimeException("File not exists or can not be read!");
        }
        FileInputStream fileinputstream = new FileInputStream(file);
        String filename = getFileName(filePath);
        downloadFile(fileinputstream, null, filename, 2048, response);
        fileinputstream.close();
        fileinputstream = null;
        file = null;
    }

    /**
     * 下载文件
     * 
     * @param filedata 下载数据流
     * @param contentType 文件类型
     * @param filename (下载后的)文件名称
     * @param buffersize 缓冲区大小
     * @param m_response
     * @throws IOException
     * @throws BimisException
     */
    private void downloadFile(InputStream filedata, String contentType, String filename, int buffersize,
                              HttpServletResponse m_response) throws IOException, RuntimeException {
        if (filedata == null) {
            return;
        }
        if (buffersize <= 0) {
            buffersize = 2048;
        }
        long contentLengh = filedata.available();
        if (contentType == null || contentType.length() == 0) {
            m_response.setContentType("application/x-msdownload");
        }
        else {
            m_response.setContentType(contentType);
        }
        if (contentLengh > 0) {
            m_response.setContentLength((int) contentLengh);
        }
        String m_contentDisposition = "attachment;";
        if (filename == null || filename.length() == 0) {
            m_response.setHeader("Content-Disposition",m_contentDisposition);
        }
        else {
            m_response.setHeader("Content-Disposition", m_contentDisposition + " filename=" + toUtf8String(filename));
        }
        ServletOutputStream rspout = m_response.getOutputStream();
        copyStream(filedata, rspout, buffersize, true);
    }

    /**
     * 将文件名中的汉字转为UTF8编码的串,以便下载时能正确显示另存的文件名.
     * 
     * @param s 原文件名
     * @return 重新编码后的文件名
     */
    private String toUtf8String(String s) {
        StringBuffer sb = new StringBuffer();
        for (int i = 0; i < s.length(); i++) {
            char c = s.charAt(i);
            if (c >= 0 && c <= 255) {
                sb.append(c);
            } else {
                byte[] b;
                try {
                    b = Character.toString(c).getBytes("utf-8");
                } catch (Exception ex) {
                    b = new byte[0];
                }
                for (int j = 0; j < b.length; j++) {
                    int k = b[j];
                    if (k < 0) k += 256;
                    sb.append("%" + Integer.toHexString(k).toUpperCase());
                }
            }
        }
        return sb.toString();
    }

    private final long copyStream(InputStream source, OutputStream dest, int bufferSize, boolean flush)
                                                                                                       throws RuntimeException {
        int bytes;
        long total;
        byte[] buffer;
        buffer = new byte[bufferSize];
        total = 0;
        try {
            while ((bytes = source.read(buffer)) != -1) {
                // Technically, some read(byte[]) methods may return 0 and we
                // cannot
                // accept that as an indication of EOF.
                if (bytes == 0) {
                    bytes = source.read();
                    if (bytes < 0) break;
                    dest.write(bytes);
                    if (flush) dest.flush();
                    ++total;
                    continue;
                }
                dest.write(buffer, 0, bytes);
                if (flush) dest.flush();
                total += bytes;
            }
        } catch (IOException e) {
            throw new RuntimeException("IOException caught while copying.", e);
        }
        return total;
    }

    /**
     * 根据传入的路径,获取文件的名称
     * 
     * @param fullFilePath
     * @return
     */
    private String getFileName(String fullFilePath) {
        if (fullFilePath == null) {
            return "";
        }
        int index1 = fullFilePath.lastIndexOf('/');
        int index2 = fullFilePath.lastIndexOf('\\');

        // index is the maximum value of index1 and index2
        int index = (index1 > index2) ? index1 : index2;
        if (index == -1) {
            // not found the path separator
            return fullFilePath;
        }
        String fileName = fullFilePath.substring(index + 1);
        return fileName;
    }

    /**
     * 文件名的安全检查,以免被人通过"../../../"的方式获取其它文件
     * 
     * @param filename
     * @return
     */
    private boolean fileSafeCheck(String filename) {
        if (filename.indexOf("../") >= 0) {
            return false;
        }
        return true;
    }
}

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值