• struts2 中 result type="stream"


    Stream result type是Struts2中比较有用的一个feature。特别是在动态生成图片和文档下载的情况下

    1:图片验证码:

    Action类,action主要要提供一个获取InputStrem的方法:

    public class CheckCodeAction extends ActionSupport implements SessionAware {
    private Logger log = LoggerFactory.getLogger(this.getClass());
    private InputStream imageStream;
    private Map session;

    public String getCheckCodeImage(String str, int show, ByteArrayOutputStream output) {
    Random random = new Random();
    BufferedImage image = new BufferedImage(80, 30, BufferedImage.TYPE_3BYTE_BGR);
    Font font = new Font("Arial", Font.PLAIN, 24);
    int distance = 18;
    Graphics d = image.getGraphics();
    d.setColor(Color.WHITE);
    d.fillRect(0, 0, image.getWidth(), image.getHeight());
    d.setColor(new Color(random.nextInt(100) + 100, random.nextInt(100) + 100, random.nextInt(100) + 100));
    for (int i = 0; i < 10; i++) {
    d.drawLine(random.nextInt(image.getWidth()), random.nextInt(image.getHeight()), random.nextInt(image.getWidth()),
    random.nextInt(image.getHeight()));
    }
    d.setColor(Color.BLACK);
    d.setFont(font);
    String checkCode = "";
    char tmp;
    int x = -distance;
    for (int i = 0; i < show; i++) {
    tmp = str.charAt(random.nextInt(str.length() - 1));
    checkCode = checkCode + tmp;
    x = x + distance;
    d.setColor(new Color(random.nextInt(100) + 50, random.nextInt(100) + 50, random.nextInt(100) + 50));
    d.drawString(tmp + "", x, random.nextInt(image.getHeight() - (font.getSize())) + (font.getSize()));
    }
    d.dispose();
    try {
    ImageIO.write(image, "jpg", output);
    } catch (IOException e) {
    log.warn("生成验证码错误.", e);
    }
    return checkCode;
    }

    public String execute() throws Exception {
    ByteArrayOutputStream output = new ByteArrayOutputStream();
    String checkCode = getCheckCodeImage("ABCDEFGHJKLMNPQRSTUVWXYZ123456789", 4, output);
    this.session.put(Constants.CHECK_CODE_KEY, checkCode);
    //这里将output stream转化为 inputstream
    this.imageStream = new ByteArrayInputStream(output.toByteArray());
    output.close();
    return SUCCESS;
    }

    public InputStream getImageStream() {
    return imageStream;
    }

    public void setSession(Map session) {
    this.session = session;
    }

    struts配置文件:

    <action name="checkCode" class="CheckCodeAction">
    <result name="success" type="stream">
    <param name="contentType">image/jpeg</param>
    <!-- 指定提供InputStream的filed name -->
    <param name="inputName">imageStream</param>
    <param name="bufferSize">1024</param>
    </result>
    <interceptor-ref name="defaultStack"/>
    </action>

    2:文件下载:

    我这里的应用是POI在内存中生成excel文件供客户端下载。struts.xml中的配置如下:

    <action name="jxcQuery_*" class="com.chengzhong.action.JxcChaXunAction" method="{1}">
    <result name="success">jxcchaxun.jsp</result>
    <!--进销存信息导出为excel -->
    <result name="toexcelOK" type="stream">
    <param name="contentType">application/vnd.ms-excel</param>
    <param name="contentDisposition">attachment;filename="${fileName}"</param>
    <param name="inputName">excelIS</param>
    </result>
    <result name="error">../404.htm</result>
    </action>

    1.type="stream"           把一般内容输出到流

    2.参数contentType的地方指定为application/vnd.ms-excel
    3.设置为 attachment 将会告诉浏览器下载该文件,filename 指定下载文件保有存时的文件名,若未指定将会是以浏览的页面名作为文件名,如以 download.action 作为文件名。这里使用的是动态文件名,${fileName}。它将通过 Action 的 getFileName() 获得文件名。也就是说Action里面要有一个getFileName ()的方法。

    public String getFileName() {
    String fileName = "进销存信息统计表.xls"
    try {
    //中文文件名需要转码为 ISO8859-1,否则乱码
    return new String(fileName.getBytes(), "ISO8859-1");
    } catch (UnsupportedEncodingException e) {
    return "jxc.xls";
    }
    }

    或者Action 里面有一个fileName的属性,提供它的set 和get 方法。在程序合适的位置给fileName赋值。这两者本质上应该是一样的。
    我刚开始没有用注释处的方法转码,用中文做文件名的时候,它就象前面说的用浏览的页面名作为文件名了。

    4.<param name="inputName">excelIS</param>
         参数inputName指定输入流的名称。和前面的文件名一样,Action里或者提供一个getExcelIS()的方法,或者提供excelIS属性。

    5.对流的操作:

    ByteArrayOutputStream baos = new ByteArrayOutputStream();
      try {
       
       /************************************************************/ 
        DataImportAndExportTool.InfoToExcel(Info, sheetName).write(baos);
        byte[] ba = baos.toByteArray(); 
        baos.close(); 
        excelIS = new ByteArrayInputStream(ba);       
       /*******************************************************************/
       //DataImportAndExportTool.InfoToExcel(Info, sheetName).write(fOut);     //这样excel表保存在了服务器上
       
      } catch (Exception e) {
       
       e.printStackTrace();
      }
        
       return "toexcelOK";、

    DataImportAndExportTool.InfoToExcel(Info, sheetName)是我生成excel的方法,info是一个list,sheetName 是工作薄名,这句执行后生成了一个workbook。

    ByteArrayOutputStream类是在创建它的实例时,程序内部创建一个byte型别数组的缓冲区,然后利用ByteArrayOutputStream和ByteArrayInputStream的实例向数组中写入或读出byte型数据。在网络传输中我们往往要传输很多变量,我们可以利用ByteArrayOutputStream把所有的变量收集到一起,然后一次性把数据发送出去。

    ByteArrayOutputStream用途很多。其中缓冲是一个。对象的深浅复制也会用到

    注意:以下是一些参数说明

    contentType

    内容类型,和互联网MIME标准中的规定类型一致,例如text/plain代表纯文本,text/xml表示XML,image/gif代表GIF图片,image/jpeg代表JPG图片

    inputName

    下载文件的来源流,对应着action类中某个类型为Inputstream的属性名,例如取值为inputStream的属性需要编写getInputStream()方法

    contentDisposition

    文件下载的处理方式,包括内联(inline)和附件(attachment)两种方式,而附件方式会弹出文件保存对话框,否则浏览器会尝试直接显示文件。取值为:

    attachment;filename="struts2.txt",表示文件下载的时候保存的名字应为struts2.txt。如果直接写filename="struts2.txt",那么默认情况是代表inline,浏览器会尝试自动打开它,等价于这样的写法:inline; filename="struts2.txt"

    bufferSize

    下载缓冲区的大小

    。在这里面,contentType属性和contentDisposition分别对应着HTTP响应中的头Content-TypeContent-disposition头。

  • 相关阅读:
    Python流程控制
    Python中的条件判断
    控制台出现“The script has an unsupported MIME type ('text/html')”报错
    React项目中使用hot-react-loader
    React组件绑定this的三种方法
    egg.js异步请求数据
    Zepto源码分析之二(新旧版本zepto.Z方法的区别)
    Zepto源码分析之一(代码结构及初始化)
    构建RN或Weex项目时,使用Android Studio常遇到的问题
    CentOS安装PHP7.*
  • 原文地址:https://www.cnblogs.com/sdream/p/5335885.html
Copyright © 2020-2023  润新知