什么是对象存储OSS
阿里云对象存储OSS(Object Storage Service)是阿里云提供的海量、安全、低成本、高可靠的云存储服务。其数据设计持久性不低于99.9999999999%(12个9),服务可用性(或业务连续性)不低于99.995%。
OSS具有与平台无关的RESTful API接口,您可以在任何应用、任何时间、任何地点存储和访问任意类型的数据。
您可以使用阿里云提供的API、SDK接口或者OSS迁移工具轻松地将海量数据移入或移出阿里云OSS。数据存储到阿里云OSS以后,您可以选择标准存储(Standard)作为移动应用、大型网站、图片分享或热点音视频的主要存储方式,也可以选择成本更低、存储期限更长的低频访问存储(Infrequent Access)、归档存储(Archive)作为不经常访问数据的存储方式。
官方文档
集成OSS
pom.xml
<dependency>
<groupId>com
.aliyun
.oss<
/groupId>
<artifactId>aliyun
-sdk
-oss<
/artifactId>
<version>3
.10
.2<
/version>
<
/dependency>
<dependency>
<groupId>org
.projectlombok<
/groupId>
<artifactId>lombok<
/artifactId>
<
/dependency>
application.yml
oss:
endpoint: https
://oss
-cn
-hangzhou.aliyuncs.com
accessKeyId: yourAccessKeyId
secretAccessKey: yourAccessKeySecret
bucketName: yourBucketName
urlPrefix: 你的文件访问地址
OSS客户端配置类,并注入到Spring中
@Data
@Configuration
@ConfigurationProperties(prefix
= "oss")
public class OssConfig {
private String endpoint
;
private String accessKeyId
;
private String secretAccessKey
;
private String bucketName
;
private String urlPrefix
;
@Bean
public OSS
oSSClient() {
return new OSSClientBuilder().build(endpoint
, accessKeyId
, secretAccessKey
);
}
}
文件上传、删除、下载、图像压缩、图像添加水印
测试
@RestController
public class OssController {
@Autowired
private OssUtil ossUtil
;
@PostMapping("/oss/upload")
public String
upload(@RequestParam("file") MultipartFile file
) {
return ossUtil
.putObject(file
);
}
@GetMapping("oss/delete")
public String
delete(@RequestParam("fileName") String fileName
) {
Boolean flag
= ossUtil
.deleteObject(fileName
);
if (flag
) {
return "删除成功";
}
return "删除失败";
}
@GetMapping("oss/list")
public List
<OSSObjectSummary> list() {
List
<OSSObjectSummary> fileList
= ossUtil
.listObjects();
return fileList
;
}
@GetMapping("oss/download")
public void download(@RequestParam("fileName") String fileName
, HttpServletResponse response
) throws IOException
{
response
.setHeader("Content-Disposition",
"attachment;filename=" + new String(fileName
.getBytes(), "ISO-8859-1"));
ossUtil
.download(response
.getOutputStream(), fileName
);
}
@PostMapping("/oss/uploadPic")
public String
uploadPic(@RequestParam("file") MultipartFile file
) {
boolean flag
= ossUtil
.isImage(file
);
if (flag
) {
return ossUtil
.uploadPic(file
);
}
return "上传失败";
}
}
OSS工具类
@Component
public class OssUtil {
@Autowired
private OSS ossClient
;
@Autowired
private OssConfig ossConfig
;
private static final long EXPIRATION
= 3600l
* 1000 * 24 * 7;
private static final String
[] IMAGE_TYPE
= new String[] { ".bmp", ".jpg", ".jpeg", ".gif", ".png" };
private String PATH
= "javakf/";
public String
uploadFile(MultipartFile file
) {
String fileUrl
= putObject(file
);
return fileUrl
;
}
public String
multiUpload(List
<MultipartFile> fileList
) {
String url
= null
;
String fileUrl
= null
;
for (int i
= 0; i
< fileList
.size(); i
++) {
url
= putObject(fileList
.get(i
));
if (i
== 0) {
fileUrl
= url
;
} else {
fileUrl
+= ";" + url
;
}
}
return fileUrl
.trim();
}
public String
uploadFiles(MultipartFile
... file
) {
if (file
.length
< 1) {
throw new RuntimeException("上传文件为空!");
}
StringBuilder str
= new StringBuilder();
for (MultipartFile muFile
: file
) {
str
.append(putObject(muFile
));
str
.append(";");
}
return str
.deleteCharAt(str
.length() - 1).toString();
}
public String
putObject(MultipartFile file
) {
try {
String fileName
= getFilePathName(file
, true);
ossClient
.putObject(ossConfig
.getBucketName(), fileName
, new ByteArrayInputStream(file
.getBytes()));
return this.ossConfig
.getUrlPrefix() + fileName
;
} catch (Exception e
) {
e
.printStackTrace();
throw new RuntimeException("上传文件失败!");
}
}
public String
uploadPic(MultipartFile file
) {
try {
String fileName
= getFilePathName(file
, true);
InputStream inputStream
= file
.getInputStream();
if (ImageUtil
.isImage(file
.getOriginalFilename())) {
inputStream
= ImageUtil
.getInputStream(
ImageUtil
.setWatermark(ImageUtil
.compress(ImageIO
.read(inputStream
))),
ImageUtil
.getFileExtention(file
.getOriginalFilename()));
}
ossClient
.putObject(ossConfig
.getBucketName(), fileName
, inputStream
);
return this.ossConfig
.getUrlPrefix() + fileName
;
} catch (Exception e
) {
e
.printStackTrace();
throw new RuntimeException("上传文件失败!");
}
}
public boolean isImage(MultipartFile file
) {
boolean flag
= false;
for (String type
: IMAGE_TYPE
) {
if (StringUtils
.endsWithIgnoreCase(file
.getOriginalFilename(), type
)) {
flag
= true;
break;
}
}
return flag
;
}
public Boolean
deleteObject(String fileName
) {
try {
ossClient
.deleteObject(ossConfig
.getBucketName(), fileName
);
return true;
} catch (Exception e
) {
e
.printStackTrace();
return false;
}
}
public List
<OSSObjectSummary> listObjects() {
ObjectListing listObjects
= ossClient
.listObjects(ossConfig
.getBucketName());
List
<OSSObjectSummary> fileList
= listObjects
.getObjectSummaries();
return fileList
;
}
public List
<OSSObjectSummary> listObjects(Integer maxKeys
) {
if (maxKeys
== null
) {
maxKeys
= 100;
}
ObjectListing listObjects
= ossClient
.listObjects(new ListObjectsRequest(ossConfig
.getBucketName()).withMaxKeys(maxKeys
));
List
<OSSObjectSummary> fileList
= listObjects
.getObjectSummaries();
return fileList
;
}
public List
<OSSObjectSummary> listObjects(String prefix
) {
ObjectListing listObjects
= ossClient
.listObjects(ossConfig
.getBucketName(), prefix
);
List
<OSSObjectSummary> fileList
= listObjects
.getObjectSummaries();
return fileList
;
}
public void download(OutputStream outputStream
, String fileName
) {
try {
OSSObject ossObject
= ossClient
.getObject(ossConfig
.getBucketName(), fileName
);
BufferedInputStream in
= new BufferedInputStream(ossObject
.getObjectContent());
BufferedOutputStream out
= new BufferedOutputStream(outputStream
);
byte[] buffer
= new byte[1024];
int lenght
= 0;
while ((lenght
= in
.read(buffer
)) != -1) {
out
.write(buffer
, 0, lenght
);
}
if (out
!= null
) {
out
.flush();
out
.close();
}
if (in
!= null
) {
in
.close();
}
} catch (IOException e
) {
e
.printStackTrace();
}
}
public String
getUrl(String fileName
) {
if (!StringUtils
.isEmpty(fileName
)) {
Date expiration
= new Date(new Date().getTime() + EXPIRATION
);
URL url
= ossClient
.generatePresignedUrl(ossConfig
.getBucketName(), fileName
, expiration
);
if (url
!= null
) {
return url
.toString();
}
}
return null
;
}
public String
putObject(InputStream inputStream
, String fileName
) {
try {
String fileSuffix
= fileName
.substring(fileName
.lastIndexOf(".")).toLowerCase();
fileName
= PATH
+ new Random().nextInt(10000) + System
.currentTimeMillis() + fileSuffix
;
ObjectMetadata objectMetadata
= new ObjectMetadata();
objectMetadata
.setContentLength(inputStream
.available());
objectMetadata
.setCacheControl("no-cache");
objectMetadata
.setHeader("Pragma", "no-cache");
objectMetadata
.setContentEncoding("utf-8");
objectMetadata
.setContentType(getcontentType(fileSuffix
));
objectMetadata
.setContentDisposition("inline;filename=" + fileName
);
ossClient
.putObject(ossConfig
.getBucketName(), fileName
, inputStream
, objectMetadata
);
} catch (IOException e
) {
e
.printStackTrace();
} finally {
try {
if (inputStream
!= null
) {
inputStream
.close();
}
} catch (IOException e
) {
e
.printStackTrace();
}
}
return this.ossConfig
.getUrlPrefix() + fileName
;
}
private String
getFilePathName(MultipartFile file
, boolean isRetain
) {
String fileName
= file
.getOriginalFilename();
String name
= fileName
;
String fileSuffix
= "";
if (fileName
.indexOf('.') != -1) {
name
= fileName
.substring(0, fileName
.indexOf('.'));
fileSuffix
= fileName
.substring(fileName
.lastIndexOf("."));
}
LocalDate date
= LocalDate
.now();
StringBuilder filePathName
= new StringBuilder(PATH
);
filePathName
.append(date
.getYear());
filePathName
.append("/");
filePathName
.append(date
.getMonthValue());
filePathName
.append("/");
filePathName
.append(date
.getDayOfMonth());
filePathName
.append("/");
Random r
= new Random();
int pix
= r
.ints(1, (100 + 1)).findFirst().getAsInt();
filePathName
.append(System
.currentTimeMillis());
filePathName
.append("" + pix
);
if (isRetain
) {
filePathName
.append("_");
if (name
.length() >= 32) {
name
= name
.substring(0, 32);
}
filePathName
.append(name
);
}
filePathName
.append(fileSuffix
);
return filePathName
.toString();
}
public String
getcontentType(String fileSuffix
) {
if (fileSuffix
.equalsIgnoreCase(".bmp")) {
return "image/bmp";
}
if (fileSuffix
.equalsIgnoreCase(".gif")) {
return "image/gif";
}
if (fileSuffix
.equalsIgnoreCase(".jpeg") || fileSuffix
.equalsIgnoreCase(".jpg")
|| fileSuffix
.equalsIgnoreCase(".png")) {
return "image/jpeg";
}
if (fileSuffix
.equalsIgnoreCase(".html")) {
return "text/html";
}
if (fileSuffix
.equalsIgnoreCase(".txt")) {
return "text/plain";
}
if (fileSuffix
.equalsIgnoreCase(".vsd")) {
return "application/vnd.visio";
}
if (fileSuffix
.equalsIgnoreCase(".pptx") || fileSuffix
.equalsIgnoreCase(".ppt")) {
return "application/vnd.ms-powerpoint";
}
if (fileSuffix
.equalsIgnoreCase(".docx") || fileSuffix
.equalsIgnoreCase(".doc")) {
return "application/msword";
}
if (fileSuffix
.equalsIgnoreCase(".xml")) {
return "text/xml";
}
return "image/jpeg";
}
public boolean createBucket(String bucketName
) {
try {
boolean flag
= ossClient
.doesBucketExist(bucketName
);
if (!flag
) {
ossClient
.createBucket(bucketName
);
ossClient
.setBucketAcl(bucketName
, CannedAccessControlList
.PublicRead
);
return true;
}
} catch (Exception e
) {
e
.printStackTrace();
}
return false;
}
public boolean deleteBucket(String bucketName
) {
try {
boolean flag
= ossClient
.doesBucketExist(bucketName
);
if (flag
) {
ossClient
.deleteBucket(bucketName
);
return true;
}
} catch (Exception e
) {
e
.printStackTrace();
}
return false;
}
public List
<String> listBuckets() {
List
<Bucket> buckets
= ossClient
.listBuckets();
List
<String> bucketNames
= new ArrayList<>();
for (Bucket bucket
: buckets
) {
bucketNames
.add(bucket
.getName());
}
return bucketNames
;
}
}
图像工具类
需要添加依赖
<dependency>
<groupId>net
.coobird<
/groupId>
<artifactId>thumbnailator<
/artifactId>
<version>0
.4
.11<
/version>
<
/dependency>
public class ImageUtil {
private static final transient float IMAGE_RATIO
= 0.1f;
private static final transient int IMAGE_WIDTH
= 800;
private static float alpha
= 0.3f;
private static Font font
= new Font("PingFang SC Regular", Font
.PLAIN
, 36);
private static Color color
= new Color(111, 111, 111);
private static final String text
= "这是一个水印文本";
private static final int XMOVE
= 80;
private static final int YMOVE
= 80;
public static BufferedImage
compress(BufferedImage image
) throws IOException
{
Thumbnails
.Builder
<BufferedImage> imageBuilder
= Thumbnails
.of(image
).outputQuality(IMAGE_RATIO
);
if (image
.getWidth() > IMAGE_WIDTH
) {
return imageBuilder
.width(IMAGE_WIDTH
).asBufferedImage();
} else {
return imageBuilder
.scale(1).asBufferedImage();
}
}
public static BufferedImage
setWatermark(BufferedImage image
) throws IOException
{
return Thumbnails
.of(image
).outputQuality(IMAGE_RATIO
).scale(1)
.watermark(Positions
.BOTTOM_RIGHT
, createWatermark(text
, image
.getWidth(), image
.getHeight()), alpha
)
.asBufferedImage();
}
public static boolean isImage(String fileName
) {
String
[] imageExtension
= new String[] { "jpeg", "jpg", "gif", "bmp", "png" };
for (String e
: imageExtension
)
if (getFileExtention(fileName
).toLowerCase().equals(e
))
return true;
return false;
}
public static String
getFileExtention(String fileName
) {
String extension
= fileName
.substring(fileName
.lastIndexOf(".") + 1);
return extension
;
}
public static InputStream
getInputStream(BufferedImage image
, String readImageFormat
) throws IOException
{
ByteArrayOutputStream os
= new ByteArrayOutputStream();
ImageIO
.write(image
, readImageFormat
, os
);
InputStream is
= new ByteArrayInputStream(os
.toByteArray());
os
.close();
return is
;
}
public static BufferedImage
createWatermark(String text
, int width
, int height
) {
BufferedImage image
= new BufferedImage(width
, height
, BufferedImage
.TYPE_INT_RGB
);
Graphics2D g
= image
.createGraphics();
image
= g
.getDeviceConfiguration().createCompatibleImage(width
, height
, Transparency
.TRANSLUCENT
);
g
.dispose();
g
= image
.createGraphics();
AttributedString ats
= new AttributedString(text
);
ats
.addAttribute(TextAttribute
.FONT
, font
, 0, text
.length());
g
.setRenderingHint(RenderingHints
.KEY_INTERPOLATION
, RenderingHints
.VALUE_INTERPOLATION_BILINEAR
);
g
.setRenderingHint(RenderingHints
.KEY_ANTIALIASING
, RenderingHints
.VALUE_ANTIALIAS_ON
);
g
.rotate(Math
.toRadians(-30));
g
.setColor(color
);
g
.setFont(font
);
g
.setComposite(AlphaComposite
.getInstance(AlphaComposite
.SRC_ATOP
, alpha
));
g
.setComposite(AlphaComposite
.getInstance(AlphaComposite
.SRC_OVER
));
int x
= -width
/ 2;
int y
= -height
/ 2;
int[] arr
= getWidthAndHeight(text
, font
);
int markWidth
= arr
[0];
int markHeight
= arr
[1];
while (x
< width
* 1.5) {
y
= -height
/ 2;
while (y
< height
* 1.5) {
g
.drawString(text
, x
, y
);
y
+= markHeight
+ YMOVE
;
}
x
+= markWidth
+ XMOVE
;
}
g
.dispose();
return image
;
}
private static int[] getWidthAndHeight(String text
, Font font
) {
Rectangle2D r
= font
.getStringBounds(text
,
new FontRenderContext(AffineTransform
.getScaleInstance(1, 1), false, false));
int unitHeight
= (int) Math
.floor(r
.getHeight());
int width
= (int) Math
.round(r
.getWidth()) + 1;
int height
= unitHeight
+ 3;
return new int[] { width
, height
};
}
}
代码托管:springboot_oss