摘要: 主要是PC项目前端上传需要从服务端拿到OSS认证才能上传、后端直接调用OSSClient上传就行。
文件上传流程比较复杂的服务器设置回调功能。整个流程图是这样的
可以参考阿里api文档介绍的工作流程说明:https://help.aliyun.com/document_detail/31927.html?spm=5176.doc31988.6.633.OTY557
废话不多说可以参考代码:
# OSS \u914D\u7F6E
oss.endpoint = oss-cn-shanghai.aliyuncs.com //上传节点
oss.accessKeyId = LTAIETtq2nU2PNbA//唯一标识
oss.accessKeySecret = 0FwnHo8Hj9ti9C5p7Sg9hYnqn553BO//密钥
oss.bucketName = ## //文件存储目录名
oss.expireTime = 3600 //
OssClient单例工厂
/**
* ClassName: OssClientFactory
* Function: OssClient单例工厂
* date: 2017/11/9 11:14
*
* @author lijc
* @version 1.0.0
* @since JDK 1.8
*/
@Component
public class OssClientFactory {
private volatile static OSSClient client;
private static String endpoint;
private static String accessKeyId;
private static String accessKeySecret;
public static OSSClient getOSSClient(){
if (client == null) {
synchronized (OssClientFactory.class){
if (client == null) {
client = new OSSClient(endpoint, accessKeyId, accessKeySecret);
}
}
}
return client;
}
@Value("${oss.endpoint}")
public void setEndpoint(String endpoint) {
this.endpoint = endpoint;
}
@Value("${oss.accessKeyId}")
public void setAccessKeyId(String accessKeyId) {
this.accessKeyId = accessKeyId;
}
@Value("${oss.accessKeySecret}")
public void setAccessKeySecret(String accessKeySecret) {
this.accessKeySecret = accessKeySecret;
}
}
与前端进行交互接口功能主要有、OSS签名授权、删除图片、创建oss bucket
接口:
ublic class OssController {
@Resource
private OssService ossService;
/**
* OSS签名授权
*/
@ApiOperation(value = "OSS签名授权", notes = "OSS签名授权", produces = "application/json")
@RequestMapping(value = "/authorize", method = RequestMethod.POST)
public ReturnData authorize(@Valid OssAuthorizeParam ossAuthorizeParam, BindingResult result) {
return ossService.authorize(ossAuthorizeParam.getDir());
}
/**
* 删除图片
*/
@ApiOperation(value = "删除OSS图片", notes = "删除OSS图片", produces = "application/json")
@RequestMapping(value = "/remove", method = RequestMethod.POST)
public ReturnData remove(@Valid OssRemoveParam ossRemoveParam, BindingResult result) {
return ossService.remove(ossRemoveParam.getKey());
}
/**
* 创建oss bucket
*/
@ApiOperation(value = "创建oss bucket", notes = "创建oss bucket", produces = "application/json")
@RequestMapping(value = "/createBucketName", method = RequestMethod.POST)
public ReturnData createBucketName(@Valid OssBucketNameParam ossBucketNameParam, BindingResult result) {
return ossService.createBucketName(ossBucketNameParam.getBucketName());
}
}
参数:
/**
*授权接口参数
*/
@Getter
@Setter
@ToString
public class OssAuthorizeParam implements Param {
@ApiModelProperty(value = "目录", required = true)
@NotEmpty(message = "目录不能为空")
private String dir;
}
/**
*授权接口返回值
*/
@Getter
@Setter
public class OssAuthorizeData implements Serializable{
private static final long serialVersionUID = -6646242394834700700L;
private String accessId;
private String policy;
private String signature;
private String dir;
private String host;
private String expire;
}
/**
*删除文件参数
*/
@Getter
@Setter
@ToString
public class OssRemoveParam implements Param {
@ApiModelProperty(value = "key", required = true)
@NotEmpty(message = "key不能为空")
private String key;
}
/**
*相关接口
*/
public interface OssService {
ReturnData authorize(String dir);
ReturnData remove(String objectName);
ReturnData createBucketName(String bucketName);
}
/**
*接口实现
*/
@Slf4j
@Service
public class OssServiceImpl implements OssService {
@Value("${oss.endpoint}")
private String endpoint;
@Value("${oss.accessKeyId}")
private String accessKeyId;
@Value("${oss.accessKeySecret}")
private String accessKeySecret;
@Value("${oss.bucketName}")
private String bucketName;
@Value("${oss.expireTime}")
private Long expireTime;
@Override
public ReturnData authorize(String dir) {
try {
String host = "http://" + bucketName + "." + endpoint;
OSSClient client = OssClientFactory.getOSSClient();
PolicyConditions policyConds = new PolicyConditions();
policyConds.addConditionItem(PolicyConditions.COND_CONTENT_LENGTH_RANGE, 0, 1048576000);
policyConds.addConditionItem(MatchMode.StartWith, PolicyConditions.COND_KEY, dir);
long expireEndTime = System.currentTimeMillis() + expireTime * 1000;
Date expiration = new Date(expireEndTime);
String postPolicy = client.generatePostPolicy(expiration, policyConds);
byte[] binaryData = postPolicy.getBytes("utf-8");
String encodedPolicy = BinaryUtil.toBase64String(binaryData);
String postSignature = client.calculatePostSignature(postPolicy);
OssAuthorizeData ossAuthorizeData = new OssAuthorizeData();
ossAuthorizeData.setAccessId(accessKeyId);
ossAuthorizeData.setDir(dir);
ossAuthorizeData.setExpire(String.valueOf(expireEndTime / 1000));
ossAuthorizeData.setHost(host);
ossAuthorizeData.setPolicy(encodedPolicy);
ossAuthorizeData.setSignature(postSignature);
return XgReturnUtil.success(ossAuthorizeData);
}catch(Exception e){
log.warn("OSS authorize error",e);
return XgReturnUtil.fail(ReturnCode.SERVER_EXCEPTION);
}
}
@Override
public ReturnData remove(String objectName) {
try {
OSSClient client = OssClientFactory.getOSSClient();
client.deleteObject(bucketName,objectName);
return XgReturnUtil.success();
}catch(Exception e){
log.warn("OSS authorize error",e);
return XgReturnUtil.fail(ReturnCode.SERVER_EXCEPTION);
}
}
@Override
public ReturnData createBucketName(String bucketName) {
try {
OSSClient client = OssClientFactory.getOSSClient();
boolean ifExist = client.doesBucketExist(bucketName);
if(!ifExist)
client.createBucket(bucketName);
return XgReturnUtil.success();
}catch(Exception e){
log.warn("OSS createBucketName error",e);
return XgReturnUtil.fail(ReturnCode.SERVER_EXCEPTION);
}
}
}
例子:完成图片上传(单个批量)、批量删除、图片搜素功能。
"1.0" encoding="UTF-8"?>
"-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
"com.xinguang.ftcs.common.mapper.OssImageMapper">
"add" parameterType="OssImage">
INSERT INTO t_oss_image
"(" suffix =")" suffixOverrides=",">
<if test="reference_id != null">referenceId,if>
<if test="imageType != null">image_type,if>
<if test="purpose != null">purpose,if>
<if test="objectName != null">object_name,if>
<if test="createTime != null">create_time,if>
"VALUES (" suffix=")" suffixOverrides=",">
<if test="referenceId != null">#{referenceId},if>
<if test="imageType != null">#{imageType},if>
<if test="purpose != null">#{purpose},if>
<if test="objectName != null">#{objectName},if>
<if test="createTime != null">#{createTime},if>
"batchAdd" parameterType="java.util.List">
insert into t_oss_image
(
reference_id,
image_type,
purpose,
object_name,
create_time
)
values
"list" item="item" index="index" separator="," >
(#{item.referenceId},#{item.imageType},#{item.purpose},#{item.objectName},#{item.createTime})
"batchDelete" parameterType="java.util.List">
update
t_oss_image
set
del_flag = '1'
where
id in
"list" item="id" open="(" separator="," close=")">
#{id}
//对应Mapper文件
@Mapper
public interface OssImageMapper {
/** 新增OSS图片 */
void add(OssImage ossImage);
/** 新增OSS图片列表 */
void batchAdd(List ossImageList);
/** 删除OSS图片列表 */
void batchDelete(List ids);
/** 查询OSS图片 */
List searchOssImageList(OssImageSearchParam param);
/** 通过主键Ids获取集合 */
List getByIds(List ids);
/** 删除OSS图片 (真删) */
@Delete("DELETE FROM t_oss_image WHERE id=#{id}")
void delete(@Param("id") String id);
}
/**
*OSSImageService实现
*/
@Slf4j
@Service
public class OssImageService {
@Resource
private OssImageMapper ossImageMapper;
@Value("${oss.bucketName}")
private String bucketName;
@Value("${oss.expireTime}")
private Long expireTime;
/**
* 新增单个图片
* @param param
* @param referenceId
* @param imageType
*/
public void add(OssImageAddParam param,String referenceId,String imageType){
OssImage ossImage = new OssImage();
ossImage.setImageType(imageType);
ossImage.setObjectName(param.getObjectName());
ossImage.setPurpose(param.getPurpose());
ossImage.setReferenceId(referenceId);
ossImage.setCreateTime(new Date());
ossImageMapper.add(ossImage);
}
/**
* 批量新增图片
* @param list
* @param referenceId
* @param imageType
*/
public void batchAdd(List list,String referenceId,String imageType){
if(CollectionUtils.isEmpty(list))
return;
Date now = new Date();
List ossImageList = new ArrayList<>();
for(OssImageAddParam addParam:list){
OssImage ossImage = new OssImage();
ossImage.setImageType(imageType);
ossImage.setObjectName(addParam.getObjectName());
ossImage.setPurpose(addParam.getPurpose());
ossImage.setReferenceId(referenceId);
ossImage.setCreateTime(now);
ossImageList.add(ossImage);
}
ossImageMapper.batchAdd(ossImageList);
}
/**
* 批量删除图片
* @param ids
*/
@Transactional
public void batchDelete(List ids){
if(CollectionUtils.isEmpty(ids))
return;
List ossImages = ossImageMapper.getByIds(ids);
OSSClient client = OssClientFactory.getOSSClient();
for(OssImage ossImage:ossImages){
client.deleteObject(bucketName,ossImage.getObjectName());
}
ossImageMapper.batchDelete(ids);
}
/**
* 查询图片
* @param param
*/
public List searchOssImageList(OssImageSearchParam param){
List ossImages = ossImageMapper.searchOssImageList(param);
if(CollectionUtils.isEmpty(ossImages))
return null;
List ossImageDataList = new ArrayList<>();
OSSClient ossClient = OssClientFactory.getOSSClient();
long time = new Date().getTime();
Date expireDate = new Date(time+expireTime * 60 * 60 * 1000);
for(OssImage ossImage:ossImages) {
OssImageData data = new OssImageData();
data.setId(ossImage.getId());
data.setReferenceId(ossImage.getReferenceId());
data.setObjectName(ossImage.getObjectName());
data.setPurpose(ossImage.getPurpose());
boolean objectExist = ossClient.doesObjectExist(bucketName, ossImage.getObjectName());
if(objectExist) {
URL url = ossClient.generatePresignedUrl(bucketName, ossImage.getObjectName(), expireDate);
data.setImgUrl(url.toString());
}
ossImageDataList.add(data);
}
return ossImageDataList;
}
}
/**
*对应OSS参数
*/
/**
*图片新增参数
*/
@Getter
@Setter
@ToString
public class OssImageAddParam implements Param{
@ApiModelProperty(value = "图片用途")
@NotEmpty(message = "图片用途不能为空")
private String purpose; // 图片用途,自定义枚举
@ApiModelProperty(value = "OSS objectname")
@NotEmpty(message = "图片url不能为空")
private String objectName; // OSS objectname
}
/**
*图片搜素参数
*/
@Getter
@Setter
@ToString
public class OssImageSearchParam implements Serializable{
private String referenceId; //关联ID
private List referenceIds;//关联ID集合
private String imageType; //图片类型,1-商品,2-卖家,3-VAT订单
private String purpose; //图片用途
}
后端直接上传文件:
一、创建相应的表
二、将文件转化成输入流
三、调用OssClient把生成url放到数据库中
//文件上传到Oss服务器并还回URL
String url = ossFileService.uploadFile(ossClient, bucketName, expireTime, key, inputStream).toString();
四、返回给前端相应的图片访问连接(注意:从数据库取出url 加上 String host = “http://” + bucketName + “.” + endpoint;)
注意点:
以上需求可能不满足你的业务需求:我的业务是没有进行回调如果需要回调请注意callback的设置。
定义callback 时,阿里支持两种方式,一个是callbackBody字符串直接拼接 用&符连接。
这里我使用的是第二种方式,callbackBody 采用json字符串。但是这跟以往的字符串不一样,中间有阿里自带的字符bucket,object,size等以及自定义的字符,ali oss 需要解析自定义字符,这里可以理解成变量的一个占位符,那么json串是如何拼接一个占位符变量呢?可以参照官网的一篇错误排查文章:https://yq.aliyun.com/articles/68863/callbackBody
定义的原来是一个字符串的jsonobject,一直以为需要定义一个占位符类型的jsonobject对象,例如:callbackBody应该拼成这样 "{\'bucket\':${bucket},\'object\':${object},\'size\':${size},\'mimeType\':${mimeType},\'uid\':${x:uid},\'biz_type\':${x:biz_type}}"