适应浏览器自带断点下载

源码:http://download.csdn.net/download/u013160017/9996400
package com.goldmsg.download.controller;

import com.goldmsg.download.base.ReturnInfo;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.*;

/**
 * Created by zhouhaiming on 2017-9-26 11:57
 * Email: dg_chow@163.com
 *
 * @Description:
 */
@Controller
@RequestMapping("/")
public class Download {
    private final Logger logger = LoggerFactory.getLogger(this.getClass());

    @RequestMapping("/hello")
    String home() {
        return "Hello World!";
    }

    @RequestMapping("/download")
    public Object downloadFileByPath(HttpServletRequest request, HttpServletResponse response) {
        try {
            downloadFile("E:\\共享文件夹\\Oracle 10g_x64_setup.zip", request, response);
        } catch (UnsupportedEncodingException e) {
            e.printStackTrace();
        }
        return ReturnInfo.genSucceedEvent("测试成功!");
    }

    /**
     * 执行下载动作
     *
     * @param srcFileName 绝对路径,指向服务器上某个已存在的文件
     * @return
     * @throws UnsupportedEncodingException
     */
    private Object downloadFile(String srcFileName, HttpServletRequest request, HttpServletResponse response) throws UnsupportedEncodingException {
        String filepath = srcFileName;
        FileInputStream inputFileStream = null;
        OutputStream outputStream = null;
        try {
            File file = new File(filepath);
            if (file.exists()) {
                long point = 0;
                long fileLength = file.length();
                long position_end = fileLength;

                inputFileStream = new FileInputStream(file);
                outputStream = response.getOutputStream();
                response.reset();

                //设置支持断点
                response.setHeader("Accept-Ranges", "bytes");
                //获取断点位置
                String Range = request.getHeader("Range");
                if (Range != null) {
                    response.setStatus(javax.servlet.http.HttpServletResponse.SC_PARTIAL_CONTENT);
                    String RangeFromTo = Range.replaceAll("bytes=", "");
                    logger.info("threadName: " + Thread.currentThread().getId() + " Range : " + RangeFromTo);

                    String[] Ranges = RangeFromTo.split("-");
                    point = Long.parseLong(Ranges[0]);

                    if (Ranges.length == 2 && !Ranges[1].equals("")) {
                        position_end = Long.parseLong(Ranges[1]);
                    }
                }

                //写明要下载的文件的大小
                response.setHeader("Content-Length", new Long(position_end - point).toString());
                logger.info("threadName: " + Thread.currentThread().getId() + "point : " + point + " Content-Length : " + new Long(position_end - point).toString());

                //设置response的编码方式
                response.setContentType("application/x-msdownload");

                //设置断点续传回应头
                String contentRange = new StringBuffer("bytes ")
                        .append(new Long(point).toString())
                        .append("-")
                        .append(new Long(fileLength - 1).toString())
                        .append("/")
                        .append(new Long(fileLength).toString())
                        .toString();

                if (point != 0) {
                    // 断点续传的回应头:告诉改块插入的位置和文件的总大小
                    // 格式:Content-Range: bytes [文件块的开始字节]-[文件块的结束字节 - 1]/[文件的总大小]
                    contentRange = new StringBuffer("bytes ")
                            .append(new Long(point).toString())
                            .append("-")
                            .append(new Long(position_end - 1).toString())//
                            .append("/")
                            .append(new Long(fileLength).toString())
                            .toString();
                    // 移动文件指针位置,断点处
                    inputFileStream.skip(point);
                }
                response.setHeader("Content-Range", contentRange);

                //设置附加文件名(解决中文乱码)
                String downloadname = file.getName();
                response.setHeader("Content-Disposition", "attachment;filename=" + new String(downloadname.getBytes("gbk"), "iso-8859-1"));

                long bytesWritten = 0;
                byte[] bytes = new byte[1024 * 4];
                int byteCount = 0;

                long NeedWriten = position_end - point + 1;

                while (NeedWriten >= bytesWritten && (byteCount = inputFileStream.read(bytes)) != -1) {
                    if (NeedWriten >= bytesWritten) {
                        long tTempWriten = (bytesWritten + byteCount) > NeedWriten ? (NeedWriten - bytesWritten) : byteCount;
                        outputStream.write(bytes, 0, (int) tTempWriten);
                        bytesWritten += tTempWriten;
                    }
                }
            } else {
                logger.error("下载文件失败:" + filepath + " and authcode: 文件不存在");
                setHttpResposeCode(response, response.SC_NOT_FOUND, "download file failed :" + filepath + " : file not exist");
                return ReturnInfo.genFileNotExistError(srcFileName);
            }

        } catch (FileNotFoundException e) {
            logger.error("下载文件失败:" + filepath + " FileNotFoundException happen : " + e + " URL : " + request.getRequestURL().toString());
            setHttpResposeCode(response, response.SC_NOT_FOUND, "download file failed FileNotFoundException happen : " + e + " filepath :" + filepath + " : file not exist");
            return ReturnInfo.genFileNotExistError(srcFileName);
        } catch (IOException e) {
            logger.error("下载文件失败:" + filepath + " IOException hapepn : " + e + " URL : " + request.getRequestURL().toString());
            setHttpResposeCode(response, response.SC_INTERNAL_SERVER_ERROR, "download file failed IOException happen : " + e);
            return ReturnInfo.genInternalsErrorEvent("下载失败");
        } finally {
            try {
                if (null != inputFileStream) {
                    inputFileStream.close();
                }
                if (null != outputStream) {
                    outputStream.close();
                }
            } catch (IOException e) {
                logger.error("下载文件失败:" + filepath + " EofException happen : " + e);
            }
        }
        logger.info("下载文件成功:" + filepath);
        return ReturnInfo.genSucceedEvent("正在下载");
    }

    /**
     * 设置http  返回码
     *
     * @param code
     * @param msg
     **/
    private void setHttpResposeCode(HttpServletResponse response, int code, String msg) {
        try {
            response.reset();
            response.setCharacterEncoding("UTF-8");               //设置字符编码格式
            response.setContentType("text/html; charset=UTF-8"); //设置输出编码格式
            response.sendError(code, new String(msg.getBytes(), "UTF-8"));
        } catch (IOException e) {
            e.printStackTrace();
            logger.error("FileDownLoad setHttpResposeCode IOException happen : " + e);
        }
    }

}







package com.goldmsg.download.base;

/**
 * Created by zhouhaiming on 2017-9-26 15:50
 * Email: dg_chow@163.com
 *
 * @Description:
 */

import java.util.HashMap;
import java.util.Map;

public class ReturnInfo {


    public static Map genFileNotExistError(Object msg){
        Map map = new HashMap();
        map.put("error", 3003);
        map.put("msg", msg + "资源不存在");
        return map;
    }

    public static Map genInternalsErrorEvent(String msg){
        Map map = new HashMap();
        map.put("error", 3004);
        map.put("msg", msg);
        return map;
    }

    public static Map genSucceedEvent(Object msg){
        Map map = new HashMap();
        map.put("error", 0);
        map.put("msg", msg);
        return map;
    }
}

 

如果您喜欢这篇文章请在下面点个赞和收藏。谢谢您的支持!

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值