获取普通图片和svg图片属性,并实现单张下载和批量下载,svg转png下载,图片大小压缩

1. 获取图片属性(分辨率,大小,颜色模式,后缀名)

@Override
    public PictureAttributeVo saveUpload(MultipartFile file) throws Exception {
        if (file == null) {
            throw new Exception("文件有误");
        }
        String filename = file.getOriginalFilename();
        //图标大小,处理为b
        long size = file.getSize();
        //根据后缀判断图标类型
        String type = FilenameUtils.getExtension(file.getOriginalFilename()).toUpperCase();
        BufferedImage read = ImageIO.read((FileInputStream) file.getInputStream());
        //获取图片颜色模式,RGB,CMYK等,具体可点进去getType自己看
        //这个网上找了好久没找到,应该可以解决一些人的问题
        ColorModel colorModel = read.getColorModel();
        int typeCode = colorModel.getColorSpace().getType();
        String mode = "";
        mode = PictureUtils.getColorModel(typeCode);
        if (!"JPG".equals(type) && !"PNG".equals(type) && !"GIF".equals(type) && !"TIF".equals(type) && !"BMP".equals(type) && !"JPEG".equals(type)) {
            throw new Exception("图片格式有误");
        }
        //获取图片base64
        byte[] bytes = file.getBytes();
        String base = new String(Base64.encodeBase64(bytes));
        String thumbnailPictureCode = new String(Base64.encodeBase64(bytes));
        //获取图标宽高
        BufferedImage sourceImg = ImageIO.read((FileInputStream) file.getInputStream());
        int width = sourceImg.getWidth();
        int height = sourceImg.getHeight();
        //拼接出分辨率
        String resolutionRatio = width + "x" + height + "px";
    }

2. svg图片只有分辨率值得一说,而且也没有颜色模式

public static String getSvgWidthAndHeight(String svgURI) throws IOException {
        File file = new File(svgURI);
        String parser = XMLResourceDescriptor.getXMLParserClassName();
        SAXSVGDocumentFactory f = new SAXSVGDocumentFactory(parser);
        Document doc = f.createDocument(file.toURI().toString());
        Element element = doc.getDocumentElement();
        String viewBox = element.getAttribute("viewBox");
        String width = viewBox.split(" ")[2];
        String height = viewBox.split(" ")[3];
        //分辨率
        String resolutionRatio = width+"x"+height+"px";
        //这里只能先在服务器生成一个文件获取分辨率,所以要删除,图片可以用流读取
        file.delete();
        return resolutionRatio;
    }

3. 图片大小压缩

/**
     * 根据指定大小压缩图片
     *
     * @param imageBytes  源图片字节数组
     * @param fileSize 指定图片大小,单位kb
     * @return 压缩质量后的图片字节数组
     */
public static byte[] compressPicture(byte[] imageBytes, long fileSize) {
        if (imageBytes == null || imageBytes.length <= 0 || imageBytes.length < fileSize * 1024) {
            return imageBytes;
        }
        long srcSize = imageBytes.length;
        double accuracy = getAccuracy(srcSize / 1024);
        try {
            while (imageBytes.length > fileSize * 1024) {
                ByteArrayInputStream inputStream = new ByteArrayInputStream(imageBytes);
                ByteArrayOutputStream outputStream = new ByteArrayOutputStream(imageBytes.length);
                Thumbnails.of(inputStream)
                        .scale(accuracy)
                        .outputQuality(accuracy)
                        .toOutputStream(outputStream);
                imageBytes = outputStream.toByteArray();
            }
        } catch (Exception e) {
            logger.error("图片压缩失败", e);
        }
        return imageBytes;
    }

4. svg转png格式下载

因为前端有个功能是修改svg颜色,所以我需要先传给他svg代码,很简单,把svg图片导出成txt格式用流读取即可,让前端去掉字符串中的"\"这个转义字符.

这里svgcode是svg代码,是前端修改完svg图片颜色传回来的

@Override
    public void downloadPngIcon(HttpServletRequest request, HttpServletResponse response, SvgVo svgVo) throws Exception {
        Integer id = svgVo.getId();
        String svgCode = svgVo.getSvgCode();
        if (id == null || iconAttributeMapper.selectById(id) == null) {
            throw new Exception("图标不存在");
        }
        //获取图标名和后缀
        TUedIconAttribute tUedIconAttribute = iconAttributeMapper.selectById(id);
        //更新图标下载量
        tUedIconAttribute.setDownloadCount(tUedIconAttribute.getDownloadCount() + 1);
        iconAttributeMapper.updateById(tUedIconAttribute);
        String imageName = tUedIconAttribute.getImageName();
        Integer imageId = tUedIconAttribute.getImageId();
        TUedPicture tUedPicture = pictureMapper.selectById(imageId);
        String pictureCode = tUedPicture.getPictureCode();
        String format = tUedPicture.getFormat().toLowerCase();
        String fileName = imageName + ".png";

        String agent = request.getHeader("User-Agent").toUpperCase();
        // 判断浏览器代理并分别设置响应给浏览器的编码格式
        String finalFileName = null;
        if (agent.contains("MSIE") || ((agent.indexOf("RV") != -1) && (agent.indexOf("FIREFOX") == -1))) {
            finalFileName = URLEncoder.encode(fileName, "UTF-8");
        } else {
            finalFileName = new String(fileName.getBytes("UTF-8"), "ISO8859-1");
        }

        //设置响应
        response.setContentType("application/x-download");// 告知浏览器下载文件,而不是直接打开,浏览器默认为打开
        response.setHeader("Content-Disposition", "attachment;filename=\""
                + finalFileName + "\"");// 下载文件的名称

        BASE64Decoder decoder = new BASE64Decoder();
        ServletOutputStream outputStream = response.getOutputStream();
        //如果是svg图片下载成png图片
        if ("svg".equals(format)) {
            try {
                String svgPicture = "D:\\" + UUID.randomUUID().toString() + ".svg";
                if (svgCode != null) {
                    FileOutputStream fos = null;
                    try {
                        byte[] svgCodeBytes = svgCode.getBytes();
                        fos = new FileOutputStream(new File(svgPicture));
                        fos.write(svgCodeBytes);
                    } catch (IOException e) {
                        throw new Exception();
                    } finally {
                    	fos.flush();
                        fos.close();
                    }
                    String newSvgCode = PictureUtils.getImgStr(svgPicture);
                    new File(svgPicture).delete();
                    byte[] bytes = decoder.decodeBuffer(newSvgCode);
                    PNGTranscoder t = new PNGTranscoder();
                    TranscoderInput input = new TranscoderInput(new ByteArrayInputStream(bytes));
                    TranscoderOutput output = new TranscoderOutput(outputStream);
                    t.transcode(input, output);
                    outputStream.flush();
                }
            } catch (Exception e) {
                throw new Exception();
            } finally {
                if (outputStream != null) {
                    try {
                        outputStream.close();
                    } catch (IOException e) {
                        log.info("下载图标失败",e);
                    }
                }
            }
        } else if ("png".equals(format)) {
            try {
                // Base64解码
                byte[] b = decoder.decodeBuffer(pictureCode);
                for (int i = 0; i < b.length; ++i) {
                    if (b[i] < 0) {// 调整异常数据
                        b[i] += 256;
                    }
                }
                outputStream.write(b);
                outputStream.flush();
            } catch (Exception e) {
                throw new Exception();
            } finally {
                if (outputStream != null) {
                    try {
                        outputStream.close();
                    } catch (IOException e) {
                        log.info("下载图标失败",e);
                    }
                }
            }
        }
    }

5. 单张图片下载

@Override
    public void pictureDownload(HttpServletRequest request, HttpServletResponse response, Integer id) throws Exception {
        // 得到要下载的文件名
        TUedPictureAttribute tUedPictureAttribute = pictureAttributeMapper.selectById(id);
        //下载量加1
        tUedPictureAttribute.setDownloadCount(tUedPictureAttribute.getDownloadCount() + 1);
        pictureAttributeMapper.updateById(tUedPictureAttribute);
        Integer imageId = tUedPictureAttribute.getImageId();
        String imageName = tUedPictureAttribute.getImageName();
        TUedPicture tUedPicture = pictureMapper.selectById(imageId);
        String pictureCode = tUedPicture.getPictureCode();
        String format = tUedPicture.getFormat();
        String fileName = imageName + "." + format.toLowerCase();

        // 处理文件名
        // 设置响应头,控制浏览器下载该文件
        //解决中文文件名乱码
        String userAgent = request.getHeader("User-Agent");
        //IE内核浏览器
        if (userAgent.contains("MSIE") || userAgent.contains("Trident")) {
            fileName = java.net.URLEncoder.encode(fileName, "UTF-8");
        } else {
            // 非IE浏览器的处理:
            fileName = new String(fileName.getBytes("utf-8"), "iso-8859-1");
        }
        //设置文件下载头
        response.setHeader("Content-disposition", String.format("attachment; filename=\"%s\"", fileName));
        //设置文件ContentType类型,这样设置,会自动判断下载文件类型
        response.setContentType("multipart/form-data");
        response.setCharacterEncoding("iso-8859-1");
        // 读取要下载的文件,保存到文件输入流
        BASE64Decoder decoder = new BASE64Decoder();
        OutputStream out = response.getOutputStream();
        try {
            // Base64解码
            byte[] b = decoder.decodeBuffer(pictureCode);
            for (int i = 0; i < b.length; ++i) {
                if (b[i] < 0) {// 调整异常数据
                    b[i] += 256;
                }
            }
            out.write(b);
        } catch (Exception e) {
            throw new Exception();
        }finally {
            out.close();
        }
    }

6. 整套图标下载

@Override
    public void downloadAllIcon(HttpServletRequest request, HttpServletResponse response, Integer id) throws Exception {
        if (id == null || packageMapper.selectById(id) == null) {
            throw new Exception("图标库信息有误");
        }
        TUedIconPackage tUedIconPackage = packageMapper.selectById(id);
        //更新图标库下载量
        tUedIconPackage.setDownloadCount(tUedIconPackage.getDownloadCount() + 1);
        packageMapper.updateById(tUedIconPackage);
        String packageName = tUedIconPackage.getPackageName();

        // path 压缩文件初始设置
        String fileZip = packageName + ".zip"; // 拼接zip文件,之后下载下来的压缩文件的名字
        String filePath = "D:\\" + fileZip;// 之后用来生成zip文件//data//ued1//image

        List<IconVo> iconVos = pictureMapper.selectIconsByPackageId(id, null);
        for (IconVo iconVo : iconVos) {
            Integer iconId = iconVo.getIconId();
            TUedIconAttribute tUedIconAttribute = iconAttributeMapper.selectById(iconId);
            tUedIconAttribute.setDownloadCount(tUedIconAttribute.getDownloadCount() + 1);
            iconAttributeMapper.updateById(tUedIconAttribute);
        }
        //处理图标重名问题
        ArrayList<String> list = new ArrayList<>();
        HashSet<String> arrayList = new HashSet<>();
        for (IconVo iconVo : iconVos) {
            list.add(iconVo.getIconName());
            arrayList.add(iconVo.getIconName());
        }
        for (String s : arrayList) {
            Integer count =0;
            for (int i = 0; i < list.size(); i++) {
                if (list.get(i).equals(s)){
                    count++;
                    if (count!=1){
                        list.set(i,list.get(i)+"("+(count-1)+")");
                    }
                }
            }
            count =0;
        }
        for (int i = 0; i < iconVos.size(); i++) {
            IconVo iconVo = iconVos.get(i);
            iconVo.setIconName(list.get(i));
        }
        // 创建临时压缩文件
        BufferedOutputStream bos = new BufferedOutputStream(new FileOutputStream(filePath));
        ZipOutputStream zos = new ZipOutputStream(bos);
        try {
            ZipEntry ze = null;
            BASE64Decoder decoder = new BASE64Decoder();
            for (int i = 0; i < iconVos.size(); i++) {// 将所有需要下载的文件都写入临时zip文件
                // Base64解码
                byte[] b = decoder.decodeBuffer(iconVos.get(i).getPictureCode());
                for (int j = 0; j < b.length; ++j) {
                    if (b[i] < 0) {// 调整异常数据
                        b[i] += 256;
                    }
                }
                String iconName = iconVos.get(i).getIconName();
                String format = iconVos.get(i).getFormat();
                ze = new ZipEntry(iconName + "." + format.toLowerCase());
                zos.putNextEntry(ze);
                zos.write(b);
            }
        } catch (IOException e) {
            throw new Exception("临时压缩文件生成失败");
        }finally {
            zos.flush();
            zos.close();
        }
        // 以上,临时压缩文件创建完成

        // 进行浏览器下载
        // 获得浏览器代理信息
        String agent = request.getHeader("User-Agent").toUpperCase();
        // 判断浏览器代理并分别设置响应给浏览器的编码格式
        String finalFileName = null;
        if (agent.contains("MSIE") || ((agent.indexOf("RV") != -1) && (agent.indexOf("FIREFOX") == -1))) {
            finalFileName = URLEncoder.encode(fileZip, "UTF-8");
        } else {
            finalFileName = new String(fileZip.getBytes("UTF-8"), "ISO8859-1");
        }
        response.setContentType("application/x-download");// 告知浏览器下载文件,而不是直接打开,浏览器默认为打开
        response.setHeader("Content-disposition", String.format("attachment; filename=\"%s\"", finalFileName));// 下载文件的名称
        //输出到本地
        ServletOutputStream servletOutputStream = response.getOutputStream();
        DataOutputStream temps = new DataOutputStream(servletOutputStream);

        DataInputStream in = new DataInputStream(new FileInputStream(filePath));// 浏览器下载临时文件的路径
        byte[] b = new byte[2048];
        File reportZip = new File(filePath);// 之后用来删除临时压缩文件
        try {
            while ((in.read(b)) != -1) {
                temps.write(b);
            }
            temps.flush();
        } catch (Exception e) {
            log.info("下载压缩包失败",e);
        } finally {
            if (temps != null) {
                temps.close();
            }
            if (in != null) {
                in.close();
            }
            if (reportZip != null) {
                reportZip.delete();// 删除服务器本地产生的临时压缩文件
            }
            servletOutputStream.close();
        }
    }
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值