SpringBoot+Vue实现阿里云OSS服务器签名直传并且返回回调数据

vue

<template>
<el-upload
    class="upload-demo"
    :action="objectData.host"
    :before-upload="beforeUpload"
    accept=""
    :multiple="false"
    :on-exceed="handleExceed"
    :on-success="handleSuccess"
    :file-list="fileList"
    :on-error="handleError"
    :data="objectData"
    :show-file-list="false">
    <el-button size="small" type="primary">点击上传</el-button>
</el-upload>
</template>

<script>
export default {
  data() {
    return {
      fileList: [],
      objectData: {
          OSSAccessKeyId: '',
          policy: '',
          Signature: '',
          callback: '',
          key: '',
          host: '',
          dir: ''
      },
    };
  },
  methods: {
        beforeUpload(file) {
            const extensionLimits = {
                video: {extensions: ["mp4", "flv"], maxSize: 300},
                documents: {
                    extensions: ["doc", "docx", "xls", "xlsx", "ppt", "pptx", "pdf", "rar", "zip"],
                    maxSize: 30
                },
                images: {extensions: ["jpg", "png", "gif", "jpeg"], maxSize: 30},
                audio: {extensions: ["mp3"], maxSize: 30},
            };

            const ext = file.name.split(".").pop();
            const fileSize = file.size / 1024 / 1024;

            const showError = (errorMessage) => {
                this.$message.error(errorMessage);
                return false;
            };

            if (ext === "mp4" || ext === "flv") {
                if (fileSize > extensionLimits.video.maxSize) {
                    return showError("文件大小不能超过300MB!");
                }
            } else if (extensionLimits.documents.extensions.includes(ext)) {
                if (fileSize > extensionLimits.documents.maxSize) {
                    return showError("文件大小不能超过30MB!");
                }
            } else if (extensionLimits.images.extensions.includes(ext)) {
                if (fileSize > extensionLimits.images.maxSize) {
                    return showError("文件大小不能超过30MB!");
                }
            } else if (extensionLimits.audio.extensions.includes(ext)) {
                if (fileSize > extensionLimits.audio.maxSize) {
                    return showError("文件大小不能超过30MB!");
                }
            } else {
                return showError("上传文件只能是 doc、docx、xls、xlsx、ppt、pptx、pdf、rar、zip、jpg、png、gif、jpeg、mp4、flv、mp3 格式!");
            }
            this.FormLoading = true;
            let that = this
            //获取oss上传令牌
            return new Promise((resolve, reject) => {
                axios.get(JavaApiM + '/gt-web/resources/getSTSToken').then(res => {
                    const fileData = res.data.data
                    that.objectData.OSSAccessKeyId = fileData.accessId;
                    that.objectData.policy = fileData.policy;
                    that.objectData.Signature = fileData.signature;
                    that.objectData.callback = fileData.callback;
                    that.objectData.dir = fileData.dir;
                    that.objectData.host = fileData.host;
                    that.objectData.key = fileData.dir + '${filename}';
                    resolve(true);
                    console.log(fileData.domain + "/" + that.objectData.dir + file.name)
                })
                    .catch(res => {
                        reject(false)
                        console.log(res);
                    })
            })
        },
        handleExceed(files, fileList) {
        this.$message.warning(`当前限制选择 1 个文件,本次选择了 ${files.length} 个文件,共选择了 ${files.length + fileList.length} 个文件`);
    		},
        handleSuccess(file) {
        let result = file.data;
        console.log(file);
        let info = {
            Ext: "." + result.path.split(".").pop(),
            Path: result.path,
            StatusCode: 1,
            fileSys: 2,
            name: result.path.split("/").pop()
        }
        console.log(info)
        this.fileList.push(info);
        this.FormLoading = false;
    },
        handleError(res, file) {
        this.FormLoading = false;
        this.$message.error('上传失败')
    		},
  }
};
</script>

<style>
</style>

java

    /**
     * 调用OSS接口获取STS临时访问凭证
     *
     * @return {@link ApiRest }
     * @author liuyanqiang
     * @since 2023/06/28 10:08
     **/
    @ApiOperation(value = "调用OSS接口获取STS临时访问凭证", notes = "调用OSS接口获取STS临时访问凭证")
    @RequestMapping(value = "/getSTSToken", method = RequestMethod.GET)
    public ApiRest getSTSToken() {
        return super.success(resourcesService.getSTSToken());
    }

    /**
     * 回调
     *
     * @param request 请求
     * @return {@link ApiRest }
     * @author liuyanqiang
     * @since 2023/07/03 10:46
     **/
    @ApiOperation(value = "调用OSS接口上传的回调函数", notes = "调用OSS接口上传的回调函数")
    @RequestMapping(value = "/callback", method = RequestMethod.POST)
    public ApiRest callback(HttpServletRequest request) {
        return super.success(resourcesService.callback(request));
    }
    /**
     * 调用OSS接口获取STS临时访问凭证
     *
     * @return {@link Map }<{@link String },{@link String }>
     * @author liuyanqiang
     * @since 2023/06/28 02:16
     **/
    Map<String,String> getSTSToken();

    /**
     * 回调
     *
     * @param request 请求
     * @return {@link Map }<{@link String },{@link String }>
     * @author liuyanqiang
     * @since 2023/07/06 02:55
     **/
    Map<String,String>  callback(HttpServletRequest request);
    @Value("${aliCloud.oss.access-key}")
    private String ACCESS_KEY;

    @Value("${aliCloud.oss.secret-key}")
    private String SECRET_KEY;

    @Value("${aliCloud.oss.bucket}")
    private String BUCKET;

    @Value("${aliCloud.oss.endpoint}")
    private String ENDPOINT;

    @Value("${aliCloud.oss.custom-domain}")
    private String CUSTOM_DOMAIN;

    @Value("${aliCloud.oss.file-dir}")
    private String FILE_DIR;

    @Value("${aliCloud.oss.callback-url}")
    private String CALLBACK_URL;



    /**
     * 调用OSS接口获取STS临时访问凭证
     *
     * @return {@link Map }<{@link String }, {@link String }>
     * @author liuyanqiang
     * @since 2023/06/28 02:16
     **/
    @Override
    public Map<String, String> getSTSToken() {
        return ossUtil.getSTSToken(CUSTOM_DOMAIN,BUCKET, ENDPOINT, ACCESS_KEY, SECRET_KEY,FILE_DIR,CALLBACK_URL);
    }

    /**
     * 回调
     *
     * @param request 请求
     * @return {@link Map }<{@link String }, {@link String }>
     * @author liuyanqiang
     * @since 2023/07/03 10:46
     **/
    @Override
    public Map<String, String> callback(HttpServletRequest request) {
        Map<String, String> respMap = new HashMap<>();
        String filename = request.getParameter("filename");
        String path = "https://".concat(CUSTOM_DOMAIN).concat("/").concat(filename);
        respMap.put("path", path);
        respMap.put("size", request.getParameter("size"));
        respMap.put("mimeType", request.getParameter("mimeType"));
        respMap.put("height", request.getParameter("height"));
        respMap.put("width", request.getParameter("width"));
        return respMap;
    }

/**
 * 阿里云 oss 上传工具类
 *
 * @author liuyanqiang
 * @version 1.0.0
 * @since 2023/04/19 06:36
 **/
@Slf4j
@Data
@Component
public class OSSUtil {
    /**
     * oss 工具客户端
     */
    private static OSSClient ossClient = null;

    /**
     * 获取STS临时访问凭证
     *
     * @param customDomain    自定义域
     * @param bucketName      bucket名称
     * @param endPoint        终点
     * @param accessKeyId     访问密钥id
     * @param accessKeySecret 访问密钥秘密
     * @param fileDir         文件dir
     * @param callbackUrl     回调url
     * @return {@link Map }<{@link String }, {@link String }>
     * @author liuyanqiang
     * @since 2023/07/03 10:45
     **/
    public static Map<String, String> getSTSToken(String customDomain,String bucketName, String endPoint, String accessKeyId, String accessKeySecret, String fileDir,String callbackUrl) {
        // 初始化oss
        initOSS(bucketName, endPoint, accessKeyId, accessKeySecret);
        Map<String, String> respMap = Maps.newHashMap();
        try {
            // 拼接文件路径
            fileDir = fileDir + DateUtil.format(new Date(), "yyyyMMdd") + "/" + System.currentTimeMillis()+"/";
            // 获取临时访问凭证
            long expireTime = 30;
            long expireEndTime = System.currentTimeMillis() + expireTime * 1000;
            Date expiration = new Date(expireEndTime);
            PolicyConditions policyConds = new PolicyConditions();
            policyConds.addConditionItem(PolicyConditions.COND_CONTENT_LENGTH_RANGE, 0, 1048576000);
            policyConds.addConditionItem(MatchMode.StartWith, PolicyConditions.COND_KEY, fileDir);
            String postPolicy = ossClient.generatePostPolicy(expiration, policyConds);
            byte[] binaryData = postPolicy.getBytes("utf-8");
            String policy = BinaryUtil.toBase64String(binaryData);
            String signature = ossClient.calculatePostSignature(postPolicy);
            // 设置回调参数
            JSONObject jasonCallback = new JSONObject();
            jasonCallback.put("callbackUrl", callbackUrl);
            jasonCallback.put("callbackBody",
                    "filename=${object}&size=${size}&mimeType=${mimeType}&height=${imageInfo.height}&width=${imageInfo.width}");
            jasonCallback.put("callbackBodyType", "application/x-www-form-urlencoded");
            String callbackData = BinaryUtil.toBase64String(jasonCallback.toString().getBytes());
            respMap.put("callback", callbackData);

            respMap.put("accessId",accessKeyId);
            respMap.put("policy",policy);
            respMap.put("signature",signature);
            respMap.put("dir",fileDir);
            respMap.put("host","https://" + bucketName + "." + endPoint);
            respMap.put("expire",String.valueOf(expireEndTime / 1000));
            respMap.put("domain","https://" + customDomain);
            log.info("获取临时访问凭证成功",respMap);
            return respMap;
        } catch (UnsupportedEncodingException e) {
            e.printStackTrace();
        } catch (ClientException e) {
            e.printStackTrace();
        }
        return respMap;
    }

    /**
     * 上传文件至阿里云 OSS
     *
     * @param file            待上传文件
     * @param customDomain    阿里云自定义域名
     * @param fileDir         阿里云OSS服务的访问域名路径
     * @param endPoint        阿里云OSS服务的访问域名
     * @param accessKeyId     访问密钥id
     * @param accessKeySecret 访问密钥串
     * @param bucketName      上传文件的存储空间名称
     * @return {@link String } 返回访问的全路径
     * @author liuyanqiang
     * @since 2023/04/19 06:32
     **/
    public static String uploadFileToOSS(MultipartFile file, String customDomain, String fileDir, String endPoint, String accessKeyId, String accessKeySecret, String bucketName) {
        // 初始化oss
        initOSS(bucketName, endPoint, accessKeyId, accessKeySecret);
        String visitUrl = null;
        try {
            // 获取文件名
            String orgName = file.getOriginalFilename();
            if (StringUtils.isEmpty(orgName)) {
                orgName = file.getName();
            }
            orgName = getFileName(orgName);
            //文件名称后缀使用

            // 拼接文件路径
            String fileRelName = fileDir + DateUtil.format(new Date(), "yyyyMMdd") + "/" + System.currentTimeMillis() + "_" + orgName;
            // 上传至oss
            PutObjectResult result = ossClient.putObject(bucketName, fileRelName, file.getInputStream());
            if (result != null) {
                log.info("------OSS文件上传成功------");
            }
            // 拼接访问路径
            visitUrl = "https://" + customDomain + "/" + fileRelName;
        } catch (IOException e) {
            log.error(e.getMessage(), e);
            return null;
        }
        return visitUrl;
    }


    /**
     * 删除文件
     *
     * @param bucketName      上传文件的存储空间名称
     * @param fileName        要删除的文件名称
     * @param endPoint        阿里云OSS服务的访问域名
     * @param accessKeyId     访问密钥id
     * @param accessKeySecret 访问密钥串
     * @return {@link VoidResult }
     * @author liuyanqiang
     * @since 2023/04/19 06:30
     **/
    public static VoidResult deleteFileToOSS(String bucketName, String fileName, String endPoint, String accessKeyId, String accessKeySecret) {
        // 初始化oss
        initOSS(bucketName, endPoint, accessKeyId, accessKeySecret);
        return ossClient.deleteObject(bucketName, fileName);
    }


    /**
     * 初始化 oss 客户端
     *
     * @param bucketName      上传文件的存储空间名称
     * @param endpoint        阿里云OSS服务的访问域名
     * @param accessKeyId     访问密钥id
     * @param accessKeySecret 访问密钥串
     * @return {@link OSSClient }
     * @author liuyanqiang
     * @since 2023/04/19 18:23
     **/
    private static OSSClient initOSS(String bucketName, String endpoint, String accessKeyId, String accessKeySecret) {
        if (ossClient == null) {
            synchronized (OSSClient.class) {
                if (ossClient == null) {
                    ossClient = new OSSClient(endpoint, new DefaultCredentialProvider(accessKeyId, accessKeySecret), new ClientConfiguration());
                    // 设置权限(公开读)
                    ossClient.setBucketAcl(bucketName, CannedAccessControlList.PublicRead);
                }
            }
        }
        return ossClient;
    }


    /**
     * 判断文件名是否带盘符,重新处理
     *
     * @param fileName 文件名称
     * @return {@link String }
     * @author liuyanqiang
     * @since 2023/04/19 06:36
     **/
    public static String getFileName(String fileName) {
        //判断是否带有盘符信息
        // Check for Unix-style path
        int unixSep = fileName.lastIndexOf('/');
        // Check for Windows-style path
        int winSep = fileName.lastIndexOf('\\');
        // Cut off at latest possible point
        int pos = (winSep > unixSep ? winSep : unixSep);
        if (pos != -1) {
            // Any sort of path separator found...
            fileName = fileName.substring(pos + 1);
        }
        //替换上传文件名字的特殊字符
        fileName = fileName.replace("=", "").replace(",", "").replace("&", "").replace("#", "");
        return fileName;
    }
}

可参考官方文档:如何通过Java在服务端签名直传并设置上传回调_对象存储-阿里云帮助中心

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

小刘要努力(ง •̀_•́)ง

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值