java后端生成echarts图片

生成图的前提下载 phantomjs-2.1.1-windows 与对应的js

 

一种方式和网上大多方式大同小异 直接上码:

@Component
public class EchartsUtil {
    /**
     * 临时文件夹路径
     */
    @Value("${file.path}")
    private  String TEMP_FILE_PATH;
    @Value("${echartHost}")
    private  String   echartHost;
    private static final String SUCCESS_CODE = "1";
    private static final Logger logger = LoggerFactory.getLogger(EchartsUtil.class);

    private static EchartsUtil EchartsUtil;
    @PostConstruct
    public void init() {
        EchartsUtil=this;
        EchartsUtil.TEMP_FILE_PATH=this.TEMP_FILE_PATH;
        EchartsUtil.echartHost=this.echartHost;

    }

    public static String generateEchartsBase64(String option) throws ClientProtocolException, IOException {
        String base64 = "";
        if (option == null) {
            return base64;
        }
        option = option.replaceAll("\\s+", "").replaceAll("\"", "'");

        // 将option字符串作为参数发送给echartsConvert服务器
        Map<String, String> params = new HashMap<>();
        params.put("opt", option);
        String response = HttpUtil.post(EchartsUtil.echartHost, params, "utf-8");

        // 解析echartsConvert响应
        JSONObject responseJson = JSON.parseObject(response);
        String code = responseJson.getString("code");

        // 如果echartsConvert正常返回
        if (SUCCESS_CODE.equals(code)) {
            base64 = responseJson.getString("data");
        }
        // 未正常返回
        else {
            String string = responseJson.getString("msg");
            throw new RuntimeException(string);
        }
        return base64;
    }

    public static String  getImage(Map<String, Object> datas) throws IOException {
  
        String option = null;
        try {
            if (!datas.containsKey("ftl")){
                logger.error("没有指定生成图表的模板!");
                return null;
            }
            option = FreemarkerUtil.generateString((String) datas.get("ftl"), String.valueOf(datas.get("folder")), datas);
        } catch (TemplateException e) {
            logger.error(e.getMessage());
        }
        // 根据option参数
        String base64 = generateEchartsBase64(option);
        File file = new File(EchartsUtil.TEMP_FILE_PATH);
        if(!file.exists()) {
            // 如果不存在就创建文件
            file.mkdir();
        }
        BASE64Decoder decoder = new BASE64Decoder();
        String name= String.valueOf(UUID.randomUUID());
        try (OutputStream out = new FileOutputStream(EchartsUtil.TEMP_FILE_PATH+name+".jpg")){
            // 解密
            byte[] b = decoder.decodeBuffer(base64);
            for (int i = 0; i < b.length; ++i) {
                if (b[i] < 0) {
                    b[i] += 256;
                }
            }
            out.write(b);
            out.flush();
            return EchartsUtil.TEMP_FILE_PATH+name+".jpg";
        }
    }
public class FreemarkerUtil {
    private static final String path = FreemarkerUtil.class.getClassLoader().getResource("").getPath();

    public static String generateString(String templateFileName, String templateDirectory, Map<String, Object> datas)
            throws IOException, TemplateException {
        Configuration configuration = new Configuration(Configuration.VERSION_2_3_0);
        // 设置默认编码
        configuration.setDefaultEncoding("UTF-8");
        configuration.setClassicCompatible(true);
        //获取模板地址
        configuration.setClassForTemplateLoading(FreemarkerUtil.class,templateDirectory);

        // 生成模板对象
        Template template = configuration.getTemplate(templateFileName);

        // 将datas写入模板并返回
        try (StringWriter stringWriter = new StringWriter()) {
            template.process(datas, stringWriter);
            stringWriter.flush();
            return stringWriter.getBuffer().toString();
        }
    }
}
public class HttpUtil {
    public static String post(String url, Map<String, String> params, String charset)
            throws ClientProtocolException, IOException {
        String responseEntity = "";

        // 创建CloseableHttpClient对象
        CloseableHttpClient client = HttpClients.createDefault();

        // 创建post方式请求对象
        HttpPost httpPost = new HttpPost(url);

        // 生成请求参数
        List<NameValuePair> nameValuePairs = new ArrayList<NameValuePair>();
        if (params != null) {
            for (Map.Entry<String, String> entry : params.entrySet()) {
                nameValuePairs.add(new BasicNameValuePair(entry.getKey(), entry.getValue()));
            }
        }

        // 将参数添加到post请求中
        httpPost.setEntity(new UrlEncodedFormEntity(nameValuePairs, charset));

        // 发送请求,获取结果(同步阻塞)
        CloseableHttpResponse response = client.execute(httpPost);

        // 获取响应实体
        HttpEntity entity = response.getEntity();
        if (entity != null) {
            // 按指定编码转换结果实体为String类型
            responseEntity = EntityUtils.toString(entity, charset);
        }

        // 释放资源
        EntityUtils.consume(entity);
        response.close();

        return responseEntity;
    }

创建模板:

{
title: {
text: ${title}
},
xAxis: {
type: 'category',
data: ${aoxList}
},
yAxis: {
type: 'value'
},
color:[
${colordata}
],
series: [
{
data: ${aoList},
type: 'bar'
}
]
}
测试:
@GetMapping("12323")
public String test3(){
   //制造数据
    List<String> aoxList = new ArrayList<>();
    aoxList.add("2");  aoxList.add("4");  aoxList.add("7");aoxList.add("9");  aoxList.add("10");  aoxList.add("9");
    aoxList.add("8");  aoxList.add("8");  aoxList.add("7");
    List<String> aoList = new ArrayList<>();
    aoList.add("1");  aoList.add("4");  aoList.add("7");aoList.add("9");  aoList.add("10");  aoList.add("10");
    aoList.add("10");  aoList.add("10");  aoList.add("10");
    // 模板参数
    HashMap<String, Object> datas = new HashMap<>();
    //aohour、aoList、aoxList对应模板/template/option.ftl中的x和y轴的名字,模板可自行修改,
    //ftl 为设置模板的名字。路径在/templates下
    datas.put("title",JSON.toJSONString("wxw图示"));
    datas.put("colordata", JSON.toJSONString("#000000"));
    datas.put("aoxList", JSON.toJSONString(aoxList));
    datas.put("aoList", JSON.toJSONString(aoList));
    datas.put("ftl", "option.ftl");
    datas.put("folder","/Columnar");
    try {
        System.out.println( EchartsUtil.getImage(datas));
    } catch (IOException e) {
        e.printStackTrace();
    }
    return "ok";
}

 此方法前提:

没配置环境变量的话:

 显示echarts-convert server start success. [pid]=10364表明启动成功

此方式作者发现的问题:例如饼图还有一些复杂的图示是无法生成,不报错,请求一直阻塞在链接6666服务上面;

最后发现了第二种方式,

public class EchartGenerate {
  public static String generateEChart(String options) {
        String dataPath = writeFile(options);
        String fileName= UUID.randomUUID()+ ".jpg";
        String path = ConstantConfigUtil.FILE_PATH +fileName;
        try {
            File file = new File(path);    
            if (!file.exists()) {  
                File dir = new File(file.getParent());
                dir.mkdirs();
                file.createNewFile();
            }
            String cmd = ConstantConfigUtil.PHANTOM_JS_PATH +" "+ ConstantConfigUtil.ECHARTS_JS_PATH + " -infile " + dataPath + " -outfile " + path;
            System.out.println(cmd);
            Process process = Runtime.getRuntime().exec(cmd);
            BufferedReader input = new BufferedReader(new InputStreamReader(process.getInputStream()));
            String line = "";
            while ((line = input.readLine()) != null) {
                System.out.println(line);
            }
            input.close();

        } catch (IOException e) {
            e.printStackTrace();
        }finally{
            return path;
        }
    }

    
    public static String writeFile(String options) {
        String dataPath=ConstantConfigUtil.FILE_PATH+ UUID.randomUUID() +".json";
        try {
            File writename = new File(dataPath); 
            if (!writename.exists()) {   
                File dir = new File(writename.getParent());
                dir.mkdirs();
                writename.createNewFile(); 
            }
            BufferedWriter out = new BufferedWriter(new FileWriter(writename));
            out.write(options); 
            out.flush(); 
            out.close(); 
        } catch (IOException e) {
            e.printStackTrace();
        }
        return dataPath;
    }

}
public static String  getImage2(Map<String, Object> datas) throws IOException {
    String option = null;
    try {
        if (!datas.containsKey("ftl")){
            logger.error("没有指定生成图表的模板!");
            return null;
        }
        option = FreemarkerUtil.generateString((String) datas.get("ftl"), String.valueOf(datas.get("folder")), datas);
    } catch (TemplateException e) {
        logger.error(e.getMessage());
    }
    // 根据option参数
    String path = EchartGenerate.generateEChart(option);
    return path;

}

测试:

   @GetMapping("1232")
    public String test2(){
        //制造数据
        List<Map<String,Object>> data = new ArrayList<>();
        for(int i=1;i<6;i++){
        HashMap<String,Object> value=new HashMap<String,Object>();
        value.put("value",i+1);
        value.put("name",String.valueOf(i+1));
         data.add(value);
        }
        System.out.println( JSON.toJSONString(data));
        // 模板参数
        HashMap<String, Object> datas = new HashMap<>();
        //aohour、aoList、aoxList对应模板/template/option.ftl中的x和y轴的名字,模板可自行修改,
        //ftl 为设置模板的名字。路径在/templates下
//        datas.put("title",JSON.toJSONString("123图示"));
//        datas.put("cakeData",JSON.toJSONString(data));
        datas.put("ftl", "option.ftl");
        datas.put("folder","/area");
        try {
            System.out.println(EchartsUtil.getImage2(datas));
        } catch (IOException e) {
            e.printStackTrace();
        }
        return "ok";
    }

 问题:刚开始按照网上的方式  配置了环境变量:

 故:

 这里的值为

 但是请求一直报错,生成的图片也无法打开:

但是这个命令直接用cmd执行时成功的

最后只能使用对应的绝对路径: 生成成功;

以上是结合个人见解与网上信息所得。

  • 0
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
图表图片的步骤是什么? 回答: 生成echarts图表图片的步骤如下: 1. 首先,需要安装部署Phantomjs,可以将下载好的Phantomjs放在任意位置。 2. 找到echarts-convert.js文件,并将其放在与Phantomjs相同的目录下。 3. 在命令行中执行命令,例如在Linux系统中可以执行nohup phantomjs echarts-convert.js -s -p 50130 > echarts.log 2>&1 &,而在Windows系统中可以执行C:\Users\Administrator\Desktop\phantomjs-2.1.1-windows\bin>phantomjs C:\Users\Administrator\Desktop\echartsconvert\echarts-convert.js -s -p 9090。\[2\]\[3\] 4. 调用接口生成图片,可以通过发送请求来调用接口生成echarts图表的图片。 #### 引用[.reference_title] - *1* *2* [java后台生成echarts图表图片](https://blog.csdn.net/zixuanyankai/article/details/130702369)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v91^insertT0,239^v3^insert_chatgpt"}} ] [.reference_item] - *3* [java 实现后台生成echarts 图片](https://blog.csdn.net/weixin_43831289/article/details/119645323)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v91^insertT0,239^v3^insert_chatgpt"}} ] [.reference_item] [ .reference_list ]
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值