springboot上传图片到阿里云OSS同时进行压缩(使用thumbnailator)

首先导入thumbnailator包,关于这个的使用可以看别的博文。

pom文件引入:

        <dependency>
            <groupId>com.aliyun.oss</groupId>
            <artifactId>aliyun-sdk-oss</artifactId>
            <version>3.10.2</version>
        </dependency>

        <dependency>
            <groupId>commons-io</groupId>
            <artifactId>commons-io</artifactId>
            <version>2.4</version>
        </dependency>
        <dependency>
            <groupId>net.coobird</groupId>
            <artifactId>thumbnailator</artifactId>
            <version>0.4.8</version>
        </dependency>

然后写一个压缩的工具类:

import lombok.extern.slf4j.Slf4j;
import net.coobird.thumbnailator.Thumbnails;
import org.apache.commons.io.IOUtils;

import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;

/**
 * 压缩工具类
 */
@Slf4j
public class CompressionUtil {

    /**
     * 压缩后的图片大小
     */
    private static final long AFTER_COMPRESSION_FILE_SIZE = 500L;

    /**方便通过文件流来给到thumbnailator的操作字节流
     * 传入stream然后转化为byte[]然后得到压缩后的数组
     */
    public static byte[] streamToBytesAndCompression(InputStream inputStream, Integer userId) throws IOException {
    	//使用的是org.apache.commons.io.IOUtils
        byte[] bytes = IOUtils.toByteArray(inputStream);
        //图片小于500kb
        bytes = compressPicForScale(bytes, AFTER_COMPRESSION_FILE_SIZE, userId.toString());
        return bytes;
    }

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

    /**
     * 自动调节精度(经验数值)
     *
     * @param size 源图片大小
     * @return 图片压缩质量比
     */
    private static double getAccuracy(long size) {
        double accuracy;
        if (size < 900) {
            accuracy = 0.85;
        } else if (size < 2047) {
            accuracy = 0.6;
        } else if (size < 3275) {
            accuracy = 0.44;
        } else {
            accuracy = 0.4;
        }
        return accuracy;
    }
}

写一个OSS上传的工具类

public class OOSUtil {
	/**
     * 按照byte数组传输图片
     *
     * @param dir       存放的目录名称
     * @param fileName  文件名称
     * @param byteArray 压缩后的byte数组
     * @return 图片链接
     */
    public static String addFileByByteArray(String dir, String fileName, byte[] byteArray) {
        OSS ossClient = new OSSClientBuilder().build(endpoint, accessKeyId, accessKeySecret);
        ObjectMetadata metadata = new ObjectMetadata();
        metadata.setHeader(OSSHeaders.OSS_STORAGE_CLASS, StorageClass.Standard.toString());
        //公共读
        metadata.setObjectAcl(CannedAccessControlList.PublicRead);
        metadata.setCacheControl("no-cache");
        metadata.setHeader("Pragma", "no-cache");
        metadata.setContentDisposition("inline;filename=" + fileName);
        metadata.setContentType(getcontentType(fileName.substring(fileName.lastIndexOf("."))));
        try {
            fileName = dir + "/" + fileName;
            ossClient.putObject(bucketName, fileName, new ByteArrayInputStream(byteArray), metadata);
        } catch (Exception e) {
            return null;
        } finally {
            ossClient.shutdown();
        }
        return "https://XXX-oos.XXX.XXX/" + fileName;//自己绑定OSS的域名
    }

	/**
     * 判断OSS服务文件上传时文件的类型contentType
     *
     * @param FilenameExtension 文件后缀
     * @return String
     */
    public static String getcontentType(String FilenameExtension) {
        if (".bmp".equalsIgnoreCase(FilenameExtension)) {
            return "image/bmp";
        }
        if (".gif".equalsIgnoreCase(FilenameExtension)) {
            return "image/gif";
        }
        if (".jpeg".equalsIgnoreCase(FilenameExtension) ||
                ".jpg".equalsIgnoreCase(FilenameExtension)) {
            return "image/jpeg";
        }
        if (".html".equalsIgnoreCase(FilenameExtension)) {
            return "text/html";
        }
        if (".txt".equalsIgnoreCase(FilenameExtension)) {
            return "text/plain";
        }
        if (".vsd".equalsIgnoreCase(FilenameExtension)) {
            return "application/vnd.visio";
        }
        if (".pptx".equalsIgnoreCase(FilenameExtension) ||
                ".ppt".equalsIgnoreCase(FilenameExtension)) {
            return "application/vnd.ms-powerpoint";
        }
        if (".docx".equalsIgnoreCase(FilenameExtension) ||
                ".doc".equalsIgnoreCase(FilenameExtension)) {
            return "application/msword";
        }
        if (".xml".equalsIgnoreCase(FilenameExtension)) {
            return "text/xml";
        }
        if (".png".equalsIgnoreCase(FilenameExtension)) {
            return "image/png";
        }
        return "image/jpg";
    }
}

自己写一个测试方法:

    @Test
    void testByteArrays() throws IOException {
        //1. 得到byte数组
        byte[] bytes = FileUtils.readFileToByteArray(new File("C:\\Users\\Lenovo\\Desktop\\earth.png"));
        long l = System.currentTimeMillis();
        String userId = "3";
        //2. 调用方法得到压缩后的byte数组
        bytes = CompressionUtil.compressPicForScale(bytes, 300, userId);// 图片小于300kb
        System.out.println("压缩花费时间为:"+(System.currentTimeMillis() - l));
        //TODO 注意文件的后缀
        //上传压缩后的数组
        String url = OOSUtil.addFileByByteArray("carry_head_portrait", userId + ".png", bytes);
        System.out.println(url);
//也可以用下面这两个方法
// byte[] bytes = CompressionUtil.streamToBytesAndCompression(inputStream, userId);
//url = OOSUtil.addFileByByteArray("carry_head_portrait", userId + suffix, bytes);    
    }

这样我们执行后在OSS控制台就可以看到结果了。

原来我的图片是4.13MB,压缩后是198.962KB,压缩的时间是2s多,说明压缩效果还是不错的。

  • 2
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
SpringBoot中配置阿里云OSS参数需要做以下几个步骤: 1. 引入阿里云OSS的依赖 在 `pom.xml` 文件中添加以下依赖: ```xml <dependency> <groupId>com.aliyun.oss</groupId> <artifactId>aliyun-sdk-oss</artifactId> <version>3.12.0</version> </dependency> ``` 2. 在 `application.properties` 文件中配置阿里云OSS参数 在 `application.properties` 文件中添加以下配置: ``` spring: cloud: alibaba: oss: endpoint: oss-cn-hangzhou.aliyuncs.com access-key: your-access-key secret-key: your-secret-key bucket-name: your-bucket-name ``` 其中,`endpoint` 为阿里云OSS服务的访问地址,`access-key` 和 `secret-key` 分别为阿里云OSS的 AccessKeyId 和 AccessKeySecret,`bucket-name` 为你在阿里云OSS上创建的存储桶名称。 3. 创建阿里云OSS客户端 在代码中创建阿里云OSS客户端,代码如下: ```java import com.aliyun.oss.OSS; import com.aliyun.oss.OSSClientBuilder; import org.springframework.beans.factory.annotation.Value; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; @Configuration public class OSSConfig { @Value("${spring.cloud.alibaba.oss.endpoint}") private String ossEndpoint; @Value("${spring.cloud.alibaba.oss.access-key}") private String ossAccessKeyId; @Value("${spring.cloud.alibaba.oss.secret-key}") private String ossAccessKeySecret; @Value("${spring.cloud.alibaba.oss.bucket-name}") private String ossBucketName; @Bean public OSS ossClient() { return new OSSClientBuilder().build(ossEndpoint, ossAccessKeyId, ossAccessKeySecret); } } ``` 在上述代码中,通过 `@Value` 注解获取 `application.properties` 文件中配置的阿里云OSS参数,并通过 `OSSClientBuilder` 创建阿里云OSS客户端。 4. 使用阿里云OSS客户端进行操作 在代码中使用阿里云OSS客户端进行上传、下载、删除等操作,具体操作方式可以参考阿里云OSS官方文档。例如,上传文件的代码如下: ```java import com.aliyun.oss.OSS; import com.aliyun.oss.model.PutObjectRequest; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; @Service public class OSSService { @Autowired private OSS ossClient; public void uploadFile(String objectName, String filePath) { PutObjectRequest request = new PutObjectRequest(ossBucketName, objectName, new File(filePath)); ossClient.putObject(request); } } ``` 在上述代码中,通过 `PutObjectRequest` 构造器创建上传请求,并通过 `ossClient.putObject(request)` 方法将文件上传到阿里云OSS上。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值