写给大忙人看的 - Java中图片压缩上传至MinIO服务器(4)

之前文章已经介绍了 MinIO 的环境搭建,已经对文件的上传下载方法,本篇文章一起与大家来学习图片压缩上传的方法

1、背景

最近客户总抱怨 APP 中图片显示较慢, 升级服务器带宽又没有多的预算。查看原因,是因为现在大家都是用的智能手机拍照,拍出来的照片小则 2-3 M,大则十几 M,所以导致图片显示较慢。思考再三,决定将图片进行压缩再上传图片服务器来解决图片显示慢的问题

2、开发准备

1、引入 maven 依赖

<!-- 图片压缩 -->
<dependency>
    <groupId>net.coobird</groupId>
    <artifactId>thumbnailator</artifactId>
    <version>0.4.8</version>
</dependency>

本次我们选择了使用 thumbnailator 来作为压缩的工具

2、thumbnailator 简介

  • Thumbnailator 是一个用来生成图像缩略图的 Java 类库,通过很简单的代码即可生成图片缩略图,也可直接对一整个目录的图片生成缩略图
  • 支持图片缩放,区域裁剪,水印,旋转,保持比例

3、压缩准备

  • 判断是否是图片方法
/**
 * 判断文件是否为图片
 */
public boolean isPicture(String imgName) {
    boolean flag = false;
    if (StringUtils.isBlank(imgName)) {
        return false;
    }
    String[] arr = {"bmp", "dib", "gif", "jfif", "jpe", "jpeg", "jpg", "png", "tif", "tiff", "ico"};
    for (String item : arr) {
        if (item.equals(imgName)) {
            flag = true;
            break;
        }
    }
    return flag;
}

3、压缩上传

/**
 * 上传文件
 *
 * @param file 文件
 * @return
 */
public JSONObject uploadFile(MultipartFile file) throws Exception {
    JSONObject res = new JSONObject();
    res.put("code", 500);
    // 判断上传文件是否为空
    if (null == file || 0 == file.getSize()) {
        res.put("msg", "上传文件不能为空");
        return res;
    }
    // 判断存储桶是否存在
    if (!client.bucketExists("test")) {
        client.makeBucket("test");
    }
    // 拿到文件后缀名,例如:png
    String suffix = file.getOriginalFilename().substring(file.getOriginalFilename().lastIndexOf(".") + 1);
    // UUID 作为文件名
    String uuid = String.valueOf(UUID.randomUUID());
    // 新的文件名
    String fileName = DateUtils.getYyyymmdd() + "/" + uuid + "." + suffix;
    /**
     * 判断是否是图片
     * 判断是否超过了 100K
     */
    if (isPicture(suffix) && (1024 * 1024 * 0.1) <= file.getSize()) {
        // 在项目根目录下的 upload 目录中生成临时文件
        File newFile = new File(ClassUtils.getDefaultClassLoader().getResource("upload").getPath() + uuid + "." + suffix);
        // 小于 1M 的
        if ((1024 * 1024 * 0.1) <= file.getSize() && file.getSize() <= (1024 * 1024)) {
            Thumbnails.of(file.getInputStream()).scale(1f).outputQuality(0.3f).toFile(newFile);
        }
        // 1 - 2M 的
        else if ((1024 * 1024) < file.getSize() && file.getSize() <= (1024 * 1024 * 2)) {
            Thumbnails.of(file.getInputStream()).scale(1f).outputQuality(0.2f).toFile(newFile);
        }
        // 2M 以上的
        else if ((1024 * 1024 * 2) < file.getSize()) {
            Thumbnails.of(file.getInputStream()).scale(1f).outputQuality(0.1f).toFile(newFile);
        }
        // 获取输入流
        FileInputStream input = new FileInputStream(newFile);
        // 转为 MultipartFile
        MultipartFile multipartFile = new MockMultipartFile("file", newFile.getName(), "text/plain", input);
        // 开始上传
        client.putObject("test", fileName, multipartFile.getInputStream(), file.getContentType());
        // 删除临时文件
        newFile.delete();
        // 返回状态以及图片路径
        res.put("code", 200);
        res.put("msg", "上传成功");
        res.put("url", minioProp.getEndpoint() + "/" + "test" + "/" + fileName);
    }
    // 不需要压缩,直接上传
    else {
        // 开始上传
        client.putObject("test", fileName, file.getInputStream(), file.getContentType());
        // 返回状态以及图片路径
        res.put("code", 200);
        res.put("msg", "上传成功");
        res.put("url", minioProp.getEndpoint() + "/" + "test" + "/" + fileName);
    }
    return res;
}
  • 这里我们判断了当文件为图片的时候,且当它大小超过了 (1024 * 1024 * 0.1),约为 100K 的时候,才进行压缩
  • 我们首先在根目录下的 upload 目录中创建了一个临时文件 newFile
  • Thumbnails.of(file.getInputStream()).scale(1f).outputQuality(0.3f).toFile(newFile);将压缩后的文件输出到临时文件中
  • 然后将 FileInputStream 转为 MultipartFile 上传
  • 最后删除临时文件 newFile.delete();
  • 完成图片压缩上传

4、测试

  • 原图 706K

原图

  • 压缩后 120K

压缩后

5、总结

  • 综合以上代码,可以看出 Thumbnails 对图片的处理是很方便的,且代码量也非常少
  • 通过测试,可以看出压缩后的图片质量也很高
  • thumbnailator 对图片的处理支持全面,缩放,裁剪等

如您在阅读中发现不足,欢迎留言!!!

### 回答1: import java.io.File; import java.io.FileInputStream; import java.io.IOException; import java.io.InputStream; import java.util.Properties; import io.minio.MinioClient;public class FileUpload { public static void main(String[] args) throws IOException { // 从配置文件读取minio服务器的地址和端口号 String minioServerUrl = ""; String minioServerPort = ""; InputStream inputStream = new FileInputStream("config.properties"); Properties prop = new Properties(); prop.load(inputStream); minioServerUrl = prop.getProperty("minioServerUrl"); minioServerPort = prop.getProperty("minioServerPort"); // 初始化minio客户端 MinioClient minioClient = new MinioClient(minioServerUrl, minioServerPort); // 获取本地文件 File localFile = new File("MyFile.txt"); // 获取文件的长度,用于断点续传 long fileSize = localFile.length(); // 文件分片上传,每次上传的大小必须是8M的整数倍 long partSize = 8 * 1024 * 1024; String bucketName = "mybucket"; String objectName = "MyFile.txt"; // 创建分片上传的任务 minioClient.putObject(bucketName, objectName, localFile.getAbsolutePath(), fileSize, partSize); } } ### 回答2: 使用Java实现文件分块上传和断点续传的基本步骤如下: 1. 引入Minio SDK:首先需要将Minio SDK引入项目的依赖,可以在项目的pom.xml文件添加相应的依赖。 ```xml <dependency> <groupId>io.minio</groupId> <artifactId>minio</artifactId> <version>8.2.5</version> </dependency> ``` 2. 创建Minio客户端:通过Minio SDK提供的API创建Minio服务器的连接。 ```java import io.minio.MinioClient; public class FileUploader { private static final String ENDPOINT = "https://minio.example.com"; private static final String ACCESS_KEY = "your-access-key"; private static final String SECRET_KEY = "your-secret-key"; public static void main(String[] args) { MinioClient minioClient = MinioClient.builder() .endpoint(ENDPOINT) .credentials(ACCESS_KEY, SECRET_KEY) .build(); // 以下为文件分块上传和断点续传的具体实现 // ... } } ``` 3. 文件分块上传:使用Minio SDK提供的`putObject`方法将文件分块上传Minio服务器。 ```java import io.minio.PutObjectArgs; public class FileUploader { // ... public static void main(String[] args) { // ... try { minioClient.putObject( PutObjectArgs.builder() .bucket("bucketName") .object("fileName") .filename("localFilePath") .build()); System.out.println("File uploaded successfully"); } catch (Exception e) { System.out.println("Error uploading file: " + e.getMessage()); } } } ``` 4. 断点续传:如果上传过程断开连接,可以记录已上传的文件块位置,并在恢复后从断点处继续上传。 ```java import io.minio.PutObjectOptions; public class FileUploader { // ... public static void main(String[] args) { // ... String bucketName = "bucketName"; String objectName = "fileName"; String localFilePath = "localFilePath"; String etag = null; try { // 获取已上传文件的etag etag = minioClient.statObject(bucketName, objectName).etag(); } catch (Exception e) { // 文件不存在,从头开始上传 System.out.println("File not found, uploading from beginning"); try { minioClient.putObject( PutObjectArgs.builder() .bucket(bucketName) .object(objectName) .filename(localFilePath) .build()); System.out.println("File uploaded successfully"); } catch (Exception ex) { System.out.println("Error uploading file: " + ex.getMessage()); } } if (etag != null) { // 断点续传 try { minioClient.putObject( PutObjectArgs.builder() .bucket(bucketName) .object(objectName) .filename(localFilePath) .headers(new HashMap<>()) .build(), PutObjectOptions.builder().setHeader("If-Match", etag).build()); System.out.println("File uploaded successfully"); } catch (Exception ex) { System.out.println("Error uploading file: " + ex.getMessage()); } } } } ``` 以上为使用Java实现文件分块上传和断点续传,并将文件上传Minio服务器的基本代码实现。根据具体需求,可以根据Minio SDK的API进行更加详细的配置和异常处理。
评论 467
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Asurplus

学如逆水行舟,不进则退

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值