java将文字写在图片上,并做成压缩包导出到客户端


应业务要求,批量制作图片并导出到本地,之前尝试了几次,走出了一个误区,不能再java后台直接将文件上传到客户端本地,后来又发现浏览器不能一次导出多张图片,于是,只能制作多个图片,先上传到服务器,再打成压缩包导出到浏览器,终于达到了想要的效果。
 步骤则是:先把所要制作的内容和文字结合在一起,传输到服务器后,直接压缩到本地。以下是相关代码:

    /**
	 * 制作图片
	 * @param benisonTemplateBO:模板对象(包含抬头内容,字体,颜色,主体内容,字体,颜色,落款内容,字体,颜色)
	 * @param order 订单map对象(包括订单编号,落款人姓名,祝福人姓名等,用来动态替换图片上的文字信息)
	 * @param time 当前时间(自定义文件夹用)
	 */
	public Map makeImg(BenisonTemplateBO benisonTemplateBO,Dto order,String time){  
	
	Map map = new HashMap();
	String newImgUrl = null;
	 try {  
		//设置抬头的字体
		FontText titleText = new FontText(order.getAsString("bless_name"),benisonTemplateBO.getTitleColour(), Integer.valueOf(benisonTemplateBO.getTitleSize()), benisonTemplateBO.getTitleType());
		//设置主体内容的字体
		FontText bodyText = new FontText(benisonTemplateBO.getRuleContent(),benisonTemplateBO.getBodyColour(), Integer.valueOf(benisonTemplateBO.getBodySize()), benisonTemplateBO.getBodyType());
		//设置落款内容的字体
		FontText tailText = new FontText(order.getAsString("write_name"),benisonTemplateBO.getTailColour(), Integer.valueOf(benisonTemplateBO.getTailSize()), benisonTemplateBO.getTailType());
		
		//拷贝图片到另一个文件夹
		String path = CommonUtil.exportUploadFilePath()+time+"/";//获取properties属性中导出后的文件路径
		logger.info("<=========path:{}=========>",path);
		map.put("path", path);
		//动态获取文件格式
		String fileFormat =benisonTemplateBO.getImgUrl().substring(benisonTemplateBO.getImgUrl().indexOf(".")+1,benisonTemplateBO.getImgUrl().length()); 
		logger.info("<=========fileFormat:{}=========>",fileFormat);
		String fileName = order.get("order_code")+"."+fileFormat;//新的文件名
		//如果没有文件夹,则新创建一个。
		Boolean dirFlag = createDir(path);
		if(!dirFlag){
			map.put("result", "false");
			map.put("msg", "创建文件夹失败");
			return map;
		}
		//拷贝图片为了不改变原图片
		newImgUrl = copyFile(CommonUtil.uploadFilePath()+benisonTemplateBO.getImgUrl(),path+fileName);
		if(StringUtils.isEmpty(newImgUrl)){
			map.put("result", "false");
			map.put("msg", "拷贝文件失败");
			return map;
		}
		//制作图片(注释是另一种,只支持JPG图像)
//      InputStream is = new FileInputStream(newImgUrl);  
//      JPEGImageDecoder jpegDecoder = JPEGCodec.createJPEGDecoder(is);  //通过JPEG图象流创建JPEG数据流解码器  (只能解析JPEGt图片)
//      BufferedImage buffImg = jpegDecoder.decodeAsBufferedImage();   //解码当前JPEG数据流,返回BufferedImage对象  
		File file = new File(newImgUrl);
		Image image = ImageIO.read(file);//得到带有图片属性的对象
		
		BufferedImage buffImg =ImageIO.read(file);
        //创建画笔
        Graphics2D g = buffImg.createGraphics();
//      g.setComposite(AlphaComposite.getInstance(AlphaComposite.SRC_ATOP, 1.0f)); // 1.0f为透明度 ,值从0-1.0,依次变得不透明(没有用到)
        //写抬头
        g.setColor(getColor(titleText.getWm_text_color()));
        g.setBackground(Color.white);
        g.setFont(getFont(titleText));
        g.drawString(titleText.getText(), Integer.valueOf(benisonTemplateBO.getTitleX()), Integer.valueOf(benisonTemplateBO.getTitleY()));//在图片上写文字:内容,X坐标,Y坐标
        //写主体
        g.setColor(getColor(bodyText.getWm_text_color()));
        g.setBackground(Color.white);
        g.setFont(getFont(bodyText));
        //主体文字要求自动换行处理
        newline(image,bodyText,g,benisonTemplateBO,order);
//      g.drawString(bodyText.getText(), Integer.valueOf(benisonTemplateBO.getBodyX()), Integer.valueOf(benisonTemplateBO.getBodyY()));//在图片上写文字:内容,X坐标,Y坐标
        //写落款
        g.setColor(getColor(tailText.getWm_text_color()));
        g.setBackground(Color.white);
        g.setFont(getFont(tailText));
        g.drawString(tailText.getText(), Integer.valueOf(benisonTemplateBO.getTailX()), Integer.valueOf(benisonTemplateBO.getTailY()));//在图片上写文字:内容,X坐标,Y坐标
        //关闭画笔
        g.dispose();

        FileOutputStream out = new FileOutputStream(newImgUrl);
        //创键编码器,用于编码内存中的图象数据。            
//      JPEGImageEncoder en = JPEGCodec.createJPEGEncoder(out);  
//      en.encode(buffImg);
        ImageIO.write(buffImg,fileFormat,out);
//      is.close();  
        out.flush();
        out.close();
        } catch (FileNotFoundException e) {  
            e.printStackTrace();  
        } catch (ImageFormatException e) {  
            e.printStackTrace();  
        } catch (IOException e) {  
            e.printStackTrace();  
        }  
	 	map.put("result", "true");
		map.put("msg", newImgUrl);//要返回的图片URL,存储数据用
        return map; 
    } 	/**
	 * 文字处理
	 * @param text自定义字体类
	 * @return
	 */
	public Font getFont(FontText text){
		Font font = null;
        if (!StringUtils.isEmpty(text.getWm_text_font())
                && text.getWm_text_size() != null) {
            font = new Font(text.getWm_text_font(), Font.BOLD,
            		text.getWm_text_size());
        } else {
            font = new Font(null, Font.BOLD, 15);
        }
        
        return font;
	}	/**
	 * 颜色处理
	 * @param color(所传颜色,如"#1234567")
	 * @return
	 */
	public Color getColor(String color) {
        if (color.charAt(0) == '#') {
            color = color.substring(1);
        }
        if (color.length() != 6) {
            return null;
        }
        try {
            int r = Integer.parseInt(color.substring(0, 2), 16);
            int g = Integer.parseInt(color.substring(2, 4), 16);
            int b = Integer.parseInt(color.substring(4), 16);
            return new Color(r, g, b);
        } catch (NumberFormatException nfe) {
            return null;
        }
    }	/**
	 * 复制图片
	 * @param src:原文件
	 * @param target:目标文件
	 */
	public String copyFile(String src,String target)  
    {     
       File srcFile = new File(src);    
       File targetFile = new File(target);    
       try {    
           InputStream in = new FileInputStream(srcFile);     
           OutputStream out = new FileOutputStream(targetFile);    
           byte[] bytes = new byte[1024];    
           int len = -1;    
           while((len=in.read(bytes))!=-1)  
           {    
               out.write(bytes, 0, len);    
           }    
           in.close();    
           out.close();  
           logger.info("文件复制成功");   
       } catch (FileNotFoundException e) {    
           e.printStackTrace();    
       } catch (IOException e) {    
           e.printStackTrace();    
       }    
       	return target;
    }  	/**
	 * 创建文件夹
	 * @param destDirName(要创建的文件夹名称)
	 * @return
	 */
	public boolean createDir(String destDirName) {  
        File dir = new File(destDirName);  
        if (!dir.exists()) {  
        	if (!destDirName.endsWith(File.separator)) {  
                destDirName = destDirName + File.separator;  
            }  
            //创建目录  
            if (dir.mkdirs()) {  
                logger.info("创建目录" + destDirName + "成功!");  
                return true;  
            } else {  
            	logger.error("创建目录" + destDirName + "失败!");  
                return false;  
            }   
        }  
        return true;  
    }	/**
	 * 文字自定义换行
	 * @param image:图片对象
	 * @param bodyText:自定义字体对象
	 * @param g:画笔对象
	 * @param benisonTemplateBO:模板对象
	 */
	public void newline(Image image,FontText bodyText,Graphics2D g,BenisonTemplateBO benisonTemplateBO,Dto order){
		
		//获取图片宽高(注释为另一种方法,自动换行)
		int srcImgWidth = image.getWidth(null);
//		int srcImgHeight = image.getHeight(null);
		//获取水印文字的总长度
		int fontlen = 0;
		if(!StringUtils.isEmpty(bodyText.getText())){
			
			fontlen = g.getFontMetrics(g.getFont()).charsWidth(bodyText.getText().toCharArray(),0,
					bodyText.getText().length());
			
//			int line = fontlen/srcImgWidth;//文字长度相对于图片宽度应该有多少行
//			int y = srcImgHeight- (line + 1)*bodyText.getWm_text_size();
			logger.info("水印文字总长度:"+fontlen + ",图片宽度:"+ srcImgWidth +",字符个数:"+ bodyText.getText().length());
			
			int tempX = Integer.valueOf(benisonTemplateBO.getBodyX());//起始横坐标
			int tempY = Integer.valueOf(benisonTemplateBO.getBodyY());//起始纵坐标
			//文字叠加,自动换行叠加
//			int tempCharLen = 0;//单字符长度
//			int tempLineLen = 0;//单行字符总长度临时计算
//			StringBuffer sb =new StringBuffer();
			
//			for(int i=0;i= srcImgWidth) {
//					//长度已经满一行,进行文字叠加
//					g.drawString(sb.toString(), tempX, tempY);
//					
//					sb.delete(0, sb.length());//清空内容,重新追加
//					
//					tempY += bodyText.getWm_text_size();
//					
//					tempLineLen =0;
//				}
//				sb.append(tempChar);//追加字符
//			}
//			g.drawString(sb.toString(), tempX, tempY);//最后叠加余下的文字
			//自定义根据符号换行
			String[] strs = bodyText.getText().split("/n");
			
			try {
				for(String str:strs){
					int startX = 0;
					//截取每行的起始横坐标
					if(str.contains("@*")&&str.contains("*@")){
						startX = Integer.valueOf(str.substring(str.indexOf("@*")+2, str.indexOf("*@")));
						str= str.substring(str.indexOf("*@")+2,str.length());
					}
					//替换祝福对象和落款人
					if(str.contains("@blessName")){
						str = str.replace("@blessName",order.getAsString("bless_name"));
					}
					if(str.contains("@writeName")){
						str = str.replace("@writeName", order.getAsString("write_name"));
					}
					g.drawString(str, tempX+startX, tempY);
					tempY += bodyText.getWm_text_size()+17;
				}
			} catch (Exception e) {
				logger.error("<===CommodityActionImpl.newline=====祝福语内容规则解析出现问题!=====>");;
			}
			
		}
		
	}emptypackage com.taikang.iu.com;

public class FontText {
    
    private String text;
    
    private String wm_text_color;//颜色
    
    private Integer wm_text_size;//大小
    
    private String wm_text_font;//字体  “黑体,Arial”

    public String getText() {
        return text;
    }

    public void setText(String text) {
        this.text = text;
    }

    public String getWm_text_color() {
        return wm_text_color;
    }

    public void setWm_text_color(String wm_text_color) {
        this.wm_text_color = wm_text_color;
    }

    public Integer getWm_text_size() {
        return wm_text_size;
    }

    public void setWm_text_size(Integer wm_text_size) {
        this.wm_text_size = wm_text_size;
    }

    public String getWm_text_font() {
        return wm_text_font;
    }

    public void setWm_text_font(String wm_text_font) {
        this.wm_text_font = wm_text_font;
    }

    public FontText(String text,String wm_text_color,
            Integer wm_text_size, String wm_text_font) {
        super();
        this.text = text;
        this.wm_text_color = wm_text_color;
        this.wm_text_size = wm_text_size;
        this.wm_text_font = wm_text_font;
    }
    
    public FontText(){}
    
}	/**
	 * 将压缩后的文件输出到客户端
	 * @param response
	 */
	public void toCilent(HttpServletResponse response){
		
		String fileName = "picture";
		String path = "D:/file/";//需要压缩文件所在位置
		try {
			OutputStream toClient = new BufferedOutputStream(response.getOutputStream());
			response.setContentType("application/octet-stream");
			//如果输出的是中文名的文件,在此处就要用URLEncoder.encode方法进行处理
			response.setHeader("Content-Disposition", "attachment;filename=" +
					URLEncoder.encode(fileName+".zip", "UTF-8"));
			PicturePackZipTools.compressZip(path, toClient,"UTF-8", false);
		} catch (IOException e) {
			e.printStackTrace();
		}
		
	}package com.taikang.iu.com;
  
import java.io.BufferedInputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.util.Arrays;
import java.util.Collections;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Set;

import org.apache.tools.zip.ZipEntry;
import org.apache.tools.zip.ZipOutputStream;

/** 
 * 图片压缩成ZIP,支持并发多线程; 
 * java.util.ZipOutputStream中文乱码  
 * 方法一、JDK1.7可以设置编码  
 * 方法二、换成Apache ant 
 * @author OY 
 *  
 */  
public class PicturePackZipTools {  
  
private static String DEFAULT_COMPRESS_ENCODE = "GBK";  
      
    private static ZipOutputStream getZipStreamEncode(OutputStream output,  
            String encode) {  
        ZipOutputStream zipStream = new ZipOutputStream(output);  
        if (encode == null || "".equals(encode)) {  
            zipStream.setEncoding(DEFAULT_COMPRESS_ENCODE);  
        } else {  
            zipStream.setEncoding(encode);  
        }  
        return zipStream;  
    }  
  
    /** 
     * 访问本地路径下的所有文件 
     *  
     * @param path 
     * @return 
     */  
    public static List loadFiles(String path) {  
        List list = null;  
        try {  
            File fold = new File(path);  
            if (fold.isDirectory()) {  
                File[] files = fold.listFiles();  
                list = Arrays.asList(files);  
            }  
        } catch (Exception e) {  
            e.printStackTrace();  
        }  
        return list;  
    }  
  
    /** 
     * 读取本地系统路径下的所有图片打成ZIP 
     *  
     * @param path 
     * @param output 
     * @param compress 
     */  
    public static void compressZip(String path, OutputStream output,  
            String encode, boolean compress) {  
        List listfiles = null;  
        ZipOutputStream zipStream = null;  
        try {  
            zipStream = getZipStreamEncode(output, encode);  
            listfiles = loadFiles(path);  
            for (File file : listfiles) {  
                compressZip(file, zipStream, compress);  
            }  
        } catch (Exception e) {  
            e.printStackTrace();  
        } finally {  
            try {  
                if (zipStream != null) {  
                    zipStream.close();  
                }  
            } catch (IOException e) {  
                e.printStackTrace();  
            }  
        }  
    }  
  
    /** 
     * 读取网络图片打成打成ZIP 
     * @param urls 
     *            key = 图片名, value = 图片URL 
     * @param output  
     * @param encode 编码 
     * @param compress 是否压缩 
     */  
    public static void compressZip(Map urls,  
            OutputStream output, String encode, boolean compress) {  
        ZipOutputStream zipStream = null;  
        try {  
            zipStream = getZipStreamEncode(output, encode);  
            Map synUrls = Collections.synchronizedMap(urls);  
            Set> set = synUrls.entrySet();  
            Iterator> it = set.iterator();  
            while (it.hasNext()) {  
                Entry entry = it.next();  
                compressZip(entry.getValue(), zipStream, entry.getKey(),  
                        compress);  
            }  
        } catch (Exception e) {  
            e.printStackTrace();  
        } finally {  
            try {  
                if (zipStream != null) {  
                    zipStream.close();  
                }  
            } catch (IOException e) {  
                e.printStackTrace();  
            }  
        }  
    }  
  
    /** 
     * 压缩单个文件为ZIP 
     * @param file 
     * @param output 
     * @param encode 
     * @param compress 
     */  
    public static void compressZip(File file, OutputStream output,  
            String encode, boolean compress) throws Exception{  
        FileInputStream input = null;  
        try {  
            input = new FileInputStream(file);  
            compressZip(input,file.getName(),output,encode,compress);  
        } catch (Exception e) {  
            e.printStackTrace();  
        }  finally {  
            try {  
                if (input != null)  
                    input.close();  
            } catch (IOException e) {  
                e.printStackTrace();  
            }  
        }  
          
    }  
  
    /** 
     * 压缩单个文件为ZIP 
     * @param input 
     * @param fileName 
     * @param output 
     * @param encode 
     * @param compress 
     */  
    public static void compressZip(InputStream input, String fileName,  
            OutputStream output, String encode, boolean compress) throws Exception {  
        ZipOutputStream zipStream = null;  
        try {  
            zipStream = getZipStreamEncode(output, encode);  
            zip(input, zipStream, fileName, compress);  
        } catch (Exception e) {  
            e.printStackTrace();  
        } finally {  
            try {  
                if (zipStream != null)  
                    zipStream.close();  
            } catch (IOException e) {  
                e.printStackTrace();  
            }  
        }  
    }  
  
    /** 
     * 本地图片 
     */  
    private static void compressZip(File file, ZipOutputStream zipStream,  
            boolean compress) throws Exception{  
        FileInputStream input = null;  
        try {  
            input = new FileInputStream(file);  
            zip(input, zipStream, file.getName(), compress);  
        } catch (Exception e) {  
            e.printStackTrace();  
        }finally{  
            try {  
                if(input != null)  
                    input.close();  
            } catch (IOException e) {  
                e.printStackTrace();  
            }  
        }  
    }  
  
    /** 
     * @param input 
     * @param zipStream 
     * @param zipEntryName 
     * @param compress 
     */  
    private static void zip(InputStream input, ZipOutputStream zipStream,  
            String zipEntryName, boolean compress) throws Exception{  
        byte[] bytes = null;  
        BufferedInputStream bufferStream = null;  
        try {  
            if(input == null)  
                throw new Exception("获取压缩的数据项失败! 数据项名为:" + zipEntryName);  
            // 压缩条目不是具体独立的文件,而是压缩包文件列表中的列表项,称为条目,就像索引一样  
            ZipEntry zipEntry = new ZipEntry(zipEntryName);  
            // 定位到该压缩条目位置,开始写入文件到压缩包中  
            zipStream.putNextEntry(zipEntry);  
            if (compress) {  
//                bytes = CompressPictureTools.compressOfQuality(input, 0);  
                zipStream.write(bytes, 0, bytes.length);  
            } else {  
                bytes = new byte[1024 * 5];// 读写缓冲区  
                bufferStream = new BufferedInputStream(input);// 输入缓冲流  
                int read = 0;  
                while ((read = bufferStream.read(bytes)) != -1) {  
                    zipStream.write(bytes, 0, read);  
                }  
            }  
        } catch (IOException e) {  
            e.printStackTrace();  
        } finally {  
            try {  
                if (null != bufferStream)  
                    bufferStream.close();  
            } catch (IOException e) {  
                e.printStackTrace();  
            }  
        }  
    }  
}  


你可能感兴趣的:(java将文字写在图片上,并做成压缩包导出到客户端)