文件的下载

文件下载有以下两种实现方法:

   * 通过超链接实现下载:实现简单,但暴露了下载文件的真实位置,并只能下载 Web 应用程序所在目录下的文件,WEB-INF 目录除外。

   * 利用程序编码实现下载:增强安全访问控制,可以下载除 Web 应用程序所在目录以外的文件,也可以将文件保存到数据库中。

利用程序编码实现下载需要设置以下两个报头:

    1. Web 服务器需要告诉浏览器其所输出内容的类型不是普通文本文件或 HTML 文件,而是一个要保存到本地的下载文件,这需要设置 Content-Type 的值为application/x-msdownload。

    2. Web 服务器希望浏览器不直接处理相应的实体内容,而是由用户选择将相应的实体内容保存到一个文件中,这需要设置 Content-Disposition报头。

    该报头指定了接收程序处理数据内容的方式,在 HTTP 应用中只有 attachment 是标准方式,attachment 表示要求用户干预。

    在 attachment 后面还可以指定 filename 参数,该参数是服务器建议浏览器将实体内容保存到文件中的文件名称。

设置报头的示例如下:

response.setHeader("Content-Type", "application/x-msdownload");
response.setHeader("Content-Disposition", "attachment;filename="+filename);

代码实现步骤:

1.获取可下载的文件页面:

    后台代码实现:

//显示要下载的文件
    @RequestMapping("/showdownFiles")
    public String show(HttpServletRequest request, Model model) {
//        String path = request.getServletContext()
//                .getRealPath("/photos");
        String path="D:/uo";
        //当前路径下文件
        File download = new File(path);
        //文件下属文件组成一个数组
        File[] files = download.listFiles();
        //获取目录下的所有文件名
        ArrayList<String> fileName = new ArrayList<>();
        for (int i = 0; i < files.length; i++) {
            fileName.add(files[i].getName());
        }
        model.addAttribute("files", fileName);
        return "showdownFiles";
    }

    jsp实现页面:

<table>
    <tr>
        <td>被下载的文件名</td>
    </tr>
    <!--遍历 model中的 files-->
    <c:forEach items="${files}" var="filename">
        <tr>
            <td>
                <a href="${pageContext.request.contextPath }/download/${filename}">${filename}</a>
<%--        <a href="${pageContext.request.contextPath }/down?filename=${filename}">${filename}</a>--%>
            </td>
        </tr>
    </c:forEach>
</table>

进行下载操作:

    方法一:


下载
@GetMapping("/download/{filename}")
public ResponseEntity<byte[]> down(@PathVariable() String filename,HttpSession session)throws  Exception{
    String path =   session.getServletContext().getRealPath("/photos");
    InputStream inputStream = new FileInputStream(new File(path+"/"+filename));
    byte[] bs = new byte[inputStream.available()];
    //写入文件
    inputStream.read(bs);
    //设置表头:
    MultiValueMap<String,String> headers = new HttpHeaders();
    headers.add("Content-Disposition","attachment ; filename="+new String(filename.getBytes("UTF-8"),"ISO-8859-1"));
    ResponseEntity<byte[]> entity = new ResponseEntity<byte[]>(bs,headers, HttpStatus.OK);
    return  entity;
}

 方法二:

@RequestMapping("/download/{filename}")
    /*路径里加的变量需要加@PathVariable
    如果是/down?filename=${filename},则需要配置@RequestParam
     */


    public String down(@PathVariable  String filename,
                       HttpServletRequest request, HttpServletResponse response) {
        String aFilePath = null; // 要下载的文件路径
        FileInputStream in = null; // 输入流
        ServletOutputStream out = null; // 输出流
        try {
            // 从workspace\.metadata\.plugins\org.eclipse.wst.server.core\
            // tmp0\wtpwebapps下载
//            aFilePath = request.getServletContext().getRealPath("uploadfiles");
            aFilePath="D:/uo";
            // 设置下载文件使用的报头
            response.setHeader("Content-Type", "application/x-msdownload");
            response.setHeader("Content-Disposition", "attachment; filename="
                    + toUTF8String(filename));
            // 读入文件
            in = new FileInputStream(aFilePath + "\\" + filename);
            // 得到响应对象的输出流,用于向客户端输出二进制数据
            out = response.getOutputStream();
            out.flush();
            int aRead = 0;
            byte b[] = new byte[1024];
            while ((aRead = in.read(b)) != -1 & in != null) {
                out.write(b, 0, aRead);
            }
            out.flush();
            in.close();
            out.close();
        } catch (Throwable e) {
            e.printStackTrace();
        }
        logger.info("下载成功");
        return null;
    }
    /**
     * 下载保存时中文文件名的字符编码转换方法
     */
    public String toUTF8String(String str) {
        StringBuffer sb = new StringBuffer();
        int len = str.length();
        for (int i = 0; i < len; i++) {
            // 取出字符中的每个字符
            char c = str.charAt(i);
            // Unicode码值为0~255时,不做处理
            if (c >= 0 && c <= 255) {
                sb.append(c);
            } else { // 转换 UTF-8 编码
                byte b[];
                try {
                    b = Character.toString(c).getBytes("UTF-8");
                } catch (UnsupportedEncodingException e) {
                    e.printStackTrace();
                    b = null;
                }
                // 转换为%HH的字符串形式
                for (int j = 0; j < b.length; j++) {
                    int k = b[j];
                    if (k < 0) {
                        k &= 255;
                    }
                    sb.append("%" + Integer.toHexString(k).toUpperCase());
                }
            }
        }
        return sb.toString();
    }

  • 2
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值