服务端签名后前端直接上传图片到阿里云OSS示例(Java)

时间:2022-03-18 16:06:25

这是基于Spring MVC实现的一个demo。

pom添加依赖包aliyun-sdk-oss

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

PostObjectPolicy

public class PostObjectPolicy {
    private String accessId;
    private String host;
    private String dir;
    private String policy;
    private String expire;
    private String signature;
    //此处省略get,set方法
}

AliyunOSSClient 获取Policy

@Service
public class AliyunOSSClient {

    @Value("${aliyun.oss.endpoint}")
    private String endpoint;
    @Value("${aliyun.oss.accessKeyId}")
    private String accessKeyId;
    @Value("${aliyun.oss.accessKeySecret}")
    private String accessKeySecret;


    private OSSClient ossClient;

    public AliyunOSSClient() {
    }

    @PostConstruct
    void init() {
        if(this.ossClient == null) {
            this.ossClient = new OSSClient(this.endpoint, this.accessKeyId, this.accessKeySecret);
        }
    }

    /**
     * 获取Policy签名等信息
     * @param bucket             
     * @param dir                存储在bucket的目录
     * @param expiredSeconds   过期时间
     * @return
     */
    public PostObjectPolicy getPostObjectPolicy(String bucket,String dir,long expiredSeconds) {

        long expireEndTime = System.currentTimeMillis() + expiredSeconds* 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, dir);

        String postPolicy = ossClient.generatePostPolicy(expiration, policyConds);
        byte[] binaryData = new byte[0];
        try {
            binaryData = postPolicy.getBytes("utf-8");
        } catch (UnsupportedEncodingException e) {
            e.printStackTrace();
        }
        String encodedPolicy = BinaryUtil.toBase64String(binaryData);
        String postSignature = ossClient.calculatePostSignature(postPolicy);

        PostObjectPolicy policy = new PostObjectPolicy();
        policy.setAccessId(accessKeyId);
        policy.setHost("https://" + bucket + "." + endpoint);
        policy.setDir(dir);
        policy.setExpire(String.valueOf(expireEndTime / 1000));
        policy.setPolicy(encodedPolicy);
        policy.setSignature(postSignature);
        return policy;
    }
}

Controller

@RestController
@RequestMapping("aliyun/oss")
public class AliyunOSSRest {

    @Autowired
    private AliyunOSSClient aliyunOSSClient ;
    @Value("${aliyun.oss.buckeet}")
    private String bucket;

    @GetMapping("policy.json")
    public PostObjectPolicy getPolicy() {
         String dir = String.valueOf(System.currentTimeMillis());
         return aliyunOSSClient .getPostObjectPolicy(bucket,dir,60);
    }
}

前端(html和js)

<!DOCTYPE html>
<html>
<head>
	<script src="https://cdn.bootcss.com/jquery/3.2.1/jquery.min.js"></script>
	<script type="text/javascript">
		function upload () {
			var file = $("#file").val();
			if(file.length == 0) {
              alert("请选择文件");
			}
            
		   $.getJSON("getPolicy.json",function(policy) {
			var filename = new Date().getTime() + getSuffix(file);
	        var formData = new FormData();
            formData.append("file",$("#file")[0].files[0]);

             //注意formData里append添加的键的大小写
	        formData.append('key', policy.dir + "/" + filename);  //存储在oss的文件路径
	        formData.append('policy', policy.policy);  //policy
	        formData.append('OSSAccessKeyId', policy.accessId);  //accessKeyId
	        formData.append('success_action_status', "200");  //成功后返回的操作码
	        formData.append('Signature', policy.signature);   //签名

	        var url = policy.host;
	        $.ajax({  
		        url:  url,  
		        type: 'POST',  
		        data: formData,  
		        async: false,  
		        cache: false,  
		        contentType: false,  
		        processData: false,  
		        success: function (returndata) {  
		           alert(returndata);  
		        },  
		        error: function (returndata) {  
		           alert(returndata);  
		        }  
	 		  });
		  });
		}
		function getSuffix(fileName) {
		    var pos = fileName.lastIndexOf(".");
		    var suffix = '';
		    if(pos != -1) {
		      suffix = fileName.substring(pos);
		    }
		    return suffix;
		  }
	</script>
	<title>demo</title>
</head>
<body>
<form >
	<input type="file"  name="file" />
	<a onclick="upload()">上传</a>
</form>
</body>
</html>

问题

跨域问题:

在阿里云选中oss上要设置跨域访问的bucket,在基础设置可以设置允许跨域访问的域名,如图:

服务端签名后前端直接上传图片到阿里云OSS示例(Java)