在项目中使用阿里云oss实现文件上传功能

文章目录

一、需求分析

二、设计思路

三、实现步骤

3.1 预处理:先在官网上,完成OOS的配置

3.1.1 购买OSS服务。

3.1.2 创建Bucket

3.1.3  Bucket参数的配置

3.2 Java程序中使用OSS:查询开发文档

3.2.1 在控制台页面,找到OSS的Java开发文档

3.2.2 在中央仓库找到OSS坐标

3.2.3 查询文档,了解基本操作

3.2.4 参数的获取(AK参数的获取)

​编辑

3.2.5 制作自己的操作OSS的工具类

3.2.6 编写上传文件接口

四、总结


一、需求分析

在博客项目的前台中,需要完成对个人资料的更新,这其中包含对用户头像的更新,其实也就是替换掉原来的头像,另外在后台中需要在写博文中对缩略图以及文章正文中图片的添加,以及能对博文的缩略图以及正文中的图片进行修改。


二、设计思路

先来谈一下原来的处理方式,进而引出为什么现在需要这种处理方式。

因为之前做过锋迷商城这个项目,所以还是有在数据库中存图片地址的这种意识,只不过那个项目比较拉,图片都在前端项目里,当然咯,那个项目只是涉及到前台,也就是说仅仅是图片的显示,直接从数据库中查询到图片地址,然后到前端项目中去找到对应的图片即可,没有涉及到后台,也就是没有涉及到对图片的上传,另外它这个项目前台中,也没有修改图片之类的,仅仅只是单纯的对图片进行显示,看似也没有多大问题,图片存死也没啥问题,但是一旦需要扩充就比较麻烦了,需要手动的往前端项目中添加图片。另外如果我此时需要上传图片呢,如果是在前端工程中将图片写死,那么我就只能上传前端项目中的图片,因为只有这样地址才是有效的,因为你如果上传的是其它地方的图片,图片地址在前端项目中里面找不到,即使可能可以通过你选择本地图片,然后将图片保存到前端项目中,然后再返回图片地址。

其实这里总结来说在锋迷商城项目中是将图片存到前端工程里。

存到前端工程里面,当然有其优点,比如说:

1. 图片的加载速度更快,因为是直接从本地获取,而不需要访问网络。

2. 安全性高,因为图片存储到本地,没有外界能直接访问图片的接口。

3. 可靠性高,因为存储到本地,不会受到网络,以及服务器故障的影响。

总的来说优点有三点:加载快、安全、稳定。

但其缺点也很明显,就比如:

1. 存储空间受限,因为是存储到本地,所以可能会受到存储空间的限制。

2. 难以扩展,因为受到存储空间的限制,因此当面对大量的图片时,可能需要修改存储位置以及修改代码。

3. 可维护性差,因为存储到前端工程中,本质上是存储到本地磁盘中,所以就不能保证唯一的文件地址可以生效了,就比如说我的前端工程,到其它电脑上面,路径可能就会失效,就比如说在我的电脑上面地址是,c/前端项目/images自然来说项目中代码也是这个,虽然可能会在代码中写相对路径,代码中地址是/images,可是另外那台电脑连c/前端工程这个目录都没有的话,就找不到对应的文件了,因此如果存在多个开发者,就需要多交流沟通,遵循路径规范,增加维护难度。

那么如果将文件存到云端,就能解决这些问题了。

1、因为存储到云端,因为云端一般来说有着巨大的存储空间,因此一般来说不会因为存储空间的问题而发愁。

2、存储到云端后,云端会响应回来一个唯一的URL地址,无论在哪台电脑上面都能正确访问。

当然也是有缺点的,存到本地的优点的反面就是存到云端的缺点,就比如说:

1. 因为需要访问网络,可能文件的加载速度就相较于本地会慢一些。

2. 风险高了,因为存到了云端,因此存在着访问接口,因此安全性也就低一些,需要在云端,做好安全措施。

3. 因为和云服务器挂钩,因此可能会受到云服务器的影响,比如说云服务器发生故障,或者网络不好等问题。

对比了它两,但是总的来说保存到本地的缺点明显,保存的云端的优势明显,即使存在问题,也可以通过一些措施进行预防和解决。

好了,正是比较了它两,得知了存储到云端的优点,我才会选择将图片保存到云端,保存到云端也很多厂商都可以做到,七牛云、阿里云、腾讯云都可以,其实这个技术就叫做OSS(对象存储服务),我还是比较喜欢使用阿里云的,下面我就来基于阿里云的OSS,如何实现文件的上传功能,当然这里不仅可以是文件的上传,也可以是文件的下载,以及文件夹的创建等许多需求,具体实现步骤可以参考阿里云的文档。


三、实现步骤

3.1 预处理:先在官网上,完成OOS的配置

3.1.1 购买OSS服务。

使用阿里云OSS之前,肯定得先到阿里云官网,购买OSS服务,这是使用任何服务的第一步。进入到阿里云OSS页面的步骤如下图所示:

 然后选择立即购买:

然后就是规格的选择,第一次用的小伙伴就可以完全按照我下面的配置进行选择,这种配置完全够简单开发了,如果以后还有另外的需求,查阅阿里云的文档,进行配置即可,其实也就是默认配置,看得出其实OSS服务还是挺便宜的,半年才几块钱。

3.1.2 创建Bucket

Bucket其实就是文件盘,相当于电脑上面的C盘、D盘,里面可以放各式各样的文件,文件夹,当然这一步也可以通过Java程序进行创建,具体创建步骤翻阅开发文档,其实没必要,我这里就需要一个现成的盘,往里面存图片就行了。因此创建一个Bucket,步骤如下:

1. 先进入OSS的控制台页面,然后按如下步骤,先找到创建Bucket的入口

3.1.3  Bucket参数的配置

 除了我通过序号进行说明的,其它配置不需要管,默认的就行 

3.2 Java程序中使用OSS:查询开发文档

3.2.1 在控制台页面,找到OSS的Java开发文档

3.2.2 在中央仓库找到OSS坐标

 将坐标复制到maven中

3.2.3 查询文档,了解基本操作

 

3.2.4 参数的获取(AK参数的获取)

其实这个和oss本身没有关系,只是调用接口的时候,都需要凭证才能进行调用,完成相关操作。

下面我来说一下,AK的获取:

1. 可以通过本身自己root用户进行创建获取

也可以通过RAM子用户进行AK的创建

 其实就是一个账号,可以有多个用户,一个主用户,多个分用户,为了安全起见,可以通过使用分用户来创建AK,并对这个分用户提供较少的权限,例如在这里我只需要给RAM用户提供操作oss服务的权限就行了,当然一个用户也可以有多个AK。

下面是RAM用户的创建步骤:

​​​​​​​

 

 最重要的AK两个值的获取:

 

 

 如果错过了,没有保存,只能重新创建一个AK:

 

 

 为当前RAM用户设置权限: 

 

3.2.5 制作自己的操作OSS的工具类

1. 先是属性配置类的创建,使得能在application.yml文件中,对oss所需的一些参数进行配置

@Component
@Data
@ConfigurationProperties(prefix = "oss")
public class OSSProperty {
    private String endpoint;
    private String accessKeyId;
    private String accessKeySecret;
    private String bucketName;
}

在application.yml文件中,完成配置:

oss:
  endpoint:
  accessKeyId:
  accessKeySecret:
  bucketName: 

 2. 工具类的封装

@Component
public class OSSUtils {


    @Autowired
    private OSSProperty ossProperty;

    //创建Bucket
    public void  createBucket(String bucketName){
        // Endpoint以华东1(杭州)为例,其它Region请按实际情况填写。
        String endpoint = ossProperty.getEndpoint();
        // 阿里云账号AccessKey拥有所有API的访问权限,风险很高。强烈建议您创建并使用RAM用户进行API访问或日常运维,请登录RAM控制台创建RAM用户。
        String accessKeyId = ossProperty.getAccessKeyId();
        String accessKeySecret = ossProperty.getAccessKeySecret();
        // 填写Bucket名称,例如example bucket。

        // 创建OSSClient实例。
        OSS ossClient = new OSSClientBuilder().build(endpoint, accessKeyId, accessKeySecret);

        try {
            // 创建存储空间。
            ossClient.createBucket(bucketName);

        } catch (OSSException oe) {
            System.out.println("Caught an OSSException, which means your request made it to OSS, "
                    + "but was rejected with an error response for some reason.");
            System.out.println("Error Message:" + oe.getErrorMessage());
            System.out.println("Error Code:" + oe.getErrorCode());
            System.out.println("Request ID:" + oe.getRequestId());
            System.out.println("Host ID:" + oe.getHostId());
        } catch (ClientException ce) {
            System.out.println("Caught an ClientException, which means the client encountered "
                    + "a serious internal problem while trying to communicate with OSS, "
                    + "such as not being able to access the network.");
            System.out.println("Error Message:" + ce.getMessage());
        } finally {
            if (ossClient != null) {
                ossClient.shutdown();
            }
        }
    }

    //上传文件
    public String uploadFile(MultipartFile file){
        String bucketName = ossProperty.getBucketName();
        // Endpoint以华东1(杭州)为例,其它Region请按实际情况填写。
        String endpoint = ossProperty.getEndpoint();
        // 阿里云账号AccessKey拥有所有API的访问权限,风险很高。强烈建议您创建并使用RAM用户进行API访问或日常运维,请登录RAM控制台创建RAM用户。
        String accessKeyId = ossProperty.getAccessKeyId();
        String accessKeySecret = ossProperty.getAccessKeySecret();
        String fileName = "";
        fileName = file.getOriginalFilename();
        String url = "";
        String path = PathUtils.generateFilePath(fileName);
        // 创建OSSClient实例。
        OSS ossClient = new OSSClientBuilder().build(endpoint, accessKeyId, accessKeySecret);
        try {
            ossClient.putObject(bucketName, path, file.getInputStream());
            url = "https://"+bucketName+"."+endpoint.substring(8) + "/" + path;
            return url;
        } catch (OSSException oe) {
            System.out.println("Caught an OSSException, which means your request made it to OSS, "
                    + "but was rejected with an error response for some reason.");
            System.out.println("Error Message:" + oe.getErrorMessage());
            System.out.println("Error Code:" + oe.getErrorCode());
            System.out.println("Request ID:" + oe.getRequestId());
            System.out.println("Host ID:" + oe.getHostId());
        } catch (ClientException ce) {
            System.out.println("Caught an ClientException, which means the client encountered "
                    + "a serious internal problem while trying to communicate with OSS, "
                    + "such as not being able to access the network.");
            System.out.println("Error Message:" + ce.getMessage());
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            if (ossClient != null) {
                ossClient.shutdown();
            }
        }
        return "";
    }

}

关键的三步:

// 创建OSSClient实例。
OSS ossClient = new OSSClientBuilder().build(endpoint, accessKeyId, accessKeySecret);
 //上传文件关键代码
 //提供bucket名称、上传之后存到OSS中的文件路径、文件输入流
 ossClient.putObject(bucketName, path, file.getInputStream());

 最后文件的云地址:

//文件的云地址
url = "https://"+bucketName+"."+endpoint.substring(8) + "/" + path;

这是参看文件列表中文件的文件详情发现的,地址格式

另外这里为了使得保存在OSS中的位置显得有层次性,并且路径唯一,对于文件地址的表示,采用当前时间(年/月/日的格式)+ UUID + 后缀名的方式进行表示。下面是路径生成的工具类:

public class PathUtils {

    public static String generateFilePath(String fileName){
        //根据日期生成路径   2022/1/15/
        SimpleDateFormat sdf = new SimpleDateFormat("yyyy/MM/dd/");
        String datePath = sdf.format(new Date());
        //uuid作为文件名
        String uuid = UUID.randomUUID().toString().replaceAll("-", "");
        //后缀和文件后缀一致
        int index = fileName.lastIndexOf(".");
        // test.jpg -> .jpg
        String fileType = fileName.substring(index);
        return new StringBuilder().append(datePath).append(uuid).append(fileType).toString();
    }
}

3.2.6 编写上传文件接口

 controller层:

@RestController
@Api(tags = "上传图片",description = "完成图片上传接口")
public class UploadController {

    @Autowired
    private UploadImgService uploadImgService;

    @PostMapping("/upload")
    @LogPrint(BusinessName = "上传图片接口")
    @ApiOperation(value = "上传图片",notes = "上传图片到云存储器")
    @ApiImplicitParam(name = "img", value = "图片文件", required = true)
    public ResponseResult uploadImg(MultipartFile img){
        try {
            return uploadImgService.uploadImg(img);
        } catch (Exception e) {
            e.printStackTrace();
            throw new RuntimeException("文件上传失败");
        }
    }

}

service层:

service接口:

public interface UploadImgService {
    ResponseResult uploadImg(MultipartFile img);
}

service实现类:

主要就是对文件类型的检查,虽然前端已经做了防护,但为了防止懂技术的人拿到后端接口直接调用,因此还得检查一遍,然后就是直接调用工具类的上传文件方法即可。

@Service
public class UploadImgServiceImpl implements UploadImgService {
    @Autowired
    private OSSUtils ossUtils;


    @Override
    public ResponseResult uploadImg(MultipartFile img) {
        String imgName = img.getOriginalFilename();
        if (!imgName.endsWith("jpg") && !imgName.endsWith("png")) {
            throw new SystemException(AppHttpCodeEnum.FILE_TYPE_ERROR);
        }
        return ResponseResult.okResult(ossUtils.uploadFile(img));
    }
}

最后将返回的文件的云地址,存入到数据库就行了。 


四、总结

1. 慢慢的增强查询文档的能力,这一次的OSS的使用,其实也是锻炼查询文档的能力。

2. OSS的具体使用,可以简化成以下几步:

    1. 购买OSS服务,创建好Bucket

    2. 获取AK(可以通过root或者ARM用户进行获取)

    3. 在程序中完成oss所需的参数配置包括AK参数的配置,以及上传文件功能的封装

  • 7
    点赞
  • 23
    收藏
    觉得还不错? 一键收藏
  • 7
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 7
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值