当前位置: 首页 > news >正文

JFinal输出流的Render

2019独角兽企业重金招聘Python工程师标准>>> hot3.png

需要输出excel文件,默认只有File的方式。 自己改了个可以输出ByteArrayOutputStream的。

package com.jbns.huaxin.jfinal.util;

import com.jfinal.kit.StrKit;
import com.jfinal.render.Render;
import com.jfinal.render.RenderException;
import org.apache.commons.lang.StringUtils;

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

/**
 * Created by AaronHe on 2016/12/5.
 */
public class StreamRender extends Render {
    private static final String DEFAULT_CONTENT_TYPE = "application/octet-stream";

    private String                fileName;
    private ByteArrayOutputStream os;

    public StreamRender(String fileName, ByteArrayOutputStream outputStream) {
        if (StringUtils.isBlank(fileName) || outputStream == null)
            throw new IllegalArgumentException("file name and output stream cannot be null");

        this.fileName = fileName;
        this.os = outputStream;
    }


    @Override
    public void render() {
        ServletContext servletContext = request.getSession().getServletContext();
        response.setHeader("Accept-Ranges", "bytes");
        response.setHeader("Content-disposition", "attachment; filename=" + encodeFileName(fileName));
        String contentType = servletContext.getMimeType(fileName);
        response.setContentType(contentType != null ? contentType : DEFAULT_CONTENT_TYPE);

        if (StrKit.isBlank(request.getHeader("Range")))
            normalRender();
        else
            rangeRender();
    }

    private String encodeFileName(String fileName) {
        try {
            return new String(fileName.getBytes("GBK"), "ISO8859-1");
        } catch (UnsupportedEncodingException e) {
            return fileName;
        }
    }

    private void normalRender() {
        response.setHeader("Content-Length", String.valueOf(os.size()));
        InputStream  inputStream  = null;
        OutputStream outputStream = null;
        try {
            inputStream = new BufferedInputStream(new ByteArrayInputStream(os.toByteArray()));
            outputStream = response.getOutputStream();
            byte[] buffer = new byte[1024];
            for (int len = -1; (len = inputStream.read(buffer)) != -1;) {
                outputStream.write(buffer, 0, len);
            }
            outputStream.flush();
        }
        catch (IOException e) {
            if (getDevMode())	throw new RenderException(e);
        }
        catch (Exception e) {
            throw new RenderException(e);
        }
        finally {
            if (inputStream != null)
                try {inputStream.close();} catch (IOException e) {}
            if (outputStream != null)
                try {outputStream.close();} catch (IOException e) {}
        }
    }

    private void rangeRender() {
        Long[] range = {null, null};
        processRange(range);

        String contentLength = String.valueOf(range[1].longValue() - range[0].longValue() + 1);
        response.setHeader("Content-Length", contentLength);
        response.setStatus(HttpServletResponse.SC_PARTIAL_CONTENT);	// status = 206

        // Content-Range: bytes 0-499/10000
        StringBuilder contentRange = new StringBuilder("bytes ").append(String.valueOf(range[0])).append("-").append(String.valueOf(range[1])).append("/").append(String.valueOf(os.size()));
        response.setHeader("Content-Range", contentRange.toString());

        InputStream inputStream = null;
        OutputStream outputStream = null;
        try {
            long start = range[0];
            long end = range[1];
            inputStream = new BufferedInputStream(new ByteArrayInputStream(os.toByteArray()));
            if (inputStream.skip(start) != start)
                throw new RuntimeException("File skip error");
            outputStream = response.getOutputStream();
            byte[] buffer = new byte[1024];
            long position = start;
            for (int len; position <= end && (len = inputStream.read(buffer)) != -1;) {
                if (position + len <= end) {
                    outputStream.write(buffer, 0, len);
                    position += len;
                }
                else {
                    for (int i=0; i<len && position <= end; i++) {
                        outputStream.write(buffer[i]);
                        position++;
                    }
                }
            }
            outputStream.flush();
        }
        catch (IOException e) {
            if (getDevMode())	throw new RenderException(e);
        }
        catch (Exception e) {
            throw new RenderException(e);
        }
        finally {
            if (inputStream != null)
                try {inputStream.close();} catch (IOException e) {}
            if (outputStream != null)
                try {outputStream.close();} catch (IOException e) {}
        }
    }

    /**
     * Examples of byte-ranges-specifier values (assuming an entity-body of length 10000):
     * The first 500 bytes (byte offsets 0-499, inclusive): bytes=0-499
     * The second 500 bytes (byte offsets 500-999, inclusive): bytes=500-999
     * The final 500 bytes (byte offsets 9500-9999, inclusive): bytes=-500
     * 															Or bytes=9500-
     */
    private void processRange(Long[] range) {
        String rangeStr = request.getHeader("Range");
        int index = rangeStr.indexOf(',');
        if (index != -1)
            rangeStr = rangeStr.substring(0, index);
        rangeStr = rangeStr.replace("bytes=", "");

        String[] arr = rangeStr.split("-", 2);
        if (arr.length < 2)
            throw new RuntimeException("Range error");

        long fileLength = os.size();
        for (int i=0; i<range.length; i++) {
            if (StrKit.notBlank(arr[i])) {
                range[i] = Long.parseLong(arr[i].trim());
                if (range[i] >= fileLength)
                    range[i] = fileLength - 1;
            }
        }

        // Range format like: 9500-
        if (range[0] != null && range[1] == null) {
            range[1] = fileLength - 1;
        }
        // Range format like: -500
        else if (range[0] == null && range[1] != null) {
            range[0] = fileLength - range[1];
            range[1] = fileLength - 1;
        }

        // check final range
        if (range[0] == null || range[1] == null || range[0].longValue() > range[1].longValue())
            throw new RuntimeException("Range error");
    }
}

使用方法

//in jfinal controller method
HSSFWorkbook wb       = new HSSFWorkbook();
//...
String fileName = "filename.xls";
ByteArrayOutputStream os = new ByteArrayOutputStream();
wb.write(os);
render(new StreamRender(fileName, os));

转载于:https://my.oschina.net/u/2006445/blog/800896

相关文章:

  • 剑指offer五:
  • Android开发环境
  • 移动端解决方案学习记录
  • 条件编译使用实例
  • sql server中分布式查询随笔(链接服务器(sp_addlinkedserver)和远程登录映射(sp_addlinkedsrvlogin)使用小总结)...
  • 架构设计从这5点考虑,能帮后期运维很大忙!
  • 安装最小化Linux,配置桌面
  • CentOS利用nginx和php-fpm搭建owncloud私有云
  • 【linux基础】17、网络属性配置详解
  • input type=file id=camera multiple=multiple capture=camera accept=image/* 上传图片,手机调用相册和摄像...
  • python面试大全
  • 最基本的操作
  • 【基础】MVC路由规则
  • 如何让vim自动显示函数声明-使用 echofunc.vim插件
  • Mysql 修改数据库,mysql修改表类型,Mysql增加表字段,Mysql删除表字段,Mysql修改字段名,Mysql修改字段排列顺序,Mysql修改表名...
  • [译] React v16.8: 含有Hooks的版本
  • C++入门教程(10):for 语句
  • CentOS6 编译安装 redis-3.2.3
  • CSS魔法堂:Absolute Positioning就这个样
  • ES学习笔记(12)--Symbol
  • Git同步原始仓库到Fork仓库中
  • JAVA SE 6 GC调优笔记
  • JAVA 学习IO流
  • js中forEach回调同异步问题
  • Redis 中的布隆过滤器
  • Ruby 2.x 源代码分析:扩展 概述
  • SpringCloud(第 039 篇)链接Mysql数据库,通过JpaRepository编写数据库访问
  • v-if和v-for连用出现的问题
  • 分布式任务队列Celery
  • 给第三方使用接口的 URL 签名实现
  • 聚类分析——Kmeans
  • 两列自适应布局方案整理
  • 目录与文件属性:编写ls
  • 判断客户端类型,Android,iOS,PC
  • 微信如何实现自动跳转到用其他浏览器打开指定页面下载APP
  • 写给高年级小学生看的《Bash 指南》
  • JavaScript 新语法详解:Class 的私有属性与私有方法 ...
  • SAP CRM里Lead通过工作流自动创建Opportunity的原理讲解 ...
  • 阿里云ACE认证之理解CDN技术
  • ​2021半年盘点,不想你错过的重磅新书
  • #pragma once
  • (超详细)2-YOLOV5改进-添加SimAM注意力机制
  • (附源码)node.js知识分享网站 毕业设计 202038
  • (附源码)springboot金融新闻信息服务系统 毕业设计651450
  • (附源码)ssm户外用品商城 毕业设计 112346
  • (黑马出品_高级篇_01)SpringCloud+RabbitMQ+Docker+Redis+搜索+分布式
  • (机器学习的矩阵)(向量、矩阵与多元线性回归)
  • (十二)springboot实战——SSE服务推送事件案例实现
  • (十三)Flask之特殊装饰器详解
  • (十五)Flask覆写wsgi_app函数实现自定义中间件
  • (原创)boost.property_tree解析xml的帮助类以及中文解析问题的解决
  • (转)http协议
  • (转)iOS字体
  • (转)scrum常见工具列表
  • ... fatal error LINK1120:1个无法解析的外部命令 的解决办法