Java 读取网络图片存储到本地并生成缩略图

 更新时间:2021年05月27日 14:35:16   作者:盛夏温暖流年  
用Java做开发经常需要处理图片。本文就来看一下如何保存图片到本地并生成缩略图

之前使用 Python 爬虫抓取电影网站信息作为自己网站的数据来源,其中包含的图片都是网络图片,会存在这样一个问题:

当原始网站访问速度比较慢时,网站图片加载时间也会变得很慢,而且如果原始网站挂了,图片就直接访问不到了。

此时的用户体验就很不好,所以对此进行了优化:

每次后端启动时会默认开启任务先将未转换的网络图片存储到本地,再把网页中图片列表改为访问本地图片,这样就解决了加载慢的问题,也降低了和原始网站的耦合性,具体步骤如下:

1.创建用于保存图片的文件夹

我的保存路径:F:\images

2.新建 createLocalImage 类用于图片转换

package com.cn.beauty.task;

import java.io.BufferedInputStream;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.net.HttpURLConnection;
import java.net.URL;

public class createLocalImage {
	// 需要保存到本地的根路径
    private static String basePath = "F:/";

    public static void main(String[] args) {
    	// 网页图片路径
        String destUrl = "http://5b0988e595225.cdn.sohucs.com/images/20200215/349bb3cb88b744dcb67f37dba2f71abf.jpeg";
        String filePath = createLocalImageMethod(destUrl);
        System.out.println("生成的相对文件路径为" + filePath);
    }

    private static String createLocalImageMethod(String destUrl) {
        FileOutputStream fos = null;
        BufferedInputStream bis = null;
        HttpURLConnection httpUrl = null;
        URL url = null;
        int BUFFER_SIZE = 1024;
        byte[] buf = new byte[BUFFER_SIZE];
        int size = 0;
        String filePath = "";
        try {
            System.out.println("原始图片URL为:" + destUrl);
            String[] fileNameArray = destUrl.split("\\/");
            if (fileNameArray.length > 1) {
                String fileName = fileNameArray[fileNameArray.length - 1];
                filePath = "images/" + fileName;
                File file = new File(basePath + filePath);
                if (!file.exists()) {
                    url = new URL(destUrl);
                    httpUrl = (HttpURLConnection) url.openConnection();
                    httpUrl.connect();
                    bis = new BufferedInputStream(httpUrl.getInputStream());
                    fos = new FileOutputStream(basePath + filePath);
                    while ((size = bis.read(buf)) != -1) {
                        fos.write(buf, 0, size);
                    }
                    fos.flush();
                }
                // 后续对图片进行缩略图处理,见后面代码
            }
        } catch (IOException e) {
            e.printStackTrace();
        } catch (ClassCastException e) {
            e.printStackTrace();
        } finally {
            try {
                fos.close();
                bis.close();
                httpUrl.disconnect();
            } catch (IOException e) {
            } catch (NullPointerException e) {
            }
        }
        return filePath;
    }
}

运行后发现图片已经成功生成:

3.生成缩略图

使用工具类Thumbnails

如果是图片列表的展示,原始图片过大还是会影响加载速度,此时我们可以将图片处理为缩略图进行显示。

我们使用了一个很强大的图片处理工具类:Thumbnails,它支持的功能包括:

  • 按指定大小进行缩放;
  • 按照比例进行缩放;
  • 不按照比例,指定大小进行缩放;
  • 旋转,水印,裁剪;
  • 转化图像格式;
  • 输出到 OutputStream;
  • 输出到 BufferedImage;

这里的需求比较简单,只用到了按指定大小进行缩放的功能。

引入对应 jar 包:

<dependency>
      <groupId>net.coobird</groupId>
      <artifactId>thumbnailator</artifactId>
      <version>0.4.8</version>
</dependency>

在 createLocalImage 方法中添加缩略图生成的代码实现:

    String thumbName = fileName.split("\\.")[0] + "_thumb." + fileName.split("\\.")[1];
    String thumbPath = basePath + filePath.replace(fileName, thumbName);
    //将要转换出的小图文件
    File fo = new File(thumbPath);
    if (fo.exists()) {
         return thumbPath;
    }
    // 第一个参数是原始图片的路径,第二个是缩略图的路径
    Thumbnails.of(basePath + filePath).size(120, 120).toFile(thumbPath);
    System.out.println("生成的缩略图路径为:" + thumbPath);

再次运行,发现缩略图已经成功生成:

另一种方法

直接将下面的代码封装成一个util即可,调用示例在main方法中,调用的地方需要引入import java.awt.image.BufferedImage;,还要确保旧文件是存在的

import java.awt.image.BufferedImage;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.util.HashMap;
import java.util.Map;
import javax.imageio.ImageIO;
import com.sun.image.codec.jpeg.JPEGCodec;
import com.sun.image.codec.jpeg.JPEGEncodeParam;
import com.sun.image.codec.jpeg.JPEGImageEncoder;
public class ResizeImage {
    public static void main(String[] args) throws IOException {
        //windows路径,linux环境下相应修改
        String outputFolder = "D:\\test\\";
        String fileName = "D:\\test\\test.jpg";
        ResizeImage r = new ResizeImage();
        int toWidth=220,toHeight=220;
        BufferedImage imageList = r.getImageList(fileName,new String[] {"jpg","png","gif"});
        r.writeHighQuality("newFile.jpg",r.zoomImage(imageList,toWidth,toHeight),outputFolder);
    }
    /**
     * @Description: 取得图片对象
     * @param 要转化的图像的文件夹,就是存放图像的文件夹路径
     * @date 2017年5月7日10:48:27
     */
    public BufferedImage zoomImage(BufferedImage im, int toWidth , int toHeight) {
        BufferedImage result = new BufferedImage(toWidth, toHeight, BufferedImage.TYPE_INT_RGB);
        result.getGraphics().drawImage(im.getScaledInstance(toWidth, toHeight, java.awt.Image.SCALE_SMOOTH), 0, 0, null);
        return result;
    }
    /**
     * @Description: 取得图片对象
     * @param 要转化的图像的文件夹,就是存放图像的文件夹路径
     * @date 2017年5月7日10:48:27
     */
    public BufferedImage getImageList(String ImgList, String[] type) throws IOException{
        Map<String,Boolean> map = new HashMap<String, Boolean>();
        for(String s : type) {
            map.put(s,true);
        }
        BufferedImage imageList = null;
        File file = null;
        file = new File(ImgList);
        try{
            if(file.length() != 0 && map.get(getExtension(file.getName())) != null ){
                imageList = javax.imageio.ImageIO.read(file);
            }
        }catch(Exception e){
            imageList = null;
        }
        return imageList;
    }
    /**
     * 把图片写到磁盘上
     * @param im
     * @param path      图片写入的文件夹地址
     * @param fileName  写入图片的名字
     * @date 2017年5月7日10:48:27
     */
    public boolean writeToDisk(BufferedImage im, String path, String fileName) {
        File f = new File(path + fileName);
        String fileType = getExtension(fileName);
        if (fileType == null)
            return false;
        try {
            ImageIO.write(im, fileType, f);
            im.flush();
            return true;
        } catch (IOException e) {
            return false;
        }
    }
    /**
     * @Description: 生成图片
     * @param String path , BufferedImage im, String fileFullPath
     * @date 2017年5月7日10:48:27
     */
    public boolean writeHighQuality(String path , BufferedImage im, String fileFullPath) throws IOException {
        FileOutputStream newimage = null;
        try {
            // 输出到文件流
            newimage = new FileOutputStream(fileFullPath+path);
            JPEGImageEncoder encoder = JPEGCodec.createJPEGEncoder(newimage);
            JPEGEncodeParam jep = JPEGCodec.getDefaultJPEGEncodeParam(im);
            // 压缩质量
            jep.setQuality(1f, true);
            encoder.encode(im, jep);
            //近JPEG编码
            newimage.close();
            return true;
        } catch (Exception e) {
            return false;
        }
    }
    /**
     * @Description: 取文件名的后缀
     * @param String fileName 格式如:cn1100000213EA_1_xnl.jpg
     * @date 2017年5月7日10:48:27
     */
    public String getExtension(String fileName) {
        try {
            return fileName.split("\\.")[fileName.split("\\.").length - 1];
        } catch (Exception e) {
            return null;
        }
    }

以上就是Java 读取网络图片存储到本地并生成缩略图的详细内容,更多关于Java 图片存储到本地并生成缩略图的资料请关注脚本之家其它相关文章!

相关文章

  • Java并发统计变量值偏差原因及解决方案

    Java并发统计变量值偏差原因及解决方案

    这篇文章主要介绍了Java并发统计变量值偏差原因及解决方案,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下
    2020-06-06
  • Java实体类中Set按照对象的某个字段对set排序

    Java实体类中Set按照对象的某个字段对set排序

    这篇文章主要介绍了Java实体类中Set按照对象的某个字段对set排序,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下
    2019-06-06
  • Java实现批量发送带附件的邮件代码

    Java实现批量发送带附件的邮件代码

    大家好,本篇文章主要讲的是Java实现批量发送带附件的邮件代码,感兴趣的同学赶快来看一看吧,对你有帮助的话记得收藏一下,方便下次浏览
    2022-01-01
  • Java 设计模式以虹猫蓝兔的故事讲解单例模式

    Java 设计模式以虹猫蓝兔的故事讲解单例模式

    单例模式(Singleton Pattern)是 Java 中最简单的设计模式之一。这种类型的设计模式属于创建型模式,它提供了一种创建对象的最佳方式
    2022-03-03
  • java如何自定义注解

    java如何自定义注解

    这篇文章主要介绍了java如何自定义注解问题,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教
    2024-02-02
  • 浅谈java面向对象(类,封装,this,构造方法)

    浅谈java面向对象(类,封装,this,构造方法)

    下面小编就为大家带来一篇浅谈java面向对象(类,封装,this,构造方法)。小编觉得挺不错的,现在就分享给大家,也给大家做个参考。一起跟随小编过来看看吧
    2017-06-06
  • Java完全二叉树的创建与四种遍历方法分析

    Java完全二叉树的创建与四种遍历方法分析

    这篇文章主要介绍了Java完全二叉树的创建与四种遍历方法,结合实例形式分析了完全二叉树的概念、定义及遍历操作相关实现技巧,并对比分析了满二叉树与完全二叉树的区别,需要的朋友可以参考下
    2017-11-11
  • response.setHeader各种用法详解

    response.setHeader各种用法详解

    本文主要介绍了response.setHeader各种用法。具有很好的参考价值,下面跟着小编一起来看下吧
    2017-03-03
  • Spring中的refresh方法分析

    Spring中的refresh方法分析

    这篇文章主要介绍了Spring中的refresh方法分析,文章围绕主题展开详细的refresh方法相关资料介绍,需要的小伙伴可以参考一下
    2022-05-05
  • 浅谈自定义注解在Spring中的应用

    浅谈自定义注解在Spring中的应用

    这篇文章主要介绍了浅谈自定义注解在Spring中的应用,具有一定借鉴价值,需要的朋友可以参考下。
    2017-12-12

最新评论