前言:

  1. 记得在OSS中配置bucket的跨域设置。
  2. 该方法只适用5G以内的文件,如果超大文件需要分片上传。
  3. 带上传进度条。

java代码(包含后端上传文件、删除文件、提供签名)

{

    private final static String OSS_BUCKET_NAME = "test";
    private final static String ENDPOINT_URL = "oss-cn-beijing.aliyuncs.com";
    private final static String OSS_ACCESS_DOMAIN_URL = "https://"+OSS_BUCKET_NAME+"."+ENDPOINT_URL;
    private final static String ACCESS_KEY_ID = "你自己的keyid";
    private final static String ACCESS_KEY_SECRET = "你自己的key secret";
    // 自定义的文件夹名(注意:第一位字符 不能是 / 否则oss端会报错)
    private final static String UPLOAD_DIR = "upload/";

    public static OSSClient initClient(){
       return  new OSSClient(ENDPOINT_URL, CredentialsProviderFactory.newDefaultCredentialProvider(ACCESS_KEY_ID, ACCESS_KEY_SECRET),
                new ClientConfiguration());
    }


    /**
     * [描述] 提供令牌给前端  让前端直传到OSS
     */
    public  static Object getSignature() {
            OSSClient ossClient = initClient();
            //token 过期时间(分钟)
            long expireTime = 10;
            long expireEndTime = System.currentTimeMillis() + expireTime *1000;
            Date expiration = new Date(expireEndTime);

            //生成的到期时间转换位s,并转换为String
            String expire = String.valueOf(expireEndTime / 1000);

            //构造用户表单域Policy条件
            PolicyConditions policyCond = new PolicyConditions();
            //设置上传文件大小的范围
            policyCond.addConditionItem(PolicyConditions.COND_CONTENT_LENGTH_RANGE, 0, 1048576000);
                //设置上传的路径的前缀:就是上传到指定文件夹
            policyCond.addConditionItem(MatchMode.StartWith, PolicyConditions.COND_KEY, UPLOAD_DIR);

            //根据到期时间生成policy策略
            String postPolicy = ossClient.generatePostPolicy(expiration, policyCond);
            //对policy进行UTF-8编码后转base64
            byte[] binaryData = postPolicy.getBytes(StandardCharsets.UTF_8);
            String endPolicy = BinaryUtil.toBase64String(binaryData);
            //生成签名,policy表单域作为填入的值,将该值作为将要签名的字符串。
            String signature = ossClient.calculatePostSignature(postPolicy);

            //封装参数参数返回
            HashMap<String, Object> map = new HashMap<>(5);
            map.put("OSSAccessKeyId",ACCESS_KEY_ID);
            map.put("host",OSS_ACCESS_DOMAIN_URL);
            map.put("policy",endPolicy);
            map.put("signature",signature);
            map.put("expiration",expire );
            map.put("key",UPLOAD_DIR );
            map.put("success_action_status","200");
            map.put("msg","签名成功");
        return map;
    }

    /**
    * 获取随机文件名用来保存
     * @param fileName 用户文件名称
     * @return 实际的cos上文件名称
     */
    private static String getRealFileName(String saveFolder, String fileName) {
        return StringUtils.isNotEmpty(saveFolder) ? saveFolder + "/" + fileName : fileName;
    }

    public static String upload(String saveFolder, String contentType, String fileName, long contentLength, InputStream input) {
        if (StringUtils.isEmpty(fileName) || StringUtils.isEmpty(contentType) || contentLength <= 0 || null == input) {
            return null;
        }
        ObjectMetadata objectMeta = new ObjectMetadata();
        objectMeta.setContentLength(contentLength);
        objectMeta.setContentType(contentType);
        String filePath = getRealFileName(saveFolder, fileName);
        try {
            initClient().putObject(OSS_BUCKET_NAME, filePath, input, objectMeta);
            return OSS_ACCESS_DOMAIN_URL + filePath;
        } catch (Exception e) {
            e.printStackTrace();
            logger.error(e.getMessage(),e);
            return null;
        } finally {
            try {
                input.close();
            } catch (IOException e) {
                e.printStackTrace();
                logger.error(e.getMessage(),e);
            }
        }
    }
    /**
    * 前端把文件上传给后端  后端再上传至OSS
     */
    public static String upload(String saveFolder, MultipartFile multipartFile) {
        if(multipartFile == null || multipartFile.isEmpty()){
            return null;
        }
        
        try {
            String fileMainName = System.currentTimeMillis()+"-";
            String filename = multipartFile.getOriginalFilename();
            String extFileName;
            if (StringUtils.isNotEmpty(filename)) {
                extFileName = filename.substring(filename.lastIndexOf("."));
            } else {
                extFileName = ".jpg";
            }
            return upload(saveFolder, multipartFile.getContentType(), fileMainName + extFileName, multipartFile.getSize(), multipartFile.getInputStream());
        } catch (IOException e) {
            e.printStackTrace();
            logger.error(e.getMessage(),e);
            return null;
        }
    }

   /**
    * 通过url地址删除指定文件
     */
    public static void delete(String fileUrl) {
        if (StringUtils.isEmpty(fileUrl)) {
            return;
        }
        try {
            fileUrl = fileUrl.replaceFirst(OSS_ACCESS_DOMAIN_URL, "");
            initClient().deleteObject(OSS_BUCKET_NAME, fileUrl);
        } catch (OSSException | ClientException e) {
            e.printStackTrace();
            logger.error(e.getMessage(),e);
        }
    }

}

前端VUE代码


<template>
    <div>
        <el-upload
            class="upload-demo"
            ref="upload"
            action="#"
            :on-preview="handlePreview"
            :on-remove="handleRemove"
            :on-change="handleChange"
            :auto-upload="false"
        >
            <el-button slot="trigger" size="small" type="primary">
                选取文件
            </el-button>
            <el-button
                style="margin-left: 10px"
                size="small"
                type="success"
                @click="submitUpload"
            >
                上传到服务器
            </el-button>
            <div slot="tip" class="el-upload__tip">
                只能上传jpg/png文件,且不超过500kb
            </div>
        </el-upload>
        <div style="width: 30%">
            <el-progress :percentage="percent"></el-progress>
        </div>

        <div>
            <el-image style="width: 200px" :src="url"></el-image>
        </div>
    </div>
</template>

<script>
import uploadUtil from '/request/uploadUtil'
export default {
    data() {
        return {
            file: null,
            percent: 0,
        }
    },
    components: {},
    methods: {
        submitUpload() {
            this.percent = 0
            const result = uploadUtil.startUpload2(
                this.file,
                (progressEvent) => {
                    this.percent =
                        (progressEvent.loaded / progressEvent.total) * 100 || 0
                }
            )
            result.then((res) => {
                console.log(res)
                this.url = res.fileUrl
                this.percent = 100
            })
        },
        handleRemove(file, fileList) {
            console.log(file, fileList)
        },
        handlePreview(file) {
            this.openVideoPlyer = true
            this.videoFile = file
        },
        handleChange(file, fileList) {
            if (fileList.length > 1) {
                fileList.splice(0, 1)
            }
            this.file = file
        },
    },
}
</script>

upload.js 工具类:

import axios from "axios"
import { Message } from 'element-ui';

// bucket 名
const fdBucket = 'jg';
// 获取oss上传签名
const getOssTokenUrl = '/oss/get_oss_token';


async function startUpload2(file, coolDown,) {
	let res= {};
	await axios.get(getOssTokenUrl, { 'fileScene': fdBucket, 'fileName': file.name })
   	.then((result) => {
            res = result.data;
        })

    const formData = new FormData();
    formData.append("OSSAccessKeyId", res.accessKeyId);
    formData.append("key", res.filePath);
    formData.append("policy", res.policy);
    formData.append("signature", res.signature);
    // 注意:file文件必须放在表单的最后面,OSS官网有说明
    formData.append("file", file.raw ? file.raw : file);

    return await axios({
        url: res.host,
        timeout: 1000 * 60 * 10,
        method: 'post',
        data: formData,
        headers: { 'Content-Type': 'multipart/form-data' },
        onUploadProgress: function (progressEvent) {
            if (progressEvent.lengthComputable) {
                coolDown(progressEvent);
            }
        },
    }).then(() => {
        return { 'fileUrl': res.fileUrl, 'filePath': res.filePath };
    }).catch(() => {
        Message.error('上传失败,请联系管理员');
        return { 'fileUrl': '', 'filePath': '' };
    });
}


export default { startUpload2 }

postman 上传文件测试截图:

在这里插入图片描述

OSS官网文档地址:
https://help.aliyun.com/document_detail/605225.html?spm=a2c4g.475682.0.0.4d686dd4C9tKE8
https://help.aliyun.com/document_detail/605224.html?spm=a2c4g.605225.0.0.7ddb7aabQxkDv

参考博客:
https://blog.csdn.net/weixin_42681295/article/details/121156732

Logo

华为开发者空间,是为全球开发者打造的专属开发空间,汇聚了华为优质开发资源及工具,致力于让每一位开发者拥有一台云主机,基于华为根生态开发、创新。

更多推荐