阿里云OSS对象存储服务

1 文件上传实战

后台代码

@RestController
@RequestMapping("/brand")
public class BrandController {
    @Autowired
    private IBrandService bs;
    @PostMapping("/uploadPic")
    //文件上传的方法,上传成功后需要把文件上传到哪交给前端
    public String uploadPic(MultipartFile brandPic) throws IOException {
        //把图片保存起来。一般情况下我们会专门创建一个文件夹来保存上传的图片
        String oldName=brandPic.getOriginalFilename();//获取到上传的文件的原始文件名
        String newName = UUID.randomUUID().toString()+oldName;
        File targetFile=new File("d:/uploadImg/"+newName);
        brandPic.transferTo(targetFile);//把图片复制到某个位置
        return newName;
    }
}

文件上传成功后可以通过URL访问到图片:

spring:
  resources:
    static-locations: file:D:\myImg

访问的路径是:http://ip:port/appName/图片名称

2 OSS

2.1 OSS引言

文件存储的常用方式

  1. 保存在当前服务器中 优点:简单 缺点:

    • 保存数据量有限
    • 分布式 集群下不能使用
  2. 通过第三方文件存储技术 FastDFS MinIO

    对象存储服务 指的就是文件存储 例如:视频 文件 音频图片等

    优点:可以根据自己的需求灵活定制

    缺点:

    • 成本高
    • 环境搭建复杂
    • 后期需要维护
  3. 使用阿里云 亚马逊 百度等公司提供OSS服务(对象存储服务) 中小型企业 优点:简单快速,成本低

2.2 OSS基本设置

2.2.1 开通

  1. 注册阿里云 注册入口
    在这里插入图片描述

  2. 搜索OSS 开通OSS
    在这里插入图片描述在这里插入图片描述
    在这里插入图片描述

  3. 打开控制台找到API文档
    在这里插入图片描述

  4. 创建 Bucket 一般一个项目创建一个
    在这里插入图片描述

  5. 测试文件上传
    在这里插入图片描述

2.2.2 阿里云创建 accessKey

  1. 在阿里云上创建 accessKey (秘钥)

在这里插入图片描述

  1. 选择创建子用户 如果不行就直接使用 AccessKey。不建议使用主账户,权限太高
    在这里插入图片描述

  2. 创建用户
    在这里插入图片描述

  3. 使用 子用户AccessKey
    在这里插入图片描述

  4. 给用户分配权限
    在这里插入图片描述

  5. 获取用户的 accessKeyId accessKeySecret
    在这里插入图片描述

2.3 Java代码使用OSS

2.3.1 基本用法

  1. 导入依赖
<dependency>
    <groupId>com.aliyun.oss</groupId>
    <artifactId>aliyun-sdk-oss</artifactId>
    <version>3.10.2</version>
</dependency>
  1. 写测试代码 获取代码中需要的参数
    在这里插入图片描述
public class OSSTest {
    public static void main(String[] args) throws FileNotFoundException {
        //1. 创建连接
        // Endpoint以北京为例,其它Region请按实际情况填写。
        String endpoint = "https://oss-cn-beijing.aliyuncs.com";
        // 阿里云主账号AccessKey拥有所有API的访问权限,风险很高。强烈建议您创建并使用RAM账号进行API访问或日常运维,请登录RAM控制台创建RAM账号。
        // 这里填写上面获取的 accessKeyId、 accessKeySecret
        String accessKeyId="xxxxx";
        String accessKeySecret = "xxx";

        OSS client = new OSSClientBuilder().build(endpoint, accessKeyId, accessKeySecret);

        //2. 通过client发起上传文件的请求
        String bulkName ="bz-mall-admin2";
        String key=UUID.randomUUID().toString()+"git-bash.png"; //文件的唯一标识,通常是不重复的文件名
        InputStream in = new FileInputStream("D:/git-bash.png");

    // 上传文件到指定的存储空间(bucketName)并将其保存为指定的文件名称(key)。
        client.putObject(bulkName, key, in);

        //3. 关闭连接
        client.shutdown();
        
        // https://bulkName+"."+endpoint+"/"+key 就是文件的外网访问路径
        // https://bz-mall-admin.oss-cn-beijing.aliyuncs.com/拼接了uuid的文件名
    }
}

2.3.2 整合文件上传 Controller

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-7669LQco-1659523644686)(D:\课件\Java\百知\javaEE\后期项目\后期项目OSS\format_webp (15)].jpg)

  1. 定义配置类 创建 OSSUtils。上传视频为例
package com.qhx.utils;

import com.aliyun.oss.OSS;
import com.aliyun.oss.OSSClientBuilder;
import org.apache.commons.io.FilenameUtils;
import org.springframework.web.multipart.MultipartFile;

import java.io.*;
import java.util.UUID;

public class OSSUtils {
    /**
     *  这里填写自己的accesskeyId和secret,尽量使用子账号的。主账号的权限太高
     */
    private static String ACCESSKEYID = "xxxx";
    private static String SECRET = "xxxxx";

    public static String upload(String filename,InputStream inputStream){
        // Endpoint以杭州为例,其它Region请按实际情况填写。
        String endpoint = "oss-cn-hangzhou.aliyuncs.com";
        // bucketName
        String bucketName = "yingxue-api-qhx";
        // 创建OSSClient实例。
        OSS ossClient = new OSSClientBuilder().build(endpoint, ACCESSKEYID, SECRET);
        // 填写Bucket名称,例如examplebucket。
        // 填写文件名。文件名包含路径,不包含Bucket名称。例如exampledir/exampleobject.txt。
        ossClient.putObject(bucketName, filename, inputStream);
        // 关闭OSSClient。
        ossClient.shutdown();
        // 返回了视频的访问路径
        return "https://" + bucketName + "." + endpoint + "/" + filename;
    }

    // 上传文件  参数是file,可以是图片、视频等
    public static String upload(MultipartFile file) throws IOException {
        // Endpoint以杭州为例,其它Region请按实际情况填写。
        String endpoint = "oss-cn-hangzhou.aliyuncs.com";
        // bucketName
        String bucketName = "yingxue-api-qhx";
        // 创建OSSClient实例。
        OSS ossClient = new OSSClientBuilder().build(endpoint, ACCESSKEYID, SECRET);

        // 获取文件原始名称
        String originalFileName = file.getOriginalFilename();
        // 获取文件后缀
        String ext = FilenameUtils.getExtension(originalFileName);
        // 生成uuid并去除-
        String uuidFileName = UUID.randomUUID().toString().replace("-","");
        // 生成uuid文件名名称
        String newFileName = uuidFileName + "." + ext;
        // 获取流
        InputStream in = file.getInputStream();
        // 填写文件名。文件名包含路径,不包含Bucket名称。例如exampledir/exampleobject.txt。
        ossClient.putObject(bucketName,newFileName, in);
        // 关闭OSSClient。
        ossClient.shutdown();

        System.out.println("新文件名为:" + newFileName);
        System.out.println("访问路径:"+"https://" + bucketName + "." + endpoint + "/" + newFileName);
		// 返回了视频的访问路径
        return "https://" + bucketName + "." + endpoint + "/" + newFileName;
    }

    // 视频获取封面 随机截取一帧当封面
    public static String getCover(String url){
        return url + "?x-oss-process=video/snapshot,t_30000,f_jpg,w_0,h_0,m_fast,ar_auto";
    }
}
  1. 写Controller
@PostMapping("/user/videos")
public Video uploadFile(MultipartFile file,
            @RequestParam("title") String title,@RequestParam("intro") String intro,
            @RequestParam("category_id")Integer cid,HttpServletRequest request) throws Exception{
        String bucketName = "yingxue-api-qhx";
        // 获取文件原始名称
        String originalFileName = file.getOriginalFilename();
        log.info("接收文件名称:"+originalFileName);
        log.info("接受视频信息:title="+title+" intro="+intro+" cid="+cid);
        log.info("类别id:"+cid);
        log.info("文件大小:"+file.getSize());
     
        String url = OSSUtils.upload(file);
        // 阿里云oss截取视频某一帧作为封面
        String cover = OSSUtils.getCover(url);
        log.info("封面地址:"+cover);

        // 设置视频信息
        Video newvideo = new Video();
        newvideo.setCover(cover);  // 封面地址
        newvideo.setCategoryId(cid); // 类别id
        newvideo.setTitle(title);  // 视频标题
        newvideo.setIntro(intro);  // 视频简介
        newvideo.setLink(url);  // 视频地址
        newvideo.setCreatedAt(LocalDateTime.now());
        newvideo.setUpdatedAt(LocalDateTime.now());
        // 获取用户信息
        User user = (User) request.getAttribute("user");
        newvideo.setUid(user.getId());  // uid
        newvideo.setLikes(0);  // 点赞数

        // 添加视频
        Video resultVideo = videoClient.publish(newvideo);
        return resultVideo;
    }

3 Minio

MinIO是一个基于Apache License v2.0开源协议的对象存储服务。非常适合于存储大容量非结构化的数据,例如图片、视频、日志文件、备份数据等,而一个对象文件可以是任意大小,从几kb到最大5T不等。MinIO是一个非常轻量的服务,可以很简单的和其他应用的结合,类似 NodeJS, Redis 或者 MySQL。

对象存储服务(Object Storage Service,OSS)是一种海量、安全、低成本、高可靠的云存储服 务,适合存放任意类型的文件。容量和处理能力弹性扩展,多种存储类型供选择,全面优化存储成 本。

对于中小型企业,如果不选择存储上云,那么 Minio 是个不错的选择,麻雀虽小,五脏俱全。

1.安装

#安装wget
yum install -y wget
# 使用wget下载minio可执行文件
wget -P /opt http://dl.minio.org.cn/server/minio/release/linux-amd64/minio 
chmod +x minio 
#启动minio server服务,指定数据存储目录/mnt/data 
./minio server /mnt/data

默认用户名密码minioadmin:minioadmin,修改默认用户名密码可以使用:

export MINIO_ROOT_USER=admin 
export MINIO_ROOT_PASSWORD=12345678

控制台监听端口是动态生成的,可以通过–console-address ":port"指定静态端口

./minio server --console-address ":50000" /mnt/data

访问minio控制台: http://192.168.239.105:50000/dashboard

2.Minio客户端使用

MinIO Client (mc)为ls,cat,cp,mirror,diff,find等UNIX命令提供了一种替代方案。

2.1 安装客户端mc

wget http://dl.minio.org.cn/client/mc/release/linux-amd64/mc 
chmod +x mc  
mv mc /usr/local/sbin/

2.2 配置mc

# 查询mc host配置 
mc config host ls 
# 添加minio服务 
mc config host add host名称 http://192.168.239.105:9000 账号 密码
# 删除host 
mc config host remove host名称

2.3 上传下载

# 查询minio服务上的所有buckets(文件和文件夹) 
mc ls host名称 
#上传文件 
mc cp 上面文件地址 host名称/bucket名称/
# 下载文件 
mc cp minio-server/mydir/fox/fox.jpg /tmp/ 
#删除文件 
mc rm minio-server/mydir/fox/fox.jpg 

2.4 Bucket管理

# 创建bucket 
mc mb minio-server/bucket01 
# 删除bucket 
mc rb minio-server/bucket02 
# bucket不为空,可以强制删除 慎用 
mc rb --force minio-server/bucket01
#查询bucket03磁盘使用情况 
mc du minio-server/bucket03

2.5 用户管理

mc admin user --help 
#新建用户 
mc admin user add minio-server fox 
mc admin user add minio-server fox02 12345678 
#查看用户 
mc admin user list minio-server 
#禁用用户 
mc admin user disable minio-server fox02 
#启用用户 
mc admin user enable minio-server fox02 
#查看用户信息 
mc admin user info minio-server fox 
#删除用户 
mc admin user remove minio-server fox02

#列出MinIO上的所有固定策略 
mc admin policy list minio-server 
# 查看plicy信息 
mc admin policy info minio-server readwrite

2.6添加新的策略

编写策略文件:/root/baizhi.json

{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Effect": "Allow",
            "Action": [
                "s3:GetBucketLocation",
                "s3:GetObject"
            ],
            "Resource": [
                "arn:aws:s3:::host名字"
            ]
        },
        {
            "Effect": "Allow",
            "Action": [
                "s3:*"
            ],
            "Resource": [
                "arn:aws:s3:::host名字/*"
            ]
        }
    ]
}
"Action": [ 
  "s3:GetBucketLocation", 
  "s3:ListBucket", 
  "s3:GetObject", 
  "s3:PutObject", 
  "s3:DeleteObject" 
]

将baizhi.json添加到策略数据库

# 添加新的策略 
mc admin policy add minio-server baizhi-admin /root/baizhi.json 
mc admin policy list minio-server
mc admin user add minio-server fox03 12345678 
# 设置用户的访问策略 
mc admin policy set minio-server baizhi-admin user=fox03

测试:fox03/12345678 登录minio控制台http://192.168.3.14:50000/,只能操作baizhihost的bucket

3.java操作minio

  1. 引入依赖
<dependency>
    <groupId>io.minio</groupId>
    <artifactId>minio</artifactId>
    <version>8.3.0</version>
</dependency>
<dependency>
    <groupId>me.tongfei</groupId>
    <artifactId>progressbar</artifactId>
    <version>0.5.3</version>
</dependency>
<dependency>
    <groupId>com.squareup.okhttp3</groupId>
    <artifactId>okhttp</artifactId>
    <version>4.8.1</version>
</dependency>
<dependency>
    <groupId>org.jetbrains.kotlin</groupId>
    <artifactId>kotlin-stdlib</artifactId>
    <version>1.3.70</version>
</dependency>
  1. 文件上传:
@Test
public void testUpload()
    throws IOException, NoSuchAlgorithmException, InvalidKeyException {
    try {
        // Create a minioClient with the MinIO server playground, its access key and secret key.
        MinioClient minioClient = MinioClient
            .builder()
            .endpoint("http://192.168.239.106:9000")
            .credentials("zhangsan", "12345678")
            .build();
        // 创建bucket
        String bucketName = "bzmall-2015";
        // 上传文件
        minioClient.uploadObject(UploadObjectArgs.builder()
                                 .bucket(bucketName)
                                 .object("test.png")
                                 .filename("D:\\test.png")
                                 .build());
        System.out.println("上传文件成功");
    } catch (MinioException e) {
        System.out.println("Error occurred: " + e);
        System.out.println("HTTP trace: " + e.httpTrace());
    }
}
  1. 文件下载
@Test
public void testDownload() {
    // Create a minioClient with the MinIO server playground, its access key and secret key.
    MinioClient minioClient = MinioClient
        .builder()
        .endpoint("http://192.168.239.106:9000")
        .credentials("zhangsan", "12345678")
        .build();
    // Download object given the bucket, object name and output file name
    try {
        minioClient.downloadObject(DownloadObjectArgs
                                   .builder().bucket("bzmall-2015")
                                   .object("test.png")
                                   .filename("d://test2.png")
                                   .build());
    } catch (Exception e) {
        e.printStackTrace();
    }
}

4.Spring boot整合minio

构建MinioClient对象,并交给spring管理

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-configuration-processor</artifactId>
    <optional>true</optional>
</dependency>

yml文件:

//yml 
minio: 
  endpoint: http://192.168.3.14:9000 
  accesskey: admin 
  secretKey: 12345678

读取配置文件的类:

@Data
@Component
@ConfigurationProperties(prefix = "minio")
public class MinioProperties {
    private String endpoint;
    private String accessKey;
    private String secretKey;
}

配置类:

@Configuration
public class MinioConfig {
    @Autowired
    private MinioProperties minioProperties;

    @Bean
    public MinioClient minioClient() {
        MinioClient minioClient = MinioClient.builder()
            .endpoint(minioProperties.getEndpoint())
            .credentials(minioProperties.getAccessKey(), minioProperties.getSecretKey())
            .build();
        return minioClient;
    }
}

文件上传:

@Autowired
private MinioClient minioClient;
@Value("${minio.bucketName}")
private String bucketName;
@Value("${minio.endpoint}")
private String endpoint;
@PostMapping("/uploadPic")
//文件上传的方法,上传成功后需要把文件上传到哪交给前端
public ResultEntity uploadPic(MultipartFile brandPic) throws IOException {
    String orgfileName = brandPic.getOriginalFilename();
    String newName= UUID.randomUUID().toString()+orgfileName;
    try {
        //文件上传
        InputStream in = brandPic.getInputStream();
        minioClient.putObject(PutObjectArgs
                              .builder()
                              .bucket(bucketName)
                              .object(newName)
                              .stream(in, brandPic.getSize(), -1)
                              .contentType(brandPic.getContentType())
                              .build());
        in.close();
    } catch (Exception e) {
        return ResultEntity.error("上传失败");
    }
    return ResultEntity.ok(endpoint+"/"+bucketName+"/"+newName);
}

文件下载:

@GetMapping("/download/{fileName}")
public void download(HttpServletResponse response,
                     @PathVariable("fileName") String fileName) throws IOException {
    InputStream in = null;
    try {
        // 获取对象信息
        StatObjectResponse stat = minioClient.statObject(StatObjectArgs.
                                                         builder().
                                                         bucket(bucketName).
                                                         object(fileName).
                                                         build());
        response.setContentType(stat.contentType());
        response.setHeader("Content-Disposition", "attachment;filename=" + URLEncoder.encode(fileName, "UTF-8"));
        //文件下载
        in = minioClient.getObject(
            GetObjectArgs.
            builder().
            bucket(bucketName).
            object(fileName).
            build());
        IOUtils.copy(in, response.getOutputStream());
        in.close();
    } catch (Exception e) {
        e.printStackTrace();
    }
}
                                       object(fileName).
                                                         build());
        response.setContentType(stat.contentType());
        response.setHeader("Content-Disposition", "attachment;filename=" + URLEncoder.encode(fileName, "UTF-8"));
        //文件下载
        in = minioClient.getObject(
            GetObjectArgs.
            builder().
            bucket(bucketName).
            object(fileName).
            build());
        IOUtils.copy(in, response.getOutputStream());
        in.close();
    } catch (Exception e) {
        e.printStackTrace();
    }
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值