springboot整合s3,用ImageIO进行图片格式转换

上次用laravel进行了一些s3得整合,可以看出来其实蛮简单得。

先导包

        <dependency>
            <groupId>software.amazon.awssdk</groupId>
            <artifactId>s3</artifactId>
        </dependency>

然后在配置类中写bean

    private static final String AK = "xxxxxxxxxxxx";
    private static final String SK = "xxxxxxxxxxxx";

    @Bean
    public S3Client s3Client() {
        return S3Client.builder()
                .credentialsProvider(StaticCredentialsProvider.create(AwsBasicCredentials.create(AK, SK)))
                .region(Region.US_WEST_2)
                .build();
    }

然后就可以用注解拿到s3client了,直接开始写接口

Controller

    @ApiOperation("上传文件")
    @PostMapping("/upload")
    public Response upload(@RequestParam("file") MultipartFile file) {
        if (StringUtils.isBlank(file.getOriginalFilename())) {
            return Response.fail(RespCode.FILE_NAME_IS_EMPTY);
        }
        if (file.getSize() == 0L) {
            return Response.fail(RespCode.FILE_IS_EMPTY);
        }
        if (file.getSize() > FILE_MAX_BYTE) {
            return Response.fail(RespCode.FILE_TOO_LARGE);
        }
        return SingleResponse.ok(s3Service.upload(file));
    }

Service

@Service
public class S3Service {

    @Autowired
    private S3Client s3Client;

    public static final String BUCKET_NAME = "xxxxxxxx";
    public static final String URL = "xxxxxxxxxx";

    public String upload(MultipartFile multipartFile) {
        String tmpPath = StringUtils.join(System.getProperties().getProperty("java.io.tmpdir"), "/");
        String fileSuf = null;
        int index = multipartFile.getOriginalFilename().lastIndexOf(".");
        if (index > -1) {
            fileSuf = multipartFile.getOriginalFilename().substring(index);
        }
        File file = new File(tmpPath + UUIDUtils.lowerCaseNoSeparatorUUID() + fileSuf);
        try {
            multipartFile.transferTo(file);
            file.deleteOnExit();
        } catch (IOException e) {
            throw new SvcException(e.getMessage());
        }
        return upload(file);
    }

    public String upload(File file) {
        PutObjectRequest putOb = PutObjectRequest.builder()
                .bucket(BUCKET_NAME)
                .key(file.getName())
                .build();
        s3Client.putObject(putOb, RequestBody.fromFile(file));
        return StringUtils.join(URL, file.getName());
    }

}
String tmpPath = StringUtils.join(System.getProperties().getProperty("java.io.tmpdir"), "/");这一句根据你不同得web容器可能会有不一样得效果,一般是tomcat没什么大毛病,但是我这次用的undertow ,就有一点小坑。如果大家也是用undertow ,大家可以看看这个博客自己解决

spring boot文件上传、undertow 临时文件配置、NoSuchFileException: /tmp/under、IOException: No space left on device_springboot上传文件临时文件清理-CSDN博客

至此,s3基本上传功能是没问题了。

但是我想要改装一下,把图片格式都变成jpg,我使用的是java得imageIO类来处理。先把第一个upload改装一下

    public String upload(MultipartFile multipartFile) {
        String tmpPath = StringUtils.join(System.getProperties().getProperty("java.io.tmpdir"), "/");
        String fileSuf = null;
        int index = multipartFile.getOriginalFilename().lastIndexOf(".");
        if (index > -1) {
            fileSuf = ".jpg"; // 将所有上传的图片统一转换为 JPG 格式
        }
        File file = new File(tmpPath + UUIDUtils.lowerCaseNoSeparatorUUID() + fileSuf);
        try {
            multipartFile.transferTo(file);
            file.deleteOnExit();

            // 转换上传的图片为 JPG 格式
            String outputImagePath = tmpPath + UUIDUtils.lowerCaseNoSeparatorUUID() + ".jpg";
            ImageConverterUtils.convertToJPG(file.getAbsolutePath(), outputImagePath);

            // 调用自己的 upload 方法处理图片上传
            return upload(new File(outputImagePath));
        } catch (IOException e) {
            throw new SvcException(e.getMessage());
        }
    }

我自己写了个很简单得工具类

public class ImageConverterUtils {
    public static void convertToJPG(String sourceImage,String outputImage) throws IOException {
        File source = new File(sourceImage);
        BufferedImage bufferedImage = ImageIO.read(source);

        File output = new File(outputImage);
        ImageIO.write(bufferedImage,"jpg",output);

    }
}

到这里确实可以把一些图片转换成jpg并且上传到s3,不过依旧有坑。

第一个就是其实imageIO貌似不支持webp格式得转换,一次webp格式得图片总数会转换不成功

很好解决,添加个pom依赖就好:

        <dependency>
            <groupId>org.sejda.imageio</groupId>
            <artifactId>webp-imageio</artifactId>
            <version>0.1.6</version>
        </dependency>

第二,不仅不支持webp,而且png也会出毛病。我的毛病是只要是png格式的,ImageIO.write居然返回false,抛出异常了。原因是ImageIO.wite方法在中调用的私有方法getWriter寻找合适的ImageWriter时不仅与formatName相关,还是输入的原图有关,造成getWriter方法找不到对应的ImageWriter。

因此改造成了一下我的工具类:

public class ImageConverterUtils {
    public static void convertToJPG(String sourceImage,String outputImage) throws IOException {
            File source = new File(sourceImage);
            BufferedImage bufferedImage = ImageIO.read(source);
            BufferedImage newBufferedImage = new BufferedImage(bufferedImage.getWidth(),
                    bufferedImage.getHeight(), BufferedImage.TYPE_INT_RGB);
            Graphics2D g = newBufferedImage.createGraphics();
            g.drawImage(bufferedImage, 0, 0,null);
            File output = new File(outputImage);
            ImageIO.write(newBufferedImage,"jpg",output);
            g.dispose();
    }
}

然后就没问题了,可以正常上传和转换格式了。

这里顺带有个蛮好用的网站,可以看到文件的MIME类型:MIME File Type Checker - HTMLStrip

 

java : 调用ImageIO.writer从BufferedImage生成jpeg图像的坑-CSDN博客

[ 云计算 | AWS 实践 ] Java 应用中使用 Amazon S3 进行存储桶和对象操作完全指南 - 知乎 (zhihu.com)

  • 4
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值