文章目录

  • 1. 概念
  • 2. 数据准备
  • 3. 实战
  • 4. 总结


1. 概念

  • 「OSS」的英文全称是Object Storage Service,翻译成中文就是「对象存储服务」,官方一点解释就是对象存储是一种使用HTTP API存储和检索非结构化数据和元数据对象的工具
  • 白话文解释就是将系统所要用的文件上传到云硬盘上,该云硬盘提供了文件下载、上传等一列服务,这样的服务以及技术可以统称为OSS,业内提供OSS服务的厂商很多,知名常用且成规模的蓝队云等
  • oss文件预览时This XML file does not appear to have any style information ass oss文件是什么_html

  • OSS相关的术语
  • 存储空间(Bucket): 存储空间是您用于存储对象(Object)的容器,所有的对象都必须隶属于某个存储空间
  • 对象/文件(Object): 对象是 OSS 存储数据的基本单元,也被称为OSS的文件。对象由元信息(Object Meta)、用户数据(Data)和文件名(Key)组成。对象由存储空间内部唯一的Key来标识
  • 地域(Region): 地域表示 OSS 的数据中心所在物理位置。您可以根据费用、请求来源等综合选择数据存储的地域。详情请查看OSS已经开通的Region
  • 访问域名(Endpoint): Endpoint 表示OSS对外服务的访问域名。OSS以HTTP RESTful API的形式对外提供服务,当访问不同地域的时候,需要不同的域名。通过内网和外网访问同一个地域所需要的域名也是不同的。具体的内容请参见各个Region对应的Endpoint,例如杭州 Region 的外网 Endpoint 是 oss-cn-hangzhou.aliyuncs.com,内网 Endpoint 是 oss-cn-hangzhou-internal.aliyuncs.com
  • 访问密钥(AccessKey): AccessKey,简称 AK,指的是访问身份验证中用到的AccessKeyId 和AccessKeySecret。OSS通过使用AccessKeyId 和AccessKeySecret对称加密的方法来验证某个请求的发送者身份。AccessKeyId用于标识用户,AccessKeySecret是用户用于加密签名字符串和OSS用来验证签名字符串的密钥,其中AccessKeySecret 必须保密,对于OSS来说,AccessKey的来源有:
  • Bucket 的拥有者申请的 AccessKey
  • 被 Bucket 的拥有者通过 STS 授权给第三方请求者的 AccessKey
  • 被Bucket 的拥有者通过 RAM 授权给第三方请求者的 AccessKey

2. 数据准备

免费的话可以用七牛云,这里我是申请了阿里云的OSS,这里主要是讲一下我们项目需要用的一些oss信息,等下yml配置需要用到

  • access-key-id和access-key-secret
  • oss文件预览时This XML file does not appear to have any style information ass oss文件是什么_java_02

  • bucket和endpoint
  • oss文件预览时This XML file does not appear to have any style information ass oss文件是什么_html_03

  • 上传的文件夹
  • oss文件预览时This XML file does not appear to have any style information ass oss文件是什么_上传_04

3. 实战

  • 依赖
<!-- mvc的自动配置 -->
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-web</artifactId>
</dependency>

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

<!-- oss-->
<dependency>
    <groupId>com.aliyun.oss</groupId>
    <artifactId>aliyun-sdk-oss</artifactId>
    <version>3.10.2</version>
</dependency>
  • yml文件配置
# oss
oss:
  access-key-id: xxx
  access-key-secret: xxx 
  bucket: typora-aliyun
  endpoint: oss-cn-shanghai.aliyuncs.com
  dir: file/
@Component
@ConfigurationProperties(prefix = "oss")
public class OSSProperties{

    private String endpoint;

    private String accessKeyId;

    private String accessKeySecret;

    private String bucket;

    private String dir;
	
	//省略getset
}
  • 配置类
@Configuration
public class OSSConfig {

    @Autowired
    private OSSProperties ossProperties;

    @Bean
    public OSSClient ossClient(){
        OSS ossClient = new OSSClientBuilder().build(ossProperties.getEndpoint(),
                ossProperties.getAccessKeyId(),
                ossProperties.getAccessKeySecret());
        return (OSSClient) ossClient;
    }
}
  • 工具类
@Component
public class OSSUtil {

    @Autowired
    private OSSProperties ossProperties;

    @Autowired
    private OSSClient ossClient;

    /**
     * 上传图片
     *
     * @param file
     * @param fileName
     * @return
     * @throws IOException
     */
    public String uploadImg2Oss(MultipartFile file, String fileName) throws IOException {
        try {
            InputStream inputStream = file.getInputStream();
            this.uploadFile2OSS(inputStream, fileName);
            String url = "https://" + ossProperties.getBucket() + "." + ossProperties.getEndpoint() + "/" + ossProperties.getDir() + fileName;
            return url;
        } catch (Exception e) {
            throw new IOException("图片上传失败");
        }
    }

    /**
     * 上传到OSS服务器 如果同名文件会覆盖服务器上的
     *
     * @param instream 文件流
     * @param fileName 文件名称 包括后缀名
     * @return 出错返回"" ,唯一MD5数字签名
     */
    public String uploadFile2OSS(InputStream instream, String fileName) {
        String ret = "";
        try {
            // 创建上传Object的Metadata
            ObjectMetadata objectMetadata = new ObjectMetadata();
            objectMetadata.setContentLength(instream.available());
            objectMetadata.setCacheControl("no-cache");
            objectMetadata.setHeader("Pragma", "no-cache");
            objectMetadata.setContentType(getcontentType(fileName.substring(fileName.lastIndexOf("."))));
            objectMetadata.setContentDisposition("inline;filename=" + fileName);
            // 上传文件
            PutObjectResult putResult = ossClient.putObject(ossProperties.getBucket(), ossProperties.getDir() + fileName, instream, objectMetadata);
            ret = putResult.getETag();
        } catch (IOException e) {
            System.out.println(e.getMessage());
        } finally {
            try {
                if (instream != null) {
                    instream.close();
                }
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
        return ret;
    }

    /**
     * Description: 判断OSS服务文件上传时文件的contentType
     */
    public static String getcontentType(String filenameExtension) {
        if (filenameExtension.equalsIgnoreCase("bmp")) {
            return "image/bmp";
        }
        if (filenameExtension.equalsIgnoreCase("gif")) {
            return "image/gif";
        }
        if (filenameExtension.equalsIgnoreCase("jpeg") || filenameExtension.equalsIgnoreCase("jpg")
                || filenameExtension.equalsIgnoreCase("png")) {
            return "image/jpeg";
        }
        if (filenameExtension.equalsIgnoreCase("html")) {
            return "text/html";
        }
        if (filenameExtension.equalsIgnoreCase("txt")) {
            return "text/plain";
        }
        if (filenameExtension.equalsIgnoreCase("vsd")) {
            return "application/vnd.visio";
        }
        if (filenameExtension.equalsIgnoreCase("pptx") || filenameExtension.equalsIgnoreCase("ppt")) {
            return "application/vnd.ms-powerpoint";
        }
        if (filenameExtension.equalsIgnoreCase("docx") || filenameExtension.equalsIgnoreCase("doc")) {
            return "application/msword";
        }
        if (filenameExtension.equalsIgnoreCase("xml")) {
            return "text/xml";
        }
        return "image/jpeg";
    }

}
  • controller
@Controller
@RequestMapping("/sysFile")
public class SysFileController {

    @Autowired
    private ISysFileService fileService;

    @Autowired
    private OSSUtil ossUtil;

    @GetMapping("/toFilePage")
    public String toFilePage(){
        return "file";
    }

    @PostMapping("/uploadOss")
    @ResponseBody
    public AjaxResult uploadOss(@RequestParam(value = "file", required = true) MultipartFile file) throws Exception {
        // 原始文件名称,如test.jpg
        String fileName = file.getOriginalFilename();
        // 唯一的文件名称
        String newFileName = getTime()+ "_" + fileName;
        // 上传文件,并获取oss上图片的地址,例如:https://typora-aliyun.oss-cn-shanghai.aliyuncs.com/file/20220506202723_test.jpg
        String url = ossUtil.uploadImg2Oss(file, newFileName);
        //存进数据库
        if (url != null) {
            SysFile sysFile = new SysFile();
            sysFile.setFileName(fileName);
            sysFile.setFileUrl(url);
            fileService.save(sysFile);
        }
        return AjaxResult.suc();

    }

    public String getTime(){
        String curTime = LocalDateTime.now().format(DateTimeFormatter.ofPattern("yyyyMMddHHmmss"));
        return curTime;
    }
}
  • 页面
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>文件上传</title>
</head>
<body>

<form enctype="multipart/form-data" method="POST" action="/sysFile/uploadOss">
    <input type="file" name="file" />
    <input type="submit" value="upload" />
</form>

</body>
</html>

准备完成之后,访问http://localhost:8080/sysFile/toFilePage,上传我们的图片, 可以在阿里oss看到我们上传的图片

oss文件预览时This XML file does not appear to have any style information ass oss文件是什么_上传_05

4. 总结

上面实战的只是最简单的上传功能,适合小文件上传,oss其实还支持更加复杂的文件操作,比如断点,追加,分片等,需要自己去看一下文档