阿里云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. 注册阿里云 注册入口
    阿里云OSS对象存储服务_第1张图片

  2. 搜索OSS 开通OSS
    阿里云OSS对象存储服务_第2张图片阿里云OSS对象存储服务_第3张图片
    阿里云OSS对象存储服务_第4张图片

  3. 打开控制台找到API文档
    阿里云OSS对象存储服务_第5张图片

  4. 创建 Bucket 一般一个项目创建一个
    阿里云OSS对象存储服务_第6张图片

  5. 测试文件上传
    阿里云OSS对象存储服务_第7张图片

2.2.2 阿里云创建 accessKey

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

阿里云OSS对象存储服务_第8张图片

  1. 选择创建子用户 如果不行就直接使用 AccessKey。不建议使用主账户,权限太高
    阿里云OSS对象存储服务_第9张图片

  2. 创建用户
    阿里云OSS对象存储服务_第10张图片

  3. 使用 子用户AccessKey
    阿里云OSS对象存储服务_第11张图片

  4. 给用户分配权限
    阿里云OSS对象存储服务_第12张图片

  5. 获取用户的 accessKeyId accessKeySecret
    阿里云OSS对象存储服务_第13张图片

2.3 Java代码使用OSS

2.3.1 基本用法

  1. 导入依赖
<dependency>
    <groupId>com.aliyun.ossgroupId>
    <artifactId>aliyun-sdk-ossartifactId>
    <version>3.10.2version>
dependency>
  1. 写测试代码 获取代码中需要的参数
    阿里云OSS对象存储服务_第14张图片
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.miniogroupId>
    <artifactId>minioartifactId>
    <version>8.3.0version>
dependency>
<dependency>
    <groupId>me.tongfeigroupId>
    <artifactId>progressbarartifactId>
    <version>0.5.3version>
dependency>
<dependency>
    <groupId>com.squareup.okhttp3groupId>
    <artifactId>okhttpartifactId>
    <version>4.8.1version>
dependency>
<dependency>
    <groupId>org.jetbrains.kotlingroupId>
    <artifactId>kotlin-stdlibartifactId>
    <version>1.3.70version>
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.bootgroupId>
    <artifactId>spring-boot-configuration-processorartifactId>
    <optional>trueoptional>
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();
    }
}

你可能感兴趣的:(阿里云,java,前端)