前言

今天码帮帮系统已经整合到上传项目案例的功能了,这里有一些图片资源需要上传,之前做项目对接过七牛云,也有使用过阿里云的视频点播服务,不过这次对接阿里云的OSS确实有点小尴尬,感觉文档不是很好对接,因为之前对接过七牛云,所以会有对接七牛云的流程在脑海里!按在七牛云的对接流程是服务端通过accessKeyId、accessKeySecret、endpoint得到签名,然后客户端根据签名上传,当然也有纯客户端的做法,但是作为一个服务端开发者,认为accessKeyId、accessKeySecret这些信息放在客户端,容易暴露出去,不是很安全,所以对接阿里云也是按照这种思路去做的,但是看了阿里云的OSS文档并没有找到这样的流程文档,可能是OSS体系太过庞大了,导致文档太多,没找到吧!那么本文将演示如何通过JAVA服务端生成签名,到VUE客户端上传图片的完整流程!

阿里云相关

开通OSS服务
JAVA整合阿里云OSS/VUE上传阿里云OSS_客户端

JAVA整合阿里云OSS/VUE上传阿里云OSS_vue.js_02
创建Bucket
JAVA整合阿里云OSS/VUE上传阿里云OSS_阿里云_03
注意地域,这玩意一定要记好,不然后面会有坑!那么到这里基本的就差不多了,后面还有跨域、在线预览问题,后面会单独讲!

JAVA整合

导入依赖

		<dependency>
            <groupId>com.aliyun.oss</groupId>
            <artifactId>aliyun-sdk-oss</artifactId>
            <version>2.2.3</version>
        </dependency>

编写阿里云OSS基本工具


import com.aliyun.oss.OSSClient;
import com.aliyun.oss.common.utils.BinaryUtil;
import com.aliyun.oss.model.GetObjectRequest;
import com.aliyun.oss.model.MatchMode;
import com.aliyun.oss.model.PolicyConditions;
import com.aliyun.oss.model.PutObjectResult;
import lombok.extern.slf4j.Slf4j;
import org.springframework.core.io.ClassPathResource;

import java.io.File;
import java.net.URL;
import java.nio.charset.StandardCharsets;
import java.util.Date;
import java.util.LinkedHashMap;
import java.util.Map;

/**
* @description: 阿里云OSS工具
 * 官方链接地址:https://help.aliyun.com/document_detail/31926.html?spm=a2c4g.11186623.6.1737.5f3e3bd36kleqs
 * 公共云下OSS Region和Endpoint对照表:https://help.aliyun.com/document_detail/31837.htm?spm=a2c4g.11186623.0.0.7b6b2c20Qv3xQw#concept-zt4-cvy-5db
 * 在线预览问题:https://help.aliyun.com/noticelist/articleid/1060057906.html
* @author TAO
* @date 2021/11/30 22:26
*/
@Slf4j
public class AliUtil {

    private static String accessKeyId = "xxx";

    private static String accessKeySecret = "xxx";

    //公共云下OSS Region和Endpoint对照表:https://help.aliyun.com/document_detail/31837.htm?spm=a2c4g.11186623.0.0.7b6b2c20Qv3xQw#concept-zt4-cvy-5db
    private static String endpoint = "oss-cn-beijing.aliyuncs.com";

    /**
     * 获取临时访问OSS签名  前端-用签名的方式上传文件
     * @param bucketName
     * @param dir bucket中的目录
     * @return
     */
    public static Map<String, String> getSignature(String bucketName, String dir) {
        Map<String, String> respMap = new LinkedHashMap<>();
        String endpointForSig = endpoint;
        String host = "https://" + bucketName + "." + endpointForSig;
        OSSClient client = new OSSClient(endpointForSig, accessKeyId, accessKeySecret);
        try {
            //设置过期时间为半小时1800L
            long expireTime = 60 * 30;
            long expireEndTime = System.currentTimeMillis() + expireTime * 1000;
            java.sql.Date expiration = new java.sql.Date(expireEndTime);
            // PostObject请求最大可支持的文件大小为5 GB,即CONTENT_LENGTH_RANGE为5*1024*1024*1024。
            PolicyConditions policyConditions = new PolicyConditions();
            policyConditions.addConditionItem(PolicyConditions.COND_CONTENT_LENGTH_RANGE, 0, 1048576000);
            policyConditions.addConditionItem(MatchMode.StartWith, PolicyConditions.COND_KEY, dir);
            String postPolicy = client.generatePostPolicy(expiration, policyConditions);
            byte[] binaryData = postPolicy.getBytes(StandardCharsets.UTF_8);
            String encodedPolicy = BinaryUtil.toBase64String(binaryData);
            String postSignature = client.calculatePostSignature(postPolicy);
            respMap.put("accessid", accessKeyId);
            respMap.put("policy", encodedPolicy);
            respMap.put("signature", postSignature);
            respMap.put("dir", dir);
            respMap.put("host", host);
            respMap.put("expire", String.valueOf(expireEndTime / 1000));
        } catch (Exception e) {
            log.info("获取阿里云OSS签名失败===>{}", e.getMessage());
        }
        return respMap;
    }

    public static Map<String, String> getSignature(String bucketName) {
        return getSignature(bucketName, "");
    }

    /**
     * 上传文件
     * @param bucketName
     * @param fileName 文件名
     * @param file 文件
     */
    public static void uploadFile(String bucketName, String fileName, File file) {
        // 创建OSSClient实例
        OSSClient ossClient = new OSSClient(endpoint, accessKeyId, accessKeySecret);
        // 上传文件
        PutObjectResult putObjectResult = ossClient.putObject(bucketName, fileName, file);
        String eTag = putObjectResult.getETag();
        log.info("eTag===>", eTag);
        // 关闭client
        ossClient.shutdown();
    }

    /**
     * 从OSS下载文件,将文件存储在项目tmp目录下,文件名是时间戳
     * @param objectName objectName oss文件名
     * @param bucketName 文件本地存储路径
     * @return
     */
    public static String downloadFileFromOSS(String objectName, String bucketName) {
        String resource;
        String OS = System.getProperty("os.name").toLowerCase();
        if (OS.equals("linux")) {
            resource = new ClassPathResource("/background/template_bg_image.jpg").getPath();

        } else {
            resource = AliUtil.class.getClassLoader().getResource("background/template_bg_image.jpg").getPath();
        }
        // 创建OSSClient实例
        OSSClient ossClient = new OSSClient(endpoint, accessKeyId, accessKeySecret);
        // 填写不包含Bucket名称在内的Object完整路径,例如testfolder/exampleobject.txt。
        ossClient.getObject(new GetObjectRequest(bucketName, objectName), new File(resource));
        ossClient.shutdown();
        return resource;
    }

    /***
     * 获取下载地址
     */
    public static String getDownUrl(String key, String bucket) {
        OSSClient client = new OSSClient(endpoint, accessKeyId, accessKeySecret);
        //判断文件是否存在
        // 设置URL过期时间为10年
        Date expiration = new Date(System.currentTimeMillis() + 3600L * 1000 * 24 * 10 * 365);
        // 生成URL
        URL url = client.generatePresignedUrl(bucket, key, expiration);
        client.shutdown();
        String s = url.toString().substring(0, url.toString().indexOf("?"));
        //生产环境中,OSS地址为内网地址,在此处转成外网地址
        if (s.contains("-internal")) {
            s = s.replace("-internal", "");
        }
        return s;
    }

    public static void main(String[] args) {
        String bucketName = "你的bucketName";
        File file = new File("C:\\Users\\Administrator\\Desktop\\test.png");
        String fileName = "tttyyy.jpg";
        Map<String, String> signature = AliUtil.getSignature(bucketName);
        log.info("signature===>",signature.toString());
        AliUtil.uploadFile(bucketName, fileName, file);
    }

}

编写controller

    @GetMapping("/getOssSignature")
    @ApiOperation(value = "获取阿里云oss签名", authorizations = @Authorization(value = "token"))
    public R getSkillByType(){
        Map<String, String> signature = AliUtil.getSignature("你的bucketName");
        return R.ok(signature);
    }

请求测试
JAVA整合阿里云OSS/VUE上传阿里云OSS_阿里云_04
完成,这里也可自行测试java的main方法启动上传图片,亲测有效!

VUE对接阿里云OSS

VUE这里直接使用element的el-upload作为上传组件!

el-upload

<el-upload class="upload-demo" drag  list-type="picture-card" :on-preview="handlePictureCardPreview"
 :on-remove="handleRemove" :http-request="fileUpload"  action="https://jsonplaceholder.typicode.com/posts/"
    multiple></el-upload>

其他代码

let axios = require('axios')

data(){
	return{
	    dialogImageUrl: '',
	    dialogVisible: false
	}
},
methods:{
	handleRemove (file, fileList) {
        console.log(file, fileList)
    },
    handlePictureCardPreview (file) {
        this.dialogImageUrl = file.url
        this.dialogVisible = true
    }
}

核心代码

fileUpload(param){
	let file = param.file // 得到文件的内容
    console.log("===>",file);
    getOssSignature().then(res =>{
	    console.log("res===>",res);
	    let sendData = new FormData();
        sendData.append('OSSAccessKeyId', res.accessid);
        sendData.append('policy', res.policy);
        sendData.append('Signature', res.signature);
        sendData.append('keys', res.dir);
        sendData.append('key',file.name)
        sendData.append('success_action_status', 200) // 指定返回的状态码
        sendData.append('file', file)
        axios.post(res.host, sendData).then(() => {
            console.log('得到上传到阿里云的图片地址:  ' + res.host+file.name)
        })
  	}).catch(err =>{
			console.error("获取签名失败!!!")
    });
}

那么到这里VUE客户端代码就完成了!但是还有两个问题,一个是跨域如下!
JAVA整合阿里云OSS/VUE上传阿里云OSS_客户端_05
另一个是在线预览,如下
JAVA整合阿里云OSS/VUE上传阿里云OSS_上传_06

跨域问题

修改CORS
JAVA整合阿里云OSS/VUE上传阿里云OSS_上传_07

在线预览

这个问题我就不多说了,让官网自己回答吧!OSS升级通知
JAVA整合阿里云OSS/VUE上传阿里云OSS_阿里云_08