前言

博主正在参加CSDN2013年度博客之星评选,如果这篇文章对您有用,请投他一票:

投票地址:http://vote.blog.csdn.net/blogstaritem/blogstar2013/oscar999

不胜感激^^

[Web Chart系列之六] canvas Chart 导出图文件

Chart 导出的原理很基本方法,在上一篇已经有介绍过。

对于Extjs 来说,在 Ext.chart.Chart 这个类直接有提供一个 save( [config] ) 的方法, 调用这个方法, 就可以在browser 下载当前这个chart 的对应格式的图形文件。

chart.save({
type: 'image/png'
});

这里使用的技术是把数据传递到服务器端, 由服务器端产生图再传到前端。

所以, 在调用save 这个方法的时候, 你会发现, 请求会访问http://svg.sencha.io/ 这个地址。

曾经, 大概在 2013 的年中的时候, 这个地址都可以访问, 当时不知何时, 这个地址的访问就会报 503 (Service Unavailable)的错误了。

aaarticlea/png;base64,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" alt="" />

这样的话, 原本可以work 的chart 导出功能, 现在就不行了。

网上搜索一下, 是说部分版本已经不提供这个服务了。

不管如何, 讲自己的服务放在别的地方, 总也不踏实, 是否可以开发出这种服务呢?

原理

首先看一看, chart.save 时,前端传递了那些参数:

aaarticlea/png;base64,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" alt="" />

参数有四个:

width 和 height 应该是图片的大小

type 应该是图的保存格式

svg  传递的就是xml方式的svg 格式的数据。

所以问题归结为一点: 在服务端如何解析这个svg 格式的数据并生成图片文件?

解决方法

看懂这些svg 数据, 并使用基本API生成一个图片不失为一种解法?

但是对java 语言来说, 是否已经存在第三方包来帮我们直接做这种事呢?

答案之一就是:

Batik

Batik是使用
svg格式图片来实现各种功能的应用程序以及Applet提供的一个基于java的工具包。

它是属于 Apache软件基金会 的一个项目, 应该是值得信赖的。

项目主页:  http://xmlgraphics.apache.org/batik/

下载地址:http://mirrors.cnnic.cn/apache/xmlgraphics/batik/

开发步骤:

1. 下载batik-1.7.zip ( 目前的最新版) 并解压

2. 把根目录, lib 和 extensions 目录下的所有lib 包拷入项目的web lib 中。(可以选择)

3. 写一个servlet   ImageExportService.java

/**
* author:oscar999
*/
import java.io.IOException;
import java.io.OutputStream;
import java.io.StringReader; import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse; import org.apache.batik.transcoder.TranscoderException;
import org.apache.batik.transcoder.TranscoderInput;
import org.apache.batik.transcoder.TranscoderOutput;
import org.apache.batik.transcoder.image.JPEGTranscoder;
import org.apache.batik.transcoder.image.PNGTranscoder; public class ImageExportService extends HttpServlet { /**
*
*/
private static final long serialVersionUID = 1L; /**
* Post File to Client
* Input Parameters:
* type(image type, as png, jpeg),
* svg(svg string, post by extjs),
* filename(save file name)
*/
@Override
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException,
IOException { String type = request.getParameter("type");
String svg = request.getParameter("svg");
String filename = "chart";
if( request.getParameter("filename")!=null&&request.getParameter("filename").length()>0)
{
filename = request.getParameter("filename");
} String postfix;
if ("image/jpeg".equals(type)) {
response.setContentType("image/jpeg");
postfix = "jpg";
} else {
response.setContentType("image/png");
postfix = "png";
}
response.setHeader("Content-Disposition", "attachment; filename=" + filename + "." + postfix); StringReader stringReader = new StringReader(svg);
OutputStream out = response.getOutputStream(); try {
TranscoderInput input = new TranscoderInput(stringReader);
TranscoderOutput output = new TranscoderOutput(out); if ("image/jpeg".equals(type)) {
new JPEGTranscoder().transcode(input, output);
} else {
new PNGTranscoder().transcode(input, output);
} } catch (TranscoderException e) {
throw new ServletException(e);
}
} }

4.  在 web.xml 中配置此servlet 的请求路径

  <servlet>
<servlet-name>ImageExportService</servlet-name>
<servlet-class>com.XXX.ImageExportService</servlet-class>
</servlet>
  <servlet-mapping>
      <servlet-name>ImageExportService</servlet-name>
      <url-pattern>/ImageExportService</url-pattern>
  </servlet-mapping>

5.  让Extjs 的Chart.save 切换到新的服务器。

Ext.draw.engine.ImageExporter.defaultUrl = 'ImageExportService';

(注意, 这部分是写在web端的, 可以放在 Ext.onReady 里面)

6. 全部完成, 写个例子测试一下

//author: oscar999
<script type="text/javascript">
var chart;
var panel1;
Ext.require(['*']);
Ext.onReady(function() { Ext.draw.engine.ImageExporter.defaultUrl = '/'+WEB_PROJECT_NAME+'/ImageExportService'; var store = Ext.create('Ext.data.JsonStore', {
fields: ['name', 'data'],
data: [
{ 'name': 'metric one', 'data':100000 },
{ 'name': 'metric two', 'data': 7 },
{ 'name': 'metric three', 'data': 5 },
{ 'name': 'metric four', 'data': 2 },
{ 'name': 'metric five', 'data':27 }
]
}); var chart = Ext.create('Ext.chart.Chart', {
renderTo: Ext.getBody(),
width: 500,
height: 300,
animate: true,
store: store,
axes: [{
type: 'Numeric',
position: 'bottom',
fields: ['data'],
label: {
renderer: Ext.util.Format.numberRenderer('0,0')
},
title: 'Sample Values',
grid: true,
minimum: 0
}, {
type: 'Category',
position: 'left',
fields: ['name'],
title: 'Sample Metrics'
}],
series: [{
type: 'bar',
axis: 'bottom',
highlight: true,
tips: {
trackMouse: true,
width: 140,
height: 28,
renderer: function(storeItem, item) {
this.setTitle(storeItem.get('name') + ': ' + storeItem.get('data') + ' views');
}
},
label: {
display: 'insideEnd',
field: 'data',
renderer: Ext.util.Format.numberRenderer('0'),
orientation: 'horizontal',
color: '#333',
'text-anchor': 'middle'
},
xField: 'name',
yField: 'data'
}]
}); Ext.MessageBox.confirm('Confirm Download', 'Would you like to download the chart as an image?', function(choice){
if(choice == 'yes'){
chart.save({
type: 'image/png',
filename:'testfile'
});
}
}); });
</script>

跨浏览器处理

可能想到会有一个问题, IE 的低版本还只是支持vml 绘图, 那在这些版本的IE中, 导出图是否就不行了呢?

其实不用担心, Extjs 已经帮我们处理好了, 即使在这些版本的IE中, 传递到服务器的也是 svg  格式的数据。

(另外发现的一点是, 如果要传入自己定义的参数, 比如filename 等, 直接从save 中可能不行,可以考虑从呼叫url 传入)

[Web Chart系列之六] canvas Chart 导出图文件的更多相关文章

  1. nginx高性能WEB服务器系列之六--nginx负载均衡配置+健康检查

    nginx系列友情链接:nginx高性能WEB服务器系列之一简介及安装https://www.cnblogs.com/maxtgood/p/9597596.htmlnginx高性能WEB服务器系列之二 ...

  2. nginx高性能WEB服务器系列之八--nginx日志分析与切割

    nginx系列友情链接:nginx高性能WEB服务器系列之一简介及安装https://www.cnblogs.com/maxtgood/p/9597596.htmlnginx高性能WEB服务器系列之二 ...

  3. nginx高性能WEB服务器系列之七--nginx反向代理

    nginx系列友情链接:nginx高性能WEB服务器系列之一简介及安装https://www.cnblogs.com/maxtgood/p/9597596.htmlnginx高性能WEB服务器系列之二 ...

  4. nginx高性能WEB服务器系列之四配置文件详解

    nginx系列友情链接:nginx高性能WEB服务器系列之一简介及安装https://www.cnblogs.com/maxtgood/p/9597596.htmlnginx高性能WEB服务器系列之二 ...

  5. nginx高性能WEB服务器系列之三版本升级

    nginx系列友情链接:nginx高性能WEB服务器系列之一简介及安装https://www.cnblogs.com/maxtgood/p/9597596.htmlnginx高性能WEB服务器系列之二 ...

  6. nginx高性能WEB服务器系列之二命令管理

    nginx系列友情链接:nginx高性能WEB服务器系列之一简介及安装https://www.cnblogs.com/maxtgood/p/9597596.htmlnginx高性能WEB服务器系列之二 ...

  7. nginx高性能WEB服务器系列之一简介及安装

    nginx系列友情链接:nginx高性能WEB服务器系列之一简介及安装https://www.cnblogs.com/maxtgood/p/9597596.htmlnginx高性能WEB服务器系列之二 ...

  8. nginx高性能WEB服务器系列之九--nginx运维故障日常解决方案

    nginx系列友情链接:nginx高性能WEB服务器系列之一简介及安装https://www.cnblogs.com/maxtgood/p/9597596.htmlnginx高性能WEB服务器系列之二 ...

  9. nginx高性能WEB服务器系列之五--实战项目线上nginx多站点配置

    nginx系列友情链接:nginx高性能WEB服务器系列之一简介及安装https://www.cnblogs.com/maxtgood/p/9597596.htmlnginx高性能WEB服务器系列之二 ...

随机推荐

  1. CKFinder 弹出窗口操作并设置回调函数

    CKFinder 弹出窗口操作并设置回调函数 官方例子参考CKFinderJava-2.4.1/ckfinder/_samples/popup.html 写一个与EXT集成的小例子 Ext.defin ...

  2. Android Activity动画属性简介

    Android Activity动画属性简介 在Android当中 设置activity的动画 需要复写 android:windowAnimationStyle这个属性 我们自定义一个动画样式来继承 ...

  3. BloomFilter——大规模数据处理利器[转]

    原文链接:原文 Bloom Filter是由Bloom在1970年提出的一种多哈希函数映射的快速查找算法.通常应用在一些需要快速判断某个元素是否属于集合,但是并不严格要求100%正确的场合. 一. 实 ...

  4. 网络打印协议之LPR或RAW

    网络打印端口 标准 TCP/IP 端口监视器 对于连接到网络的打印设备,标准的 TCP/IP 端口监视器就是最佳选择.标准端口监视器增强了LPR(line printer remote,远程行式打印机 ...

  5. hibernate不调用save也保存上了

    List<Instrument> insts = instService.search(search); if (insts.size() == 1) { Instrument inst ...

  6. 上手并过渡到PHP7(4)——取代fatal error的engine exceptions

    上手并过渡到PHP7 取代fatal error的engine exceptions 泊学原文链接泊学代码秀视频 自从PHP 4以来,PHP的错误处理几乎就是一成不变的.只不过在PHP 5.0里添加了 ...

  7. 无限级分类 mysql设计

  8. Mastering the game of Go with deep neural networks and tree search浅析

    Silver, David, et al. "Mastering the game of Go with deep neural networks and tree search." ...

  9. Java 二维码--转载

    周末试用下Android手机的二维码扫描软件,扫描了下火车票.名片等等,觉得非常不错很有意思的.当然Java也可以实现这些,现在就分享下如何简单用Java实现二维码中QRCode的编码和解码(可以手机 ...

  10. [转载]php设计模式之单例、多例设计模式

    单例(Singleton)模式和不常见的多例(Multiton)模式控制着应用程序中类的数量.如模式名称,单例只能实例化一次,只有一个对象,多例模式可以多次实例化. 基于Singleton的特性,我们 ...