什么是阿里云OSS
阿里云OSS(Object Storage Service,对象存储服务)是阿里云提供的一种存储服务,它支持任意类型的数据存储,如图片、视频、日志文件等。OSS以对象(Object)的形式组织数据,并存储在容器(Bucket)中。每个对象由其数据和元数据组成,对象被唯一地标识,使得用户可以在全球任何地方通过网络访问这些数据。
OSS的特点主要包括:
- 高可靠性和可用性:通过数据多副本机制确保数据安全,同时保证服务的高可用性。
 - 可扩展性:用户可以根据需求无限扩展存储空间,不需要担心存储容量的限制。
 - 灵活的访问控制:提供丰富的访问控制策略,支持细粒度的权限管理,确保数据安全。
 - 成本效益:采用按需付费的方式,用户只需为实际使用的存储空间和数据传输等资源支付费用,无需前期投资。
 - 易用性:提供了丰富的SDK和API接口,支持多种编程语言,便于用户集成和使用。
 - 全球化服务:阿里云在全球多个地区提供OSS服务,用户可以根据业务需要选择数据存储的地理位置。
 
OSS适用于各种存储需求的场景,如网站静态资源存储、大数据分析、内容分发网络(CDN)的源站存储、企业级数据备份和灾难恢复等。它为用户提供了一种简单、安全、高效的数据存储解决方案。
Java代码如何实现存储
要是需要GPT Plus账号的小伙伴可以联系我~,不封号好用不贵,独享账号资源,一条龙服务
这里如何配置和购买阿里云oss就不介绍了,只是分享一下如何实现存储。而且使用阿里云的OSS也有很多种方式,这里分享一下其中一种就是使用阿里官方的SDK进行调用存储
导入阿里云OSS的SDK
<!--阿里云sdk-->
        <dependency>
            <groupId>com.aliyun.oss</groupId>
            <artifactId>aliyun-sdk-oss</artifactId>
            <version>3.4.2</version>
        </dependency>
 
配置文件配置自己的配置文件信息
这里配置服务的信息即可
# 阿里云oss配置
# Aliyun OSS 配置
# 访问密钥ID,用于标识用户
aliyun.accessKeyId=XXXXXXXXXXXXXXXXXX
# 访问密钥密文,用于验证用户的身份
aliyun.accessKeySecret=XXXXXXXXXXXXXXXXXX
# OSS服务的访问域名
aliyun.oss.endpoint=XXXXXXXXXXXXXXXXXX
# OSS中的存储桶名称
aliyun.oss.bucketName=XXXXXXXXXXXXXXXXXX
#访问OSS服务的URL前缀
aliyun.oss.urlPrefix=XXXXXXXXXXXXXXXXXX
 
相关类逻辑代码编写
配置读写类
 * ClassName AliyunConfig.java
 * author 舒一笑
 * version 1.0.0
 * Description 阿里云OSS配置
 * createTime 2024年03月18日 19:13:00
 */
@Data
@Configuration
public class AliyunConfig {
    // 地域节点
    @Value("${aliyun.oss.endpoint}")
    private String endpoint;
    @Value("${aliyun.accessKeyId}")
    private String accessKeyId;
    @Value("${aliyun.accessKeySecret}")
    private String accessKeySecret;
    @Value("${aliyun.oss.bucketName}")
    private String bucketName;
    @Value("${aliyun.oss.urlPrefix}")
    private String urlPrefix;
	
	// 这里我要说明一下就是如何你的生产环境配置比较严格那就需要在这个使用这个,不能使用spring自动注入ossClient这个客户端对象,不然就会出现相关问题,我就遇到的有配置的签名不匹配,将文件的上传路径地址误认为是桶名称等等报错。
    @Bean
    public OSSClient ossClient() {
        return new OSSClient(endpoint, accessKeyId, accessKeySecret);
    }
}
 
图片文件上传base64转MultipartFile工具类
/**
 * ClassName Base64DecodedMultipartFile.java
 * author 舒一笑
 * version 1.0.0
 * Description 图片文件上传base64转MultipartFile工具类
 * createTime 2024年03月18日 19:33:00
 */
public class Base64DecodedMultipartFile implements MultipartFile {
    private final byte[] imgContent;
    private final String header;
    public Base64DecodedMultipartFile(byte[] imgContent, String header) {
        this.imgContent = imgContent;
        this.header = header;
    }
    @Override
    public String getName() {
        return System.currentTimeMillis() + Math.random() + "." + header.split("/")[1].split(";")[0];
    }
    @Override
    public String getOriginalFilename() {
        return getName();
    }
    @Override
    public String getContentType() {
        return header.split(":")[1].split(";")[0];
    }
    @Override
    public boolean isEmpty() {
        return imgContent == null || imgContent.length == 0;
    }
    @Override
    public long getSize() {
        return imgContent.length;
    }
    @Override
    public byte[] getBytes() {
        return imgContent;
    }
    @Override
    public InputStream getInputStream() {
        return new ByteArrayInputStream(imgContent);
    }
    @Override
    public void transferTo(File dest) throws IOException, IllegalStateException {
        try (FileOutputStream fos = new FileOutputStream(dest)) {
            fos.write(imgContent);
        }
    }
}
 
图片静态文件解析工具类
/**
 * ClassName Base64DecodedStaticFile.java
 * author 舒一笑
 * version 1.0.0
 * Description 图片静态文件解析工具类
 * createTime 2024年03月19日 13:08:00
 */
public class Base64DecodedStaticFile implements MultipartFile {
    private byte[] imgContent;
    public Base64DecodedStaticFile(byte[] imgContent) {
        this.imgContent = imgContent;
    }
    @Override
    public String getName() {
        return "filename";
    }
    @Override
    public String getOriginalFilename() {
        return "originalFilename.jpg";
    }
    @Override
    public String getContentType() {
        return "image/jpeg";
    }
    @Override
    public boolean isEmpty() {
        return imgContent == null || imgContent.length == 0;
    }
    @Override
    public long getSize() {
        return imgContent.length;
    }
    @Override
    public byte[] getBytes() throws IOException {
        return imgContent;
    }
    @Override
    public InputStream getInputStream() throws IOException {
        return new ByteArrayInputStream(imgContent);
    }
    @Override
    public void transferTo(java.io.File dest) throws IOException, IllegalStateException {
        // 这里根据你的需求实现文件传输的逻辑
    }
}
 
文件导入导出工具类
/**
 * ClassName FileUtil.java
 * author 舒一笑
 * version 1.0.0
 * Description 文件导入导出工具类
 * createTime 2024年03月19日 13:58:00
 */
@Component
public class FileUtil {
    @Autowired
    private AliyunConfig aliyunConfig;
    // 允许上传的格式
    private static final String[] IMAGE_TYPE = new String[]{".bmp", ".jpg", ".jpeg", ".gif", ".png"};
    public PicUploadResult upload(MultipartFile multipartFile) {
        // 1. 对上传的图片进行校验: 这里简单校验后缀名
        // 另外可通过ImageIO读取图片的长宽来判断是否是图片,校验图片的大小等。
        // TODO 图片校验
        boolean isLegal = false;
        for (String type : IMAGE_TYPE) {
            if (StringUtils.endsWithIgnoreCase(multipartFile.getOriginalFilename(), type)) {
                isLegal = true;
                break;  // 只要与允许上传格式其中一个匹配就可以
            }
        }
        PicUploadResult picUploadResult = new PicUploadResult();
        // 格式错误, 返回与前端约定的error
        if (!isLegal) {
            picUploadResult.setStatus("error");
            return picUploadResult;
        }
        // 2. 准备上传API的参数
        String fileName = multipartFile.getOriginalFilename();
        String filePath = fileName;
        // 3. 上传至阿里OSS
        try {
            // 初始化OSSClient  
            /// 这里说明一下就是为了避免上面说的ossClient 问题另外一种写法,不使用spring自动注入,也不用配置类里面的ossClient,直接使用建造者模式直接build
            OSS ossClient = new OSSClientBuilder().build(aliyunConfig.getEndpoint(), aliyunConfig.getAccessKeyId(), aliyunConfig.getAccessKeySecret());
            ossClient.putObject(aliyunConfig.getBucketName(), filePath, new ByteArrayInputStream(multipartFile.getBytes()));
        } catch (IOException e) {
            e.printStackTrace();
            // 上传失败
            picUploadResult.setStatus("error");
            return picUploadResult;
        }
        // 上传成功
        picUploadResult.setStatus("done");
        // 文件名(即直接访问的完整路径)
        picUploadResult.setName(aliyunConfig.getUrlPrefix() + filePath);
        // uid
        picUploadResult.setUid(String.valueOf(System.currentTimeMillis()));
        return picUploadResult;
    }
    /**
     * 上传的目录
     * 目录: 根据年月日归档
     * 文件名: 时间戳 + 随机数
     * @param fileName
     * @return
     */
    private String getFilePath(String fileName) {
        return StringUtils.substringAfterLast(fileName, ".");
    }
}
 
阿里云oos响应配置类
/**
 * ClassName PicUploadResult.java
 * author 舒一笑
 * version 1.0.0
 * Description 阿里云oos响应配置类
 * createTime 2024年03月18日 19:20:00
 */
@Getter
@Setter
public class PicUploadResult {
    private String uid;
    private String name;
    private String status;
    private String response;
    private String linkProps;
}
 
调用逻辑类代码示例
// 首先自动注入一下
 @Autowired
    private FileUtil fileUtil;
 
这里是我的使用示例,展示一下调用的逻辑,有些代码是具有我项目中的业务实现部分不用理会
// 调用上传方法
            PicUploadResult uploadResult = fileUtil.upload(multipartFile);
            staticResourceService.saveSingleFileToServe(snapshotName, request.getSnapshot().replace("data:image/jpeg;base64,", "").replace("data:image/png;base64,", ""));
//            requestTemplate.setSnapshot("/" + UPLOAD_URL_PREFIX + '/' + snapshotName);
            requestTemplate.setSnapshot(uploadResult.getName());
            // 静态资源小图处理
            Gson gson = new Gson();
            PanelGroupRequest panelGroupRequest = gson.fromJson(request.getPanelInfo(), PanelGroupRequest.class);
//            panelGroupRequest.setPanelData(JSON.toJSONString(jsonArray));
            Map<String, String> resource = gson.fromJson(panelGroupRequest.getStaticResource(), Map.class);
            Map<String, String> imageUrl = new HashMap<>();
            for (String s : resource.keySet()) {
                String imageCode = resource.get(s);
                byte[] bytes = DatatypeConverter.parseBase64Binary(imageCode);
                PicUploadResult picUploadResult = fileUtil.upload(new Base64DecodedStaticFile(bytes));
                imageUrl.put(s, picUploadResult.getName());
            }
            // 数据库缩略图存储处理
            String staticResource = panelGroupRequest.getStaticResource();
            Map<String,String> staticResourceMap= gson.fromJson(staticResource, Map.class);
            for (String s : staticResourceMap.keySet()) {
                String s1 = staticResourceMap.get(s);
                if (s.contains("static-resource")) {
                    // 找到匹配项,修改为阿里云oos存储地址
                    for (String string : imageUrl.keySet()) {
                        if (string.equals(s)){
                            staticResourceMap.remove(s);
                            staticResourceMap.put(imageUrl.get(s), s1);
                        }
                    }
                }
            }
            String panelData = panelGroupRequest.getPanelData();
            JSONArray jsonArray = JSON.parseArray(panelData);
            // 遍历数组,寻找特定的 propValue 值
            for (int i = 0; i < jsonArray.size(); i++) {
                JSONObject obj = jsonArray.getJSONObject(i);
                if (obj.containsKey("propValue") && obj.getString("propValue").contains("/static-resource/")) {
                    // 找到匹配项,添加前缀
                    obj.put("propValue", imageUrl.get(obj.get("propValue")));
                }
            }
            panelGroupRequest.setPanelData(JSON.toJSONString(jsonArray));
            panelGroupRequest.setStaticResource(gson.toJson(staticResourceMap));
            requestTemplate.setPanelInfo(gson.toJson(panelGroupRequest));
        }
 





















