服务端基础设施开发----整合thumbnailator编写图片插件

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/cdnight/article/details/86710581

前言

图片处理一直是web网站的重点与难点。因为硬盘费钱,带宽更加费钱,流量一多系统分分钟崩给你看。。。
下面将解决这个问题。当然,个人写图片处理也是很费时间的,下面是参考项目与文章:
thumbnailator
Java生成缩略图之Thumbnailator

java图片处理开源框架

这篇文章有大部分用法,推荐:
Java使用google开源工具Thumbnailator实现图片压缩

值得注意的是,这个项目已经停滞了四年了。github上面有三页bug。。额???
所以,将它download下来直接整合到项目中,以后估计要一直改bug。。。

整合thumbnails项目

这个。。直接从官网下载项目源代码即可,整合情况如下:
在这里插入图片描述

比较重要的工具类

这个插件整合编写难度本来就不会很低,如果手头上没几个可靠的工具估计比较悬,这次用了一些很使用的工具类,例如用魔法数字判断一个文件类型:

package net.w2p.Shared.common.files;

public enum FileType {

    //--apk 1 --  504b03041400080808000d89f34a0000000000000000000000001400
    //--apk 2 --  504b0304140000000800000000008a6135b4bfcf360080a57c000b00
    //--apk 3 --  504b0304140000000800000000007e6cbc561fa30000c18301001400
    //--apk 4 --  504b03041400080808000052ce4a0000000000000000000000001400
    //--apk 5 --  504b0304140000000800000000007e6cbc561fa30000c18301001400
    //--apk 6 --  504b0304140000000800000000007e6cbc561fa30000c18301001400
    //--apk 7 --  504b0304140000000800000000007dec827617783d0060878d000b00
    //--apk 8 --  504b0304140000000800000000008204a0933fb23e00584790000b00
    //--apk 9 --  504b0304140000000800000000000682c35d46103e0048948f000b00
    //--apk10 --  504b030414000000080000000000b5a90c5ad3893b00ac2287000b00
    /**
     * JEPG.
     */
    JPEG("FFD8FF",".jpg"),

    //--apk暂时当成有两种。
    APK1("504b030414000000080000000000",".apk"),
    APK2("504b03041400080808000",".apk"),

    /**
     * PNG.
     */
    PNG("89504E47",".png"),

    /**
     * GIF.
     */
    GIF("47494638",".gif"),

    /**
     * TIFF.
     */
    TIFF("49492A00",".tiff"),

    /**
     * Windows Bitmap.
     */
    BMP("424D",".bmp"),

    /**
     * CAD.
     */
    DWG("41433130",".dwg"),

    /**
     * Adobe Photoshop.
     */
    PSD("38425053",".psd"),

    /**
     * Rich Text Format.
     */
    RTF("7B5C727466",".rtf"),

    /**
     * XML.
     */
    XML("3C3F786D6C",".xml"),

    /**
     * HTML.
     */
    HTML("68746D6C3E",".html"),
    /**
     * CSS.
     */
    CSS("48544D4C207B0D0A0942",".css"),
    /**
     * JS.
     */
    JS("696B2E71623D696B2E71",".js"),
    /**
     * Email [thorough only].
     */
    EML("44656C69766572792D646174653A",".eml"),

    /**
     * Outlook Express.
     */
    DBX("CFAD12FEC5FD746F",".dbx"),

    /**
     * Outlook (pst).
     */
    PST("2142444E",".pst"),

    /**
     * MS Word/Excel.
     */
    XLS_DOC("D0CF11E0",".doc"),
    XLSX_DOCX("504B030414000600080000002100",".docx"),
    /**
     * ZIP Archive.
     */
    ZIP("504B0304",".zip"),
    /**
     * Visio
     */
    VSD("d0cf11e0a1b11ae10000",".xsd"),
    /**
     * MS Access.
     */
    MDB("5374616E64617264204A",".mdb"),
    /**
     * WPS文字wps、表格et、演示dps都是一样的
     */
    WPS("d0cf11e0a1b11ae10000",".wps"),
    /**
     * torrent
     */
    TORRENT("6431303A637265617465",".torrent"),
    /**
     * WordPerfect.
     */
    WPD("FF575043",".wpd"),

    /**
     * Postscript.
     */
    EPS("252150532D41646F6265",".eps"),

    /**
     * Adobe Acrobat.
     */
    PDF("255044462D312E",".pdf"),

    /**
     * Quicken.
     */
    QDF("AC9EBD8F",".qdf"),

    /**
     * Windows Password.
     */
    PWL("E3828596",".pwl"),



    /**
     * RAR Archive.
     */
    RAR("52617221",".rar"),
    /**
     * JSP Archive.
     */
    JSP("3C2540207061676520",".jsp"),
    /**
     * JAVA Archive.
     */
    JAVA("7061636B61676520",".java"),
    /**
     * CLASS Archive.
     */
    CLASS("CAFEBABE0000002E00",".class"),
    /**
     * JAR Archive.
     */
    JAR("504B03040A000000",".jar"),
    /**
     * MF Archive.
     */
    MF("4D616E69666573742D56",".mf"),
    /**
     *EXE Archive.
     */
    EXE("4D5A9000030000000400",".exe"),
    /**
     *CHM Archive.
     */
    CHM("49545346030000006000","chm"),
        /*
         * INI("235468697320636F6E66"), SQL("494E5345525420494E54"), BAT(
         * "406563686F206f66660D"), GZ("1F8B0800000000000000"), PROPERTIES(
         * "6C6F67346A2E726F6F74"), MXP(
         * "04000000010000001300"),
         */
    /**
     * Wave.
     */
    WAV("57415645",".wav"),

    /**
     * AVI.
     */
    AVI("41564920",".avi"),

    /**
     * Real Audio.
     */
    RAM("2E7261FD","ram"),

    /**
     * Real Media.
     */
    RM("2E524D46",".rm"),

    /**
     * MPEG (mpg).
     */
    MPG("000001BA",".mpg"),

    /**
     * Quicktime.
     */
    MOV("6D6F6F76",".mov"),

    /**
     * Windows Media.
     */
    ASF("3026B2758E66CF11",".asf"),

    /**
     * MIDI.
     */
    MID("4D546864",".mid"),
    /**
     * MP4.
     */
    MP4("00000020667479706d70",".mp4"),
    /**
     * MP3.
     */
    MP3("49443303000000002176",".mp3"),
    /**
     * FLV.
     */
    FLV("464C5601050000000900",".flv"),
    UNKNOWN("","")
    ;

    private String value = "";

    /**
     * Constructor.
     *
     * @param type
     */
    private FileType(String value,String ext) {
        this.value = value;
        this.ext=ext;
    }

    public String getValue() {
        return value;
    }

    public void setValue(String value) {
        this.value = value;
    }

    public void setExt(String ext){
        this.ext=ext;
    }
    public String getExt(){
        return ext;
    }

    public String getImageType(){
        if(ext==null||ext.isEmpty()){
            return "";
        }
        return ext.trim().replace(".","");
    }

    private String ext;
}
package net.w2p.Shared.common.files;

import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.util.Arrays;

public final class FileTypeJudge {
    /** * Constructor */
    private FileTypeJudge() {}
    /** * 将文件头转换成16进制字符串 *
     * @param src 原生byte
     * @return 16进制字符串 */
    private static String bytesToHexString(byte[] src) {
        StringBuilder stringBuilder = new StringBuilder();
        if (src == null || src.length <= 0) {
            return null;
        }
        for (int i = 0; i < src.length; i++) {
            int v = src[i] & 0xFF;
            String hv = Integer.toHexString(v);
            if (hv.length() < 2) {
                stringBuilder.append(0);
            }
            stringBuilder.append(hv);
        }
        return stringBuilder.toString();
    }
    /**
     * * 得到文件头
     * @param filePath * 文件路径 *
     * @return 文件头 *
     * @throws IOException */
    private static String getFileContent(String filePath) throws IOException {
        byte[] b = new byte[28];
        InputStream inputStream = null;
        try {
            inputStream = new FileInputStream(filePath);
            inputStream.read(b, 0, 28);
        } catch (IOException e) {
            e.printStackTrace();
            throw e;}
        finally {if (inputStream != null)
        {
            try {inputStream.close();}
            catch (IOException e)
            {e.printStackTrace();throw e;}}}
        return bytesToHexString(b);}

    /**
     * * 得到文件头
     * @param fileContent * 文件内容 *
     * @return 文件头 *
     * @throws IOException */
    private static String getFileContent(byte[] fileContent) throws IOException {
        byte[] b = new byte[28];

        b= Arrays.copyOfRange(fileContent,0,28);

        return bytesToHexString(b);}

    /**
     * 判断文件类型 * *
     * @param content
     *文件路径 *
     *@return 文件类型 */
    public static FileType getType(byte[] content) throws IOException {
        String fileHead = getFileContent(content);
//        System.out.println("===============魔术数字:");
//        System.out.println(fileHead);

        if (fileHead == null || fileHead.length() == 0) {
            return null;
        }
        fileHead = fileHead.toUpperCase();
        FileType[] fileTypes = FileType.values();
        for (FileType type : fileTypes) {
            if (fileHead.startsWith(type.getValue().toUpperCase())) {
                return type;
            }}

        return null;}

    /**
     * 判断文件类型 * *
     * @param filePath *
     *文件路径 *
     *@return 文件类型 */
    public static FileType getType(String filePath) throws IOException {
        String fileHead = getFileContent(filePath);
        if (fileHead == null || fileHead.length() == 0) {
            return null;}fileHead = fileHead.toUpperCase();
        FileType[] fileTypes = FileType.values();
        for (FileType type : fileTypes) {
            if (fileHead.startsWith(type.getValue())) {
                return type;}}return null;}
    public static void main(String args[]) throws Exception {
        System.out.println(FileTypeJudge.getType("d:\\FileMonitor.java"));
    }
}

添加对应的配置类以及工具类

引入依赖

WebExt下面要引入模块依赖的:
在这里插入图片描述
在WebExt下面添加对应的类,如下图:
在这里插入图片描述
这次整合的类略有点多

代码分别是:

ResizeMode

package net.w2p.WebExt.dict;


import net.w2p.Shared.common.KeyValuePair;

import java.util.ArrayList;
/***
 * 图片缩放规则
 * ***/
public  enum ResizeMode {
    KeepAspectRatio("按比例缩放",0)
    ,ScaleOnWith("按比例等宽缩放",1)
    ,ScaleOnHeight("按比例等高缩放",2)
    ,AbsoluteSize("绝对尺寸(严格按照尺寸缩放不惜变形)",3)
    ;
    private String _name;
    private Integer _id;
    private ResizeMode(String name, Integer id) {
        this._name = name;
        this._id = id;
    }
    public String getName() {
        return this._name;
    }
    public Integer getId() {
        return this._id;
    }
    public static ResizeMode  getTarget(Integer id)  {
        ResizeMode target = null;
        for(ResizeMode cmd : ResizeMode.values()) {
            if(cmd.getId() == id.intValue()) {
                target = cmd;
                break;
            }
        }
        if(target == null) {
            return null;
        }
        return target;
    }
    public static String  getNameById(Integer id)  {
        ResizeMode target = null;
        if(id==null){
            return "";
        }
        for(ResizeMode cmd : ResizeMode.values()) {
            if(cmd.getId() == id.intValue()) {
                target = cmd;
                break;
            }
        }
        if(target == null) {
            return "";
        }
        return target.getName();
    }
    /**
     * 获得列表信息。
     */
    public static ArrayList<KeyValuePair> getList()  {
        ArrayList<KeyValuePair> list=new ArrayList<KeyValuePair>();
        for(ResizeMode cmd : ResizeMode.values()) {
            KeyValuePair kv=new KeyValuePair();
            kv.setKey(cmd.getId()+"");
            kv.setValue(cmd.getName());
            list.add(kv);
        }
        return list;
    }
}

WaterMarkPos

package net.w2p.WebExt.dict;

import net.w2p.Shared.common.KeyValuePair;

import java.util.ArrayList;

/***
 * 水印位置
 * ***/
public  enum WaterMarkPos {
    BottomRight("右下",0)
    ,BottomLeft("左下",1)
    ,TopLeft("左上",2)
    ,TopRight("右上",3)
    ,CENTER("正中心",4)
    ,CenterLeft("中间左侧",5)
    ,CenterRight("中间右侧",6)
    ;
    private String _name;
    private Integer _id;
    private WaterMarkPos(String name, Integer id) {
        this._name = name;
        this._id = id;
    }
    public String getName() {
        return this._name;
    }
    public Integer getId() {
        return this._id;
    }
    public static WaterMarkPos  getTarget(Integer id)  {
        WaterMarkPos target = null;
        for(WaterMarkPos cmd : WaterMarkPos.values()) {
            if(cmd.getId() == id.intValue()) {
                target = cmd;
                break;
            }
        }
        if(target == null) {
            return null;
        }
        return target;
    }
    public static String  getNameById(Integer id)  {
        WaterMarkPos target = null;
        if(id==null){
            return "";
        }
        for(WaterMarkPos cmd : WaterMarkPos.values()) {
            if(cmd.getId() == id.intValue()) {
                target = cmd;
                break;
            }
        }
        if(target == null) {
            return "";
        }
        return target.getName();
    }
    /**
     * 获得列表信息。
     */
    public static ArrayList<KeyValuePair> getList()  {
        ArrayList<KeyValuePair> list=new ArrayList<KeyValuePair>();
        for(WaterMarkPos cmd : WaterMarkPos.values()) {
            KeyValuePair kv=new KeyValuePair();
            kv.setKey(cmd.getId()+"");
            kv.setValue(cmd.getName());
            list.add(kv);
        }
        return list;
    }
}

ThumbnailImage

package net.w2p.WebExt.vo;

import java.sql.Timestamp;
import java.util.Date;

public class ThumbnailImage {
    public   String  fileMD5="";
    public   Integer  size=0;
    public byte[] fileContent=null;

    public String getFileMD5() {
        return fileMD5;
    }

    public void setFileMD5(String fileMD5) {
        this.fileMD5 = fileMD5;
    }

    public Integer getSize() {
        return size;
    }

    public void setSize(Integer size) {
        this.size = size;
    }

    public byte[] getFileContent() {
        return fileContent;
    }

    public void setFileContent(byte[] fileContent) {
        this.fileContent = fileContent;
    }
}

ThumbnailResult

package net.w2p.WebExt.vo;

public class ThumbnailResult {

    public Boolean state=true;
    public String message="";

    public ThumbnailImage small=null;
    public ThumbnailImage medium=null;
    public ThumbnailImage large=null;

    public ThumbnailImage getSmall() {
        return small;
    }

    public void setSmall(ThumbnailImage small) {
        this.small = small;
    }

    public ThumbnailImage getMedium() {
        return medium;
    }

    public void setMedium(ThumbnailImage medium) {
        this.medium = medium;
    }

    public ThumbnailImage getLarge() {
        return large;
    }

    public void setLarge(ThumbnailImage large) {
        this.large = large;
    }

    public Boolean getState() {
        return state;
    }

    public void setState(Boolean state) {
        this.state = state;
    }

    public String getMessage() {
        return message;
    }

    public void setMessage(String message) {
        this.message = message;
    }
}

GraphicImageConf

package net.w2p.WebExt.config;

import com.xxl.conf.core.annotation.XxlConf;

/****
 *
 * 图片处理相关设置
 *  1、图片尺寸有:小small,中medium中,大large,原图四种
 *  2、可设置是否打水印,设置水印位置。
 *  3、图片处理是全系统通用配置,直接用注解获取即可。
 * ****/
public class GraphicImageConf {


    private static final String VarPrefix="graphic.image.";

    /***
     * 是否保存原图
     * ***/
    @XxlConf(VarPrefix+"enableSaveOrgPic")
    public Boolean enableSaveOrgPic=false;
    /***
     *
     * 是否允许所有观众查看原图。
     * ps:只有在enableSaveOrgPic为真时,才会保存原图,这时候才有原图能开放参观。
     * ***/
    @XxlConf(VarPrefix+"enableVisitOrgPic")
    public Boolean enableVisitOrgPic=false;

    /****
     * 缩放模式。
     * ps:有以下模式:
     * KeepAspectRatio("按比例缩放",0)
     *,ScaleOnWith("按比例等宽缩放",1)
     *,ScaleOnHeight("按比例等高缩放",2)
     *,AbsoluteSize("绝对尺寸(严格按照尺寸缩放不惜变形)",3)
     *;
     * ****/
    @XxlConf(VarPrefix+"resizeMode")
    public Integer resizeMode=0;




    /***
     * 图片【small】的尺寸,字符串形式。
     * ***/
    @XxlConf(VarPrefix+"smallSize")
    public String smallSize="320,480";


    /***
     * 图片【medium】的尺寸,字符串形式。
     * ***/
    @XxlConf(VarPrefix+"mediumSize")
    public String mediumSize="400,600";


    /***
     * 图片【large】的尺寸,字符串形式。
     * ***/
    @XxlConf(VarPrefix+"largeSize")
    public String largeSize="600,900";

    /****
     * 图片压缩质量。
     * 小数。零到一之间。
     * **/
    @XxlConf(VarPrefix+"quality")
    public Float quality=1.0f;


    /***
     * 是否打水印
     * ****/
    @XxlConf(VarPrefix+"waterMark")
    public Boolean waterMark=false;

    /****
     *
     * 水印图片的文件位置。
     * 注意!水印图片可以是网址{http开头},也可以是文件的绝对路径。
     * ***/
    @XxlConf(VarPrefix+"waterMarkPath")
    public String waterMarkPath="";

    /***
     * 水印位置
     BottomRight("右下",0)
     ,BottomLeft("左下",1)
     ,TopLeft("左上",2)
     ,TopRight("右上",3)
     ,CENTER("正中心",4)
     ,CenterLeft("中间左侧",5)
     ,CenterRight("中间右侧",6)
     * ***/
    @XxlConf(VarPrefix+"waterMarkPos")
    public Integer waterMarkPos=0;



    /***
     * 水印的透明度,0到1之间,小数。
     * ***/
    @XxlConf(VarPrefix+"waterMarkOpacity")
    public Float waterMarkOpacity=1.0f;



    public Boolean getEnableSaveOrgPic() {
        return enableSaveOrgPic;
    }

    public void setEnableSaveOrgPic(Boolean enableSaveOrgPic) {
        this.enableSaveOrgPic = enableSaveOrgPic;
    }

    public Boolean getEnableVisitOrgPic() {
        return enableVisitOrgPic;
    }

    public void setEnableVisitOrgPic(Boolean enableVisitOrgPic) {
        this.enableVisitOrgPic = enableVisitOrgPic;
    }

    public Integer getResizeMode() {
        return resizeMode;
    }

    public void setResizeMode(Integer resizeMode) {
        this.resizeMode = resizeMode;
    }

    public String getSmallSize() {
        return smallSize;
    }

    public void setSmallSize(String smallSize) {
        this.smallSize = smallSize;
    }

    public String getMediumSize() {
        return mediumSize;
    }

    public void setMediumSize(String mediumSize) {
        this.mediumSize = mediumSize;
    }

    public String getLargeSize() {
        return largeSize;
    }

    public void setLargeSize(String largeSize) {
        this.largeSize = largeSize;
    }



    public Boolean getWaterMark() {
        return waterMark;
    }

    public void setWaterMark(Boolean waterMark) {
        this.waterMark = waterMark;
    }

    public String getWaterMarkPath() {
        return waterMarkPath;
    }

    public void setWaterMarkPath(String waterMarkPath) {
        this.waterMarkPath = waterMarkPath;
    }

    public Float getWaterMarkOpacity() {
        return waterMarkOpacity;
    }

    public void setWaterMarkOpacity(Float waterMarkOpacity) {
        this.waterMarkOpacity = waterMarkOpacity;
    }

    public Float getQuality() {
        return quality;
    }

    public void setQuality(Float quality) {
        this.quality = quality;
    }
}

GraphicImagePlugin

package net.w2p.WebExt.Plugins;

import net.coobird.thumbnailator.Thumbnails;
import net.coobird.thumbnailator.geometry.Position;
import net.coobird.thumbnailator.geometry.Positions;
import net.w2p.Shared.common.ValidateUtils;
import net.w2p.Shared.common.WebTools;
import net.w2p.Shared.common.files.FileType;
import net.w2p.Shared.common.files.FileTypeJudge;
import net.w2p.Shared.path.ClassPathHelper;
import net.w2p.Shared.path.WebRoot;
import net.w2p.WebExt.config.GraphicImageConf;
import net.w2p.WebExt.dict.ResizeMode;
import net.w2p.WebExt.dict.WaterMarkPos;
import net.w2p.WebExt.vo.ThumbnailImage;
import net.w2p.WebExt.vo.ThumbnailResult;
import org.apache.commons.io.FileUtils;

import javax.imageio.ImageIO;
import java.awt.image.BufferedImage;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.net.URL;
import java.util.ArrayList;

/***
 *
 * 注意,当前插件要用到CryptoPlugin,因为要算文件的md5值。
 *
 * ***/
public class GraphicImagePlugin {
    private GraphicImageConf conf=null;
    private CryptoPlugin cryptoPlugin=null;
    private BufferedImage logoImg=null;
    private String waterMarkLastPath="";//--将上次的水印文件路径缓存,假如不一致的话就要重新读取水印文件,缓存到内存中去。
    public GraphicImagePlugin(GraphicImageConf conf,CryptoPlugin cryptoPlugin){
        this.conf=conf;
        this.cryptoPlugin=cryptoPlugin;
    }

    private class ImgSize{
        public int w=0;
        public int h=0;

        public int getW() {
            return w;
        }

        public void setW(int w) {
            this.w = w;
        }

        public int getH() {
            return h;
        }

        public void setH(int h) {
            this.h = h;
        }
    }
    private ImgSize parse2Size(String str) throws Exception{
        String[] arr_size=str.split(",");
        ImgSize imgSize=new ImgSize();
        imgSize.h=Integer.parseInt(arr_size[1]);
        imgSize.w=Integer.parseInt(arr_size[0]);
        return imgSize;
    }

    public ThumbnailResult handle(byte[] originImageContent) throws Exception {

        Boolean isLogoPathUrl=false;
        URL logoUrl=null;
        File logoFile=null;

        if(conf.waterMark){
            if(conf.waterMarkPath.trim().toLowerCase().indexOf("http")==0){
                isLogoPathUrl=true;
                logoUrl=new URL(conf.waterMarkPath.trim());
            }
            else{
                isLogoPathUrl=false;
                logoFile=new File(conf.waterMarkPath.trim());
            }
        }

        if(this.conf.waterMark){
            if(logoImg==null||!waterMarkLastPath.equals(conf.waterMarkPath)){
                waterMarkLastPath=conf.waterMarkPath;
                if(isLogoPathUrl){
                    logoImg=ImageIO.read(logoUrl);
                }
                else{
                    logoImg=ImageIO.read(logoFile);
                }
            }

        }
        ResizeMode resizeMode=ResizeMode.getTarget(conf.resizeMode);
        WaterMarkPos pos=WaterMarkPos.getTarget(conf.waterMarkPos);

        ArrayList<ImgSize> sizeItems=new ArrayList<>();
        sizeItems.add(parse2Size(conf.smallSize));
        sizeItems.add(parse2Size(conf.mediumSize));
        sizeItems.add(parse2Size(conf.largeSize));

        ArrayList<ThumbnailImage> imgList=new ArrayList<>();
        ThumbnailImage tmpImgInfo=null;
        Thumbnails.Builder<BufferedImage> tmpBuilder=null;


        BufferedImage orgImg=null;
        ByteArrayOutputStream bout = null;

        {
            ByteArrayInputStream in = new ByteArrayInputStream(originImageContent);    //将b作为输入流;
            orgImg = ImageIO.read(in);
            in.close();
        }
        for(ImgSize sizeItem:sizeItems){


            tmpImgInfo=new ThumbnailImage();
            tmpBuilder = Thumbnails.of(orgImg);
            switch (resizeMode){
                case KeepAspectRatio:
                    tmpBuilder.size(sizeItem.w,sizeItem.h);
                break;
                case ScaleOnWith:
                    tmpBuilder.width(sizeItem.w);
                break;
                case ScaleOnHeight:
                    tmpBuilder.height(sizeItem.h);
                break;
                case AbsoluteSize:
                    tmpBuilder.size(sizeItem.w,sizeItem.h).keepAspectRatio(false);
                default:
                    throw new Exception("缩放模式异常,无法确认缩放模式!");

            }
            if(conf.waterMark){

                //--打水印
                switch(pos){
                    case BottomRight:tmpBuilder.watermark(Positions.BOTTOM_RIGHT,logoImg,conf.waterMarkOpacity);break;
                    case BottomLeft:tmpBuilder.watermark(Positions.BOTTOM_LEFT,logoImg,conf.waterMarkOpacity);break;
                    case TopLeft:tmpBuilder.watermark(Positions.TOP_LEFT,logoImg,conf.waterMarkOpacity);break;
                    case TopRight:tmpBuilder.watermark(Positions.TOP_RIGHT,logoImg,conf.waterMarkOpacity);break;
                    case CENTER:tmpBuilder.watermark(Positions.CENTER,logoImg,conf.waterMarkOpacity);break;
                    case CenterLeft:tmpBuilder.watermark(Positions.CENTER_LEFT,logoImg,conf.waterMarkOpacity);break;
                    case CenterRight:tmpBuilder.watermark(Positions.CENTER_RIGHT,logoImg,conf.waterMarkOpacity);break;
                    default:throw new Exception("水印位置异常,系统无法识别水印位置!代号错误!");
                }
            }
            bout=new ByteArrayOutputStream();
            tmpBuilder.outputQuality(conf.quality);

            FileType fileType=FileTypeJudge.getType(originImageContent);


            //--现在来判断输出格式了。
            tmpBuilder.outputFormat(fileType.getImageType());
            tmpBuilder.toOutputStream(bout);
            byte[] resBytes=bout.toByteArray();
            bout.close();
            tmpImgInfo.fileContent=resBytes;
            tmpImgInfo.size=resBytes.length;
            tmpImgInfo.fileMD5=cryptoPlugin.md5(resBytes);

            imgList.add(tmpImgInfo);
        }

        ThumbnailResult result=new ThumbnailResult();
        result.small=imgList.get(0);
        result.medium=imgList.get(1);
        result.large=imgList.get(2);
        result.setState(true);
        result.setMessage("");
        return result;
    }




}

初始化配置中心的数据

请执行


-- 图片处理样式为全系统通用。
create or replace function "initGraphicImageConfig"(
in envName varchar
)
returns varchar
as $BODY$
  declare _defaultValues varchar;
  declare _envName varchar;
  declare _appname varchar;
  declare _prefix varchar;
  declare strArrays varchar[];

  declare arrItemLv1 varchar;
  declare tempArrSubItem varchar;
  declare valArrs varchar[];

  declare item_attr varchar;
  declare item_title varchar;
  declare item_val varchar;
  begin

    if envName <> 'test' and envName<> 'ppe' and envName<> 'product' then

      raise notice '环境变量异常,只能为test、ppe以及product其中一个。';
      return '环境变量异常,只能为test、ppe以及product其中一个。';

    end if;

    _appname:='graphic';
    _prefix:=concat(_appname,'.image.','');

  _defaultValues:=
      'enableSaveOrgPic->是否保存原图->false$$' ||
      'enableVisitOrgPic->是否允许所有观众查看原图。\n\r ps:只有在enableSaveOrgPic为真时,才会保存原图,这时候才有原图能开放参观。->false$$' ||
      'resizeMode->缩放模式。
     * ps:有以下模式:
     * KeepAspectRatio("按比例缩放",0)
     *,ScaleOnWith("按比例等宽缩放",1)
     *,ScaleOnHeight("按比例等高缩放",2)
     *,AbsoluteSize("绝对尺寸(严格按照尺寸缩放不惜变形)",3)->0$$' ||
     'smallSize->图片【small】的尺寸,字符串形式,默认为:320,480->320,480$$' ||
     'mediumSize->图片【medium】的尺寸,字符串形式,默认为:400,600->400,600$$' ||
     'largeSize->图片【large】的尺寸,字符串形式,默认为:600,900->600,900$$' ||
     'quality->图片压缩质量。小数。零到一之间。->1.0$$' ||
     'waterMark->是否打水印,默认false->false$$' ||
     'waterMarkPath->水印图片的文件位置。
     * 注意!水印图片可以是网址{http开头},也可以是文件的绝对路径。->$$' ||
     'waterMarkOpacity->水印的透明度,0到1之间,小数。->1.0$$' ||
     'waterMarkPos->水印位置
     BottomRight("右下",0)
     ,BottomLeft("左下",1)
     ,TopLeft("左上",2)
     ,TopRight("右上",3)
     ,CENTER("正中心",4)
     ,CenterLeft("中间左侧",5)
     ,CenterRight("中间右侧",6)->0$$' ||

''
    ;

  strArrays:=string_to_array(_defaultValues,'$$');
  _envName:=envName;

--   fastdfs.connect_timeout_in_seconds = 5
--     fastdfs.network_timeout_in_seconds = 30
--     fastdfs.charset = UTF-8
--     fastdfs.http_anti_steal_token = false
--     fastdfs.http_secret_key = FastDFS1234567890
--     fastdfs.http_tracker_http_port = 80
--                                        #fastdfs.tracker_servers = tw-server:22122,10.0.11.202:22122,10.0.11.203:22122
--     fastdfs.tracker_servers = localhost:22122
--     fastdfs.visit_url = http://localhost/

--   env     varchar(100) not null,
--     key     varchar(200) not null,
--     appname varchar(100) not null,
--     title   varchar(100) not null,
--     value   varchar(2000) default NULL::character varying,

insert into xxl_conf_project (appname, title) values (_appname,'图片处理配置') on conflict ("appname") do nothing;
  <<loop4BigArray>>
    foreach arrItemLv1 in array  strArrays

      loop

        if char_length(arrItemLv1) < 1 then
          raise notice '空字符串无须处理';
          continue ;
        end if;
        valArrs:=string_to_array(arrItemLv1,'->');
        item_attr:=valArrs[1];
        item_title:=valArrs[2];
        item_val:=valArrs[3];

      raise notice '属性名称:%,描述:%,当前值:%',item_attr,item_title,item_val;
      raise notice '开始添加记录';
        insert into xxl_conf_node("env","key","appname","title","value")
        values (_envName,concat(_prefix,item_attr),_appname,item_title,item_val)
        on conflict ("env","key") do nothing ;

    end loop loop4BigArray;


    return envName||'环境下的'||_appName||'配置成功';
  end;

  $BODY$ language plpgsql volatile ;
-- 记住执行下面方法分别添加三个环境下的默认数据。
-- select "initGraphicImageConfig"('test');
-- select "initGraphicImageConfig"('ppe');
-- select "initGraphicImageConfig"('product');

执行:

select "initGraphicImageConfig"('test');
select "initGraphicImageConfig"('ppe');
select "initGraphicImageConfig"('product');

使用java代码整合到spring中进行设置

在FileServerWebApp中整合。
注意,因为要用到crypto插件,所以,也要配置crypto插件的:

扫描二维码关注公众号,回复: 5140075 查看本文章

BeanConfiguration下面添加:

package net.w2p.local.plugins.BeanConfiguration;

import com.xxl.conf.core.XxlConfClient;
import net.w2p.WebExt.Plugins.CryptoPlugin;
import net.w2p.WebExt.config.CryptoConf;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
/***
 *
 * 系统加解密插件配置
 * ***/
@Configuration
public class CryptoConfiguration {
    @Bean(name="cryptoConf")
    public CryptoConf cryptoConf(){
        CryptoConf conf=new CryptoConf();
        return conf;
    }

    @Bean(name="cryptoPlugin")
    @Autowired
    public CryptoPlugin cryptoPlugin(@Qualifier("cryptoConf") CryptoConf conf){
        try {
            CryptoPlugin plugin = new CryptoPlugin(conf);
            return plugin;
        }
        catch (Exception ed){
            ed.printStackTrace();
            return null;
        }
    }
}

package net.w2p.local.plugins.BeanConfiguration;

import com.xxl.conf.core.XxlConfClient;
import com.xxl.conf.core.listener.XxlConfListener;
import net.w2p.Shared.common.WebTools;
import net.w2p.WebExt.Plugins.CryptoPlugin;
import net.w2p.WebExt.Plugins.DayuSmsPlugin;
import net.w2p.WebExt.Plugins.GraphicImagePlugin;
import net.w2p.WebExt.config.DaYuConf;
import net.w2p.WebExt.config.GraphicImageConf;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
/****
 *
 * 整合阿里大鱼短信服务
 *
 * ****/
@Configuration
public class GraphicImageConfiguration {
    @Bean(name="imgConf")
    public GraphicImageConf imgConf(){

        final GraphicImageConf conf=new GraphicImageConf();

        return conf;
    }

    @Bean(name="imagePlugin")
    @Autowired
    public GraphicImagePlugin imagePlugin(@Qualifier("imgConf")GraphicImageConf conf,
                                          @Qualifier("cryptoPlugin")CryptoPlugin cryptoPlugin){
        try {
            GraphicImagePlugin plugin = new GraphicImagePlugin(conf,cryptoPlugin);
            return plugin;
        }
        catch (Exception ed){
            ed.printStackTrace();
            return null;
        }
    }
}

进行测试

图片准备

注意,这次的测试没那么简单,需要配置一下测试环境,譬如,配置水印文件位置等等。下面说明一下。

在这里插入图片描述
有测试用到的图片:
在这里插入图片描述
logo.png为水印,而demo2.jpg是测试用图片:
在这里插入图片描述

配置中心配置水印

如下图:
开启水印
在这里插入图片描述

设置水印地址
在这里插入图片描述

编写测试代码

测试代码如下:

package other;

import com.alibaba.fastjson.JSONObject;
import main.BaseTest;
import net.w2p.Shared.common.OpResult;
import net.w2p.Shared.path.WebRoot;
import net.w2p.WebExt.Plugins.DayuSmsPlugin;
import net.w2p.WebExt.Plugins.GraphicImagePlugin;
import net.w2p.WebExt.vo.ThumbnailResult;
import org.apache.commons.io.FileUtils;
import org.junit.Test;
import org.springframework.beans.factory.annotation.Autowired;

import javax.imageio.ImageIO;
import java.awt.image.BufferedImage;
import java.io.File;
import java.util.ArrayList;
import java.util.HashMap;

public class ExtComponentTest extends BaseTest {



    @Autowired
    GraphicImagePlugin imagePlugin;

    @Test
    public void testImagePlugin() throws Exception{
        String demoPic="/home/too-white/图片/demos/demo2.jpg";
        byte[] fileContent=FileUtils.readFileToByteArray(new File(demoPic));

        ThumbnailResult result=imagePlugin.handle(fileContent);
        ArrayList<byte[]> resContentList=new ArrayList<>();
        resContentList.add(result.small.fileContent);
        resContentList.add(result.medium.fileContent);
        resContentList.add(result.large.fileContent);

        ArrayList<File> outputFiles=new ArrayList<>();
        outputFiles.add(new File("/home/too-white/图片/demos/small.jpg"));
        outputFiles.add(new File("/home/too-white/图片/demos/medium.jpg"));
        outputFiles.add(new File("/home/too-white/图片/demos/large.jpg"));

        for(int i=0;i<3 ;i++){
            File tmpFile=outputFiles.get(i);
            if(!tmpFile.exists()){
                tmpFile.createNewFile();
            }
            FileUtils.writeByteArrayToFile(tmpFile,resContentList.get(i));
        }


    }
}

执行结果

在这里插入图片描述

查看目标目录:
在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

图片处理插件整合成功。

结语

图片处理一直是web项目的一个难点。
一个稳定的插件不经过长时间运行是不会完善的。估计这个插件有的是bug。

猜你喜欢

转载自blog.csdn.net/cdnight/article/details/86710581