项目在服务上运行出现中文水印乱码问题解决(第二篇)
Posted kdes
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了项目在服务上运行出现中文水印乱码问题解决(第二篇)相关的知识,希望对你有一定的参考价值。
一 ,第一种解决方法和问题现象前一篇随笔有说到:https://www.cnblogs.com/KdeS/p/11805914.html
二. 另一种解决方式
因为公司重新申请的新服务器,代码迁移到这台服务器上时发现本台服务器也没有微软雅黑字体和仿宋字体,按照上一篇的配置操作一遍之后发现并没有生效,按照同事的建议采取了另一种方式,经测试这个方法更加完美。
如果这个方法对你有所帮助,请按照自己的方式修改使用。
2.1 把需要使用到的字体文件从本地复制放到服务器,本地字体文件的路劲一般是在这个位置:C:WindowsFonts
然后记住字体文件的路径,后续会使用到,我放到服务器后的路劲如下:
https://grandpictest.xxx.xxx.com/common/font/msyh.ttc //微软雅黑 常规字体
https://grandpictest.xxx.xxx.com/common/font/msyhbd.ttc //微软雅黑 粗体字
https://grandpictest.xxx.xxx.com/common/font/simfang.ttf //仿宋常规字体
2.2 编写一个文件获取字体放到项目运行的服务器并使用,代码如下:
后续如果服务器检测到字体文件不存在,则需要借助hutool这个工具去下载字体文件,pom文件
<dependency> <groupId>cn.hutool</groupId> <artifactId>hutool-all</artifactId> <version>4.1.0</version> </dependency>
java 代码:
/** * 引入自定义的字体 * @param fontPath 字体存放路径(项目运行的服务器) * @param fontStyle 字体样式(是否加粗) * @param fontSize 字体大小 * @return * @throws IOException */ public static Font getFont(String fontPath,int fontStyle, float fontSize) throws IOException { String fontUrl = null; if(fontStyle==Font.BOLD) { fontUrl = fontPath+"msyhbd.ttc"; }else { fontUrl = fontPath+"msyh.ttc"; } File file = new File(fontUrl); //1.判断文件上级目录是否存在 String parentPath=file.getParent(); File parentFile = new File(parentPath); if(!parentFile.exists()) {//创建文件夹 parentFile.mkdirs(); } if(!file.exists()) {//如果文件不存在,则需要从阿里云下载到本地路径 if(fontStyle==Font.BOLD) { HttpUtil.downloadFile("https://grandpictest.oss-cn-beijing.aliyuncs.com/common/font/msyhbd.ttc",fontUrl); }else { HttpUtil.downloadFile("https://grandpictest.oss-cn-beijing.aliyuncs.com/common/font/msyh.ttc",fontUrl); } } Font font = null; try{ font = Font.createFont(Font.TRUETYPE_FONT, file); font = font.deriveFont(fontStyle, fontSize); }catch (Exception e){ return null; } return font; }
2.3 使用字体的方式和原来使用方式的对比
中文会乱码的代码,默认的字体是使用系统的,如果系统没有就会报错:
/** * * @param srcImgPath 原图片的路径 * @param Content1 水印的内容1 * @param logoImg logo图片路径 * @param Content2 水印的内容2 * @param jd 经度 * @param wd 纬度 * @param siteCode 污染源地址,目前除唐家沱,大竹林,龙井湾,刘家院 ,其他暂时为空 * @return */ public BufferedImage mark(String srcImgPath,String Content1,String logoImg,String Content2,String jd,String wd,String siteCode) { try { // 1.拿到服务器图片 URL url = new URL(srcImgPath); //创建连接 HttpURLConnection conn=(HttpURLConnection) url.openConnection(); conn.setRequestMethod("GET"); // 提交模式 conn.setConnectTimeout(10*1000);//连接超时5秒 conn.setReadTimeout(10*1000); //读取超时10秒 conn.connect();//连接 InputStream input=conn.getInputStream();//获取写入图片数据 int count=conn.getContentLength();//获取远程资源长度 byte[] result=new byte[count]; int readCount=0; while(readCount<count){//循环读取数据 readCount+=input.read(result,readCount,count-readCount); } //把读取完整后的的图片数组转化为输入流 InputStream is = new ByteArrayInputStream(result); BufferedImage srcImg = ImageIO.read(is); // Image srcImg = ImageIO.read(new File(srcImgPath));//图片来源是本地路径的读取 //获取原始图片的宽和高 int srcImgwidth = srcImg.getWidth(null); int srcImgheight = srcImg.getHeight(null); //如果是热成像图片,宽放大至1920.高度放大至1080 boolean boo=match(srcImgPath); if(boo) { srcImgwidth=1920; srcImgheight=1080; } //2.画水印需要一个画板 创建一个画板 BufferedImage buffImg = new BufferedImage(srcImgwidth,srcImgheight,BufferedImage.TYPE_INT_RGB); //3.创建一个2D的图像,方便对图像进行操作 Graphics2D g = buffImg.createGraphics(); //消除文字锯齿 g.setRenderingHint(RenderingHints.KEY_TEXT_ANTIALIASING,RenderingHints.VALUE_TEXT_ANTIALIAS_ON); //画出来 g.drawImage(srcImg, 0, 0, srcImgwidth, srcImgheight,null); //4.画黑色黑色 g.setColor(Color.BLACK); // 1.0f为透明度 ,值从0-1.0,依次变得不透明 g.setComposite(AlphaComposite.getInstance(AlphaComposite.SRC_ATOP, 0.3f)); //图层 g.fillRect(srcImgwidth-230,srcImgheight-550, 200, 450); //5.画白色框 g.setColor(Color.WHITE); //设置画笔的宽度. 越大,边框越粗 g.setStroke(new BasicStroke(2F)); // 设置线条透明度 ,值从0-1.0,依次变得不透明 g.setComposite(AlphaComposite.getInstance(AlphaComposite.SRC_OVER)); //画矩形 g.drawRect(srcImgwidth-215, srcImgheight-535, 170, 420); //6.水印内容“AI全息影像告警” //设置水印的字体样式 Font font = new Font("微软雅黑", Font.PLAIN, 20); g.setFont(font); //根据获取的坐标 在相应的位置画出水印 g.drawString("AI全息影像告警",srcImgwidth-200, srcImgheight-500); //7.水印内容(违规类别) Font font1 = new Font("微软雅黑", Font.BOLD, 34); g.setFont(font1); g.drawString(Content1,srcImgwidth-200, srcImgheight-450); //8.水印内容“区域实时AQI” Font font2 = new Font("微软雅黑", Font.BOLD, 20); g.setFont(font2); g.drawString("区域实时AQI",srcImgwidth-190, srcImgheight-330); //9.水印内容(AQI数值) Font font3 = new Font("微软雅黑", Font.PLAIN, 40); g.setFont(font3); //根据获取的坐标 在相应的位置画出水印,根据aqi的位数不同,设置值相对居中 try { if(Integer.valueOf(Content2)>99 && Integer.valueOf(Content2)<1000) { g.drawString(Content2,srcImgwidth-170, srcImgheight-280); }else if(Integer.valueOf(Content2)<10) { g.drawString(Content2,srcImgwidth-145, srcImgheight-280); }else { g.drawString(Content2,srcImgwidth-150, srcImgheight-280); } } catch (Exception e) { g.drawString(Content2,srcImgwidth-150, srcImgheight-280); } //10.水印内容“污染源经纬度” Font font4 = new Font("微软雅黑", Font.BOLD, 20); g.setFont(font4); g.drawString("污染源经纬度",srcImgwidth-190, srcImgheight-250); //11.水印内容(经度) Font font5 = new Font("微软雅黑", Font.PLAIN, 15); g.setFont(font5); g.drawString("经度:"+jd,srcImgwidth-190, srcImgheight-220); //12.水印内容(纬度) Font font6 = new Font("微软雅黑", Font.PLAIN, 15); g.setFont(font6); g.drawString("纬度:"+wd,srcImgwidth-190, srcImgheight-190); Font font7 = new Font("微软雅黑", Font. BOLD, 15); g.setFont(font7); g.drawString("污染源地址:",srcImgwidth-190, srcImgheight-160); String content1=""; String content2=""; if(siteCode!=null) {//分两行显示 content1=siteCode.substring(0,3); content2=siteCode.substring(3); } Font font8 = new Font("微软雅黑", Font.PLAIN, 15); g.setFont(font8); g.drawString(content1,srcImgwidth-110, srcImgheight-160); Font font9 = new Font("微软雅黑", Font.PLAIN, 15); g.setFont(font9); g.drawString(content2,srcImgwidth-190, srcImgheight-130); //13.画水印logo // 水印logo图象的路径 水印一般为gif或者png的,这样可设置透明度 URL url1 =new URL(logoImg); ImageIcon imgIcon = new ImageIcon(url1); // 得到Image对象。 Image img = imgIcon.getImage(); // 透明度 g.setComposite(AlphaComposite.getInstance(AlphaComposite.SRC_ATOP)); // 表示水印图片的位置 g.drawImage(img, srcImgwidth-160, srcImgheight-430,imgIcon.getIconWidth()/2,imgIcon.getIconHeight()/2, null); //释放画板的资源 g.dispose(); return buffImg; } catch (IOException e) { e.printStackTrace(); return null; } }
修改后的的代码,使用自己指定的字体:
/** * * @param srcImgPath 原图片的路径 * @param Content1 水印的内容1 * @param logoImg logo图片路径 * @param Content2 水印的内容2 * @param jd 经度 * @param wd 纬度 * @param siteCode 污染源地址,目前除唐家沱,大竹林,龙井湾,刘家院 ,其他暂时为空 * @return */ public BufferedImage mark(String srcImgPath,String Content1,String logoImg,String Content2,String jd,String wd,String siteCode) { try { // 1.拿到服务器图片 URL url = new URL(srcImgPath); //创建连接 HttpURLConnection conn=(HttpURLConnection) url.openConnection(); conn.setRequestMethod("GET"); // 提交模式 conn.setConnectTimeout(10*1000);//连接超时5秒 conn.setReadTimeout(10*1000); //读取超时10秒 conn.connect();//连接 InputStream input=conn.getInputStream();//获取写入图片数据 int count=conn.getContentLength();//获取远程资源长度 byte[] result=new byte[count]; int readCount=0; while(readCount<count){//循环读取数据 readCount+=input.read(result,readCount,count-readCount); } //把读取完整后的的图片数组转化为输入流 InputStream is = new ByteArrayInputStream(result); BufferedImage srcImg = ImageIO.read(is); // Image srcImg = ImageIO.read(new File(srcImgPath));//图片来源是本地路径的读取 //获取原始图片的宽和高 int srcImgwidth = srcImg.getWidth(null); int srcImgheight = srcImg.getHeight(null); //如果是热成像图片,宽放大至1920.高度放大至1080 boolean boo=match(srcImgPath); if(boo) { srcImgwidth=1920; srcImgheight=1080; } //2.画水印需要一个画板 创建一个画板 BufferedImage buffImg = new BufferedImage(srcImgwidth,srcImgheight,BufferedImage.TYPE_INT_RGB); //3.创建一个2D的图像,方便对图像进行操作 Graphics2D g = buffImg.createGraphics(); //消除文字锯齿 g.setRenderingHint(RenderingHints.KEY_TEXT_ANTIALIASING,RenderingHints.VALUE_TEXT_ANTIALIAS_ON); //画出来 g.drawImage(srcImg, 0, 0, srcImgwidth, srcImgheight,null); //4.画黑色黑色 g.setColor(Color.BLACK); // 1.0f为透明度 ,值从0-1.0,依次变得不透明 g.setComposite(AlphaComposite.getInstance(AlphaComposite.SRC_ATOP, 0.3f)); //图层 g.fillRect(srcImgwidth-230,srcImgheight-550, 200, 450); //5.画白色框 g.setColor(Color.WHITE); //设置画笔的宽度. 越大,边框越粗 g.setStroke(new BasicStroke(2F)); // 设置线条透明度 ,值从0-1.0,依次变得不透明 g.setComposite(AlphaComposite.getInstance(AlphaComposite.SRC_OVER)); //画矩形 g.drawRect(srcImgwidth-215, srcImgheight-535, 170, 420); //6.水印内容“AI全息影像告警” //设置水印的字体样式 Font font = getFont(fontPath,Font.PLAIN, 20); g.setFont(font); //根据获取的坐标 在相应的位置画出水印 g.drawString("AI全息影像告警",srcImgwidth-200, srcImgheight-500); //7.水印内容(违规类别) Font font1 = getFont(fontPath,Font.BOLD, 34); g.setFont(font1); g.drawString(Content1,srcImgwidth-200, srcImgheight-450); //8.水印内容“区域实时AQI” Font font2 = getFont(fontPath,Font.BOLD, 20); g.setFont(font2); g.drawString("区域实时AQI",srcImgwidth-190, srcImgheight-330); //9.水印内容(AQI数值) Font font3 = getFont(fontPath,Font.PLAIN, 40); g.setFont(font3); //根据获取的坐标 在相应的位置画出水印,根据aqi的位数不同,设置值相对居中 try { if(Integer.valueOf(Content2)>99 && Integer.valueOf(Content2)<1000) { g.drawString(Content2,srcImgwidth-170, srcImgheight-280); }else if(Integer.valueOf(Content2)<10) { g.drawString(Content2,srcImgwidth-145, srcImgheight-280); }else { g.drawString(Content2,srcImgwidth-150, srcImgheight-280); } } catch (Exception e) { g.drawString(Content2,srcImgwidth-150, srcImgheight-280); } //10.水印内容“污染源经纬度” Font font4 =getFont(fontPath,Font.BOLD, 20); g.setFont(font4); g.drawString("污染源经纬度",srcImgwidth-190, srcImgheight-250); //11.水印内容(经度) Font font5 = getFont(fontPath,Font.PLAIN, 15); g.setFont(font5); g.drawString("经度:"+jd,srcImgwidth-190, srcImgheight-220); //12.水印内容(纬度) Font font6 =getFont(fontPath,Font.PLAIN, 15); g.setFont(font6); g.drawString("纬度:"+wd,srcImgwidth-190, srcImgheight-190); Font font7 = getFont(fontPath,Font.BOLD, 15); g.setFont(font7); g.drawString("污染源地址:",srcImgwidth-190, srcImgheight-160); String content1=""; String content2=""; if(siteCode!=null) {//分两行显示 content1=siteCode.substring(0,3); content2=siteCode.substring(3); } Font font8 = getFont(fontPath,Font.PLAIN, 15); g.setFont(font8); g.drawString(content1,srcImgwidth-110, srcImgheight-160); Font font9 =getFont(fontPath,Font.PLAIN, 15); g.setFont(font9); g.drawString(content2,srcImgwidth-190, srcImgheight-130); //13.画水印logo // 水印logo图象的路径 水印一般为gif或者png的,这样可设置透明度 URL url1 =new URL(logoImg); ImageIcon imgIcon = new ImageIcon(url1); // 得到Image对象。 Image img = imgIcon.getImage(); // 透明度 g.setComposite(AlphaComposite.getInstance(AlphaComposite.SRC_ATOP)); // 表示水印图片的位置 g.drawImage(img, srcImgwidth-160, srcImgheight-430,imgIcon.getIconWidth()/2,imgIcon.getIconHeight()/2, null); //释放画板的资源 g.dispose(); return buffImg; } catch (IOException e) { e.printStackTrace(); return null; } }
2.4 区别:
前者
后者
三 .效果图
/** * * @param srcImgPath 原图片的路径 * @param Content1 水印的内容1 * @param logoImg logo图片路径 * @param Content2 水印的内容2 * @param jd 经度 * @param wd 纬度 * @param siteCode 污染源地址,目前除唐家沱,大竹林,龙井湾,刘家院 ,其他暂时为空 * @return */public BufferedImage mark(String srcImgPath,String Content1,String logoImg,String Content2,String jd,String wd,String siteCode) {try {// 1.拿到服务器图片URL url = new URL(srcImgPath);
//创建连接HttpURLConnection conn=(HttpURLConnection) url.openConnection();conn.setRequestMethod("GET"); // 提交模式conn.setConnectTimeout(10*1000);//连接超时5秒conn.setReadTimeout(10*1000); //读取超时10秒conn.connect();//连接
InputStream input=conn.getInputStream();//获取写入图片数据int count=conn.getContentLength();//获取远程资源长度byte[] result=new byte[count];int readCount=0;while(readCount<count){//循环读取数据readCount+=input.read(result,readCount,count-readCount);}//把读取完整后的的图片数组转化为输入流InputStream is = new ByteArrayInputStream(result); BufferedImage srcImg = ImageIO.read(is);
//Image srcImg = ImageIO.read(new File(srcImgPath));//图片来源是本地路径的读取//获取原始图片的宽和高int srcImgwidth = srcImg.getWidth(null);int srcImgheight = srcImg.getHeight(null);//如果是热成像图片,宽放大至1920.高度放大至1080boolean boo=match(srcImgPath);if(boo) {srcImgwidth=1920;srcImgheight=1080; }//2.画水印需要一个画板 创建一个画板BufferedImage buffImg = new BufferedImage(srcImgwidth,srcImgheight,BufferedImage.TYPE_INT_RGB);//3.创建一个2D的图像,方便对图像进行操作Graphics2D g = buffImg.createGraphics();//消除文字锯齿g.setRenderingHint(RenderingHints.KEY_TEXT_ANTIALIASING,RenderingHints.VALUE_TEXT_ANTIALIAS_ON);//画出来g.drawImage(srcImg, 0, 0, srcImgwidth, srcImgheight,null);
//4.画黑色黑色g.setColor(Color.BLACK);// 1.0f为透明度 ,值从0-1.0,依次变得不透明g.setComposite(AlphaComposite.getInstance(AlphaComposite.SRC_ATOP, 0.3f));//图层g.fillRect(srcImgwidth-230,srcImgheight-550, 200, 450);
//5.画白色框g.setColor(Color.WHITE);//设置画笔的宽度. 越大,边框越粗g.setStroke(new BasicStroke(2F));// 设置线条透明度 ,值从0-1.0,依次变得不透明g.setComposite(AlphaComposite.getInstance(AlphaComposite.SRC_OVER));//画矩形g.drawRect(srcImgwidth-215, srcImgheight-535, 170, 420);
//6.水印内容“AI全息影像告警”//设置水印的字体样式Font font = new Font("微软雅黑", Font.PLAIN, 20);g.setFont(font);//根据获取的坐标 在相应的位置画出水印g.drawString("AI全息影像告警",srcImgwidth-200, srcImgheight-500);
//7.水印内容(违规类别)Font font1 = new Font("微软雅黑", Font.BOLD, 34);g.setFont(font1);g.drawString(Content1,srcImgwidth-200, srcImgheight-450);
//8.水印内容“区域实时AQI”Font font2 = new Font("微软雅黑", Font.BOLD, 20);g.setFont(font2);g.drawString("区域实时AQI",srcImgwidth-190, srcImgheight-330);
//9.水印内容(AQI数值)Font font3 = new Font("微软雅黑", Font.PLAIN, 40);g.setFont(font3);//根据获取的坐标 在相应的位置画出水印,根据aqi的位数不同,设置值相对居中try {if(Integer.valueOf(Content2)>99 && Integer.valueOf(Content2)<1000) {g.drawString(Content2,srcImgwidth-170, srcImgheight-280);}else if(Integer.valueOf(Content2)<10) {g.drawString(Content2,srcImgwidth-145, srcImgheight-280);}else {g.drawString(Content2,srcImgwidth-150, srcImgheight-280);}} catch (Exception e) {g.drawString(Content2,srcImgwidth-150, srcImgheight-280);}
//10.水印内容“污染源经纬度”Font font4 = new Font("微软雅黑", Font.BOLD, 20);g.setFont(font4);g.drawString("污染源经纬度",srcImgwidth-190, srcImgheight-250);
//11.水印内容(经度)Font font5 = new Font("微软雅黑", Font.PLAIN, 15);g.setFont(font5);g.drawString("经度:"+jd,srcImgwidth-190, srcImgheight-220);
//12.水印内容(纬度)Font font6 = new Font("微软雅黑", Font.PLAIN, 15);g.setFont(font6);g.drawString("纬度:"+wd,srcImgwidth-190, srcImgheight-190);
Font font7 = new Font("微软雅黑", Font. BOLD, 15);g.setFont(font7);g.drawString("污染源地址:",srcImgwidth-190, srcImgheight-160);String content1="";String content2="";if(siteCode!=null) {//分两行显示content1=siteCode.substring(0,3);content2=siteCode.substring(3);}Font font8 = new Font("微软雅黑", Font.PLAIN, 15);g.setFont(font8);g.drawString(content1,srcImgwidth-110, srcImgheight-160);
Font font9 = new Font("微软雅黑", Font.PLAIN, 15);g.setFont(font9);g.drawString(content2,srcImgwidth-190, srcImgheight-130);
//13.画水印logo// 水印logo图象的路径 水印一般为gif或者png的,这样可设置透明度 URL url1 =new URL(logoImg);ImageIcon imgIcon = new ImageIcon(url1); // 得到Image对象。 Image img = imgIcon.getImage(); // 透明度 g.setComposite(AlphaComposite.getInstance(AlphaComposite.SRC_ATOP)); // 表示水印图片的位置 g.drawImage(img, srcImgwidth-160, srcImgheight-430,imgIcon.getIconWidth()/2,imgIcon.getIconHeight()/2, null);
//释放画板的资源g.dispose();
return buffImg;} catch (IOException e) {e.printStackTrace();return null;}}
以上是关于项目在服务上运行出现中文水印乱码问题解决(第二篇)的主要内容,如果未能解决你的问题,请参考以下文章
ruoyi 框架发布在docker中,传参出现乱码问题的解决办法