SpringBoot+OSS+VUE(前后端 · 素材管理)
功能:
1. 实现客户端WEB直传(图片上传)
2. 实现素材管理模块有图片上传(客户端直传)、OSS删除。
实现步骤:
1. 数据库创建两张表一张是分组素材表、一张素材详细表
2. 创建Springboot项目,此处就详细讲解了。。。。不在的小伙伴可以去网上查找
- 创建Springboot项目:https://blog.csdn.net/qq_42539533/article/details/90607415
3. 安装SDK,在Maven项目中加入依赖项(推荐方式)
<dependency>
<groupId>com.aliyun.oss</groupId>
<artifactId>aliyun-sdk-oss</artifactId>
<version>2.8.3</version>
</dependency
4. 介绍OSS是什么?
- Object Storage Service,简称 OSS,是阿里云提供的海量、安全、低成本、高可靠的云存储服务。
- OSS官方地址:对象存储OSS_云存储服务_企业数据管理_存储-阿里云
- OSSWeb上传数据到OSS(前端) :如何基于PostPolicy的使用规则服务端签名直传并设置上传回调_对象存储-阿里云帮助中心
- OSSWeb上传数据到OSS(Java后端) :如何通过Java在服务端签名直传并设置上传回调_对象存储-阿里云帮助中心
流程介绍
- 因为公司已经开通OSS配置好OSS所有这里我就不详细截图展示了,要开通才可以使用,我采用的是OSS最佳实践方式来实现文件上传。
- 为什么要采用这种方式来实现呢?它的好处在那呢?为什么要这么做的原因呢?来着这些问题给你们讲解。
- 采用这种方式是让系统服务不需要承受较大带宽,减少开发成本、易维护,想想用普通上传方式客户端都需要经过服务端处理,而用客户端直传方式(Web直传)不需要经过服务端处理,而是经过客户直接上传图片并让OSS返回回调接口,减轻服务器的压力,提高服务端处理图片效率、减轻IO流繁琐流程处理。
String accessId = "<yourAccessKeyId>"; // 请填写您的AccessKeyId。
String accessKey = "<yourAccessKeySecret>"; // 请填写您的AccessKeySecret。
String endpoint = "oss-cn-hangzhou.aliyuncs.com"; // 请填写您的 endpoint。
String bucket = "bucket-name"; // 请填写您的 bucketname 。
String host = "https://" + bucket + "." + endpoint; // host的格式为 bucketname.endpoint
// callbackUrl为 上传回调服务器的URL,请将下面的IP和Port配置为您自己的真实信息。
String callbackUrl = "http://88.88.88.88:8888";
String dir = "user-dir-prefix/"; // 用户上传文件时指定的前缀。
流程如下图所示:
5. 进入主题
1.文件上传是
Java后端
OssService:
package com.qlrsoft.smart_store.admin.system.service;
import com.qlrsoft.smart_store.admin.bean.ResultBean;
import javax.servlet.http.HttpServletRequest;
/**
* oss上传及回调接口
* @author Lwb
*/
public interface OssService {
/**
* 服务端生成签名
* @return
*/
ResultBean getPolicy(HttpServletRequest request);
/**
* 回调接口
* @param request
* @return
*/
ResultBean callback(HttpServletRequest request);
}
OssServiceImpl:
package com.qlrsoft.smart_store.admin.system.service.impl;
import cn.hutool.json.JSONUtil;
import cn.stylefeng.roses.core.util.ToolUtil;
import com.alibaba.fastjson.JSONObject;
import com.aliyun.oss.OSSClient;
import com.aliyun.oss.common.utils.BinaryUtil;
import com.aliyun.oss.model.MatchMode;
import com.aliyun.oss.model.PolicyConditions;
import com.qlrsoft.smart_store.admin.bean.Constants;
import com.qlrsoft.smart_store.admin.bean.OssCallbackParam;
import com.qlrsoft.smart_store.admin.bean.ResultBean;
import com.qlrsoft.smart_store.admin.core.storage.oss.OssFileOperator;
import com.qlrsoft.smart_store.admin.system.service.OssService;
import com.qlrsoft.smart_store.mall.entity.MaterialDetails;
import com.qlrsoft.smart_store.mall.service.MaterialDetailsService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import javax.servlet.http.HttpServletRequest;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;
@Service
@Slf4j
public class OssServiceImpl implements OssService {
@Autowired
private OSSClient ossClient;
@Autowired
private MaterialDetailsService materialDetailsService;
@Value("${aliyun.oss.policy.expire}")
private int ALIYUN_OSS_EXPIRE;
@Value("${aliyun.oss.maxSize}")
private int ALIYUN_OSS_MAX_SIZE;
@Value("${aliyun.oss.callback}")
private String ALIYUN_OSS_CALLBACK;
@Value("${aliyun.oss.endpoint}")
private String ALIYUN_OSS_ENDPOINT;
@Value("${aliyun.oss.internet-file-url}")
private String INTERNET_FILE_URL;
/**
* 服务端生成签名
*
* @return
*/
@Override
public ResultBean getPolicy(HttpServletRequest request) {
JSONObject resultBean = new JSONObject();
String pic_location = String.valueOf(System.currentTimeMillis());
// 存储目录
String dir = pic_location+"/";
// 签名有效期
long expireEndTime = System.currentTimeMillis() + ALIYUN_OSS_EXPIRE * 1000;
Date expiration = new Date(expireEndTime);
// 文件大小
long maxSize = ALIYUN_OSS_MAX_SIZE * 1024 * 1024;
Map<String,String> map=new HashMap<>();
map.put("Cookie",request.getHeader("Cookie"));
// 回调
OssCallbackParam callback = new OssCallbackParam();
callback.setCallbackUrl(ALIYUN_OSS_CALLBACK);
callback.setSignatureVersion("2.0");
callback.setAdditionalHeaders(map);
callback.setCallbackBody("filename=${object}&size=${size}&mimeType=${mimeType}&height=${imageInfo.height}&width=${imageInfo.width}");
callback.setCallbackBodyType("application/x-www-form-urlencoded");
// 提交节点
String action = INTERNET_FILE_URL;
try {
PolicyConditions policyConds = new PolicyConditions();
policyConds.addConditionItem(PolicyConditions.COND_CONTENT_LENGTH_RANGE, 0, maxSize);
policyConds.addConditionItem(MatchMode.StartWith, PolicyConditions.COND_KEY, dir);
String postPolicy = ossClient.generatePostPolicy(expiration, policyConds);
byte[] binaryData = postPolicy.getBytes("utf-8");
String policy = BinaryUtil.toBase64String(binaryData);
String signature = ossClient.calculatePostSignature(postPolicy);
String callbackData = BinaryUtil.toBase64String(JSONUtil.parse(callback).toString().getBytes("utf-8"));
resultBean.put("accessid",ossClient.getCredentialsProvider().getCredentials().getAccessKeyId());
resultBean.put("policy",policy);
resultBean.put("signature",signature);
resultBean.put("dir",dir);
resultBean.put("expire",String.valueOf(expireEndTime / 1000));
resultBean.put("callback",callbackData);
resultBean.put("host",action);
// 返回结果
} catch (Exception e) {
log.error("签名生成失败", e);
return new ResultBean(Constants.RESCODE_SIGNATION_FAILED,Constants.RESMSG_SIGNATION_FAILED);
}
return new ResultBean(Constants.RESCODE_SUCCESS,Constants.RESMSG_SUCCESS,resultBean);
}
/**
* 回调接口
*
* @param request
* @return
*/
@Override
public ResultBean callback(HttpServletRequest request) {
MaterialDetails materialDetails=new MaterialDetails();
JSONObject resultBean = new JSONObject();
String filename = String.valueOf(request.getParameter("filename"));
materialDetails.setFileName(filename);
String substring = filename.substring(filename.lastIndexOf("/") + 1);
//截取图片类别
String groupingId = filename.substring(filename.lastIndexOf("."));
//获取图片名称
materialDetails.setDetailsName(substring);
filename = INTERNET_FILE_URL.concat("/").concat(filename);
//获取图片地址
materialDetails.setDetailsAddress(filename);
//获取分组Id
materialDetails.setGroupingId(Long.valueOf(OssFileOperator.getGroupingId(groupingId)));
//图片文件大小
materialDetails.setDetailsSize(String.valueOf(OssFileOperator.bytes2kb(Long.valueOf(request.getParameter("size")))+"KB"));
//获取文件后缀
String fileSuffix = ToolUtil.getFileSuffix(filename);
//图片类别
materialDetails.setDetailsCategory(fileSuffix);
resultBean.put("filename",filename);
resultBean.put("size",request.getParameter("size"));
resultBean.put("mimeType",request.getParameter("mimeType"));
resultBean.put("width",request.getParameter("width"));
resultBean.put("height",request.getParameter("height"));
//素材信息保存
materialDetailsService.save(materialDetails);
return new ResultBean(Constants.RESCODE_SUCCESS,Constants.RESMSG_SUCCESS,resultBean);
}
}
OssController :
package com.javaboy.aliyun_oss_upload.controller;
import com.javaboy.aliyun_oss_upload.bean.ResultBean;
import com.javaboy.aliyun_oss_upload.service.OssService;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import javax.servlet.http.HttpServletRequest;
@RestController
@RequestMapping("/aliyun/oss")
public class OssController {
private static Logger log = LoggerFactory.getLogger(OssController.class);
@Autowired
private OssService ossService;
@GetMapping("/policy")
public ResultBean policy() {
ResultBean result = ossService.getPolicy();
log.info("服务端生成签名:{}",result);
return result;
}
@PostMapping("/callback")
public ResultBean callback(HttpServletRequest request) {
ResultBean ossCallbackResult = ossService.callback(request);
log.info("oss成功的回调:{}",ossCallbackResult);
return ossCallbackResult;
}
}
bean
package com.qlrsoft.smart_store.admin.bean;
public class Constants {
public final static String RESCODE_SUCCESS = "0000";
public final static String RESMSG_SUCCESS = "成功";
public final static String RESCODE_SIGNATION_FAILED = "9999";
public final static String RESMSG_SIGNATION_FAILED = "生成签名失败";
}
package com.qlrsoft.smart_store.admin.bean;
import lombok.Data;
import java.util.Map;
/**
* oss上传成功后的回调参数
*/
@Data
public class OssCallbackParam {
/**
* 请求的回调地址
*/
private String callbackUrl;
/**
* 回调是传入request中的参数
*/
private String callbackBody;
/**
* 回调时传入参数的格式,比如表单提交形式
*/
private String callbackBodyType;
private String signatureVersion;
private Map<String, String> additionalHeaders;
}
package com.qlrsoft.smart_store.admin.bean;
public class ResultBean {
private String resCode;
private String resMsg;
private Object resultContent;
public ResultBean(String resCode, String resMsg){
this.resCode = resCode;
this.resMsg = resMsg;
}
public ResultBean(String resCode, String resMsg, Object resultContent){
this.resCode = resCode;
this.resMsg = resMsg;
this.resultContent = resultContent;
}
public ResultBean(){}
public String getResCode() {
return resCode;
}
public void setResCode(String resCode) {
this.resCode = resCode;
}
public String getResMsg() {
return resMsg;
}
public void setResMsg(String resMsg) {
this.resMsg = resMsg;
}
public Object getResultContent() {
return resultContent;
}
public void setResultContent(Object resultContent) {
this.resultContent = resultContent;
}
@Override
public String toString() {
return "ResultBean{" +
"resCode='" + resCode + '\'' +
", resMsg='" + resMsg + '\'' +
", resultContent=" + resultContent +
'}';
}
}
前端:
formImgUpload.vue
<template>
<el-upload
v-if="show"
class="upload-demo"
:drag="drag"
:accept="'image/png, image/jpg, image/jpeg'"
:action="fileUploadUrl"
:http-request="getPolicy"
:on-remove="handleRemove"
:before-remove="beforeRemove"
:multiple="multiple"
:limit="limit"
:disabled="disabled"
:on-exceed="handleExceed"
:file-list="fileList"
:on-success="handleSuccess&#