上次用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 ,大家可以看看这个博客自己解决
至此,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)