需求
在学习开发的过程中,一般接触的都是json对象类型的增删改查,刚开始做项目的时候需要图片上传功能,第一次做还不知道如何实现。
一般后端返回给前端图片有两种方法
- 返回base64编码(图片不能太大)
- 返回图片的地址url(可以借助阿里云或七牛等服务)
开启COS服务
为了节省本机空间在这里我选择腾讯云COS对象储存,把图片存在腾讯云上。注册腾讯云账号可以领取6个月免费的对象储存服务。
腾讯云COS地址
创建储存桶的时候权限要设置成公有读私有写。
一定要把静态网站功能打开,这样就能通过地址访问你上传的图片了。
后端代码
查看文档并编写配置类
文档地址
查看文档导入获取maven地址
<!-- 腾讯COS-->
<dependency>
<groupId>com.qcloud</groupId>
<artifactId>cos_api</artifactId>
<version>5.6.45</version>
</dependency>
查看文档的编写出自己的方法,我这里只实现了图片头像的上传和删除两个方法,构造COSClient的所需参数都将它们提取出来设为私有变量。这些属性都可以在文档或者官网找到
public class TencentCos {
// 初始化用户身份信息(secretId, secretKey)。
// SECRETID和SECRETKEY请登录访问管理控制台进行查看和管理
private String secretId;
private String secretKey;
//区域地址,可在对象储存介绍中查看
private String regionAddr;
//桶名称
private String bucketName;
//储存桶的远程地址
private String remoteAddr;
//COS客户端
private COSClient cosClient = null;
public TencentCos(String secretId, String secretKey, String regionAddr, String bucketName, String remoteAddr){
this.secretId = secretId;
this.secretKey = secretKey;
this.regionAddr = regionAddr;
this.bucketName = bucketName;
this.remoteAddr = remoteAddr;
COSCredentials cred = new BasicCOSCredentials(secretId, secretKey);
ClientConfig clientConfig = new ClientConfig(new Region(regionAddr));
// clientConfig 中包含了设置 region, https(默认 http), 超时, 代理等 set 方法, 使用可参见源码或者常见问题 Java SDK 部分。
// 这里建议设置使用 https 协议
clientConfig.setHttpProtocol(HttpProtocol.https);
// 3 生成 cos 客户端。
cosClient = new COSClient(cred, clientConfig);
}
public Map uploadAvatar(MultipartFile avatar) {
// 指定文件上传到 COS 上的路径,即对象键。例如对象键为folder/picture.jpg,则表示将文件 picture.jpg 上传到 folder 路径下
Date time = Calendar.getInstance().getTime();
String path = "avatar/" + new SimpleDateFormat("yyyy-MM-dd").format(time);
String key = path+"/" + UUID.randomUUID().toString()+".jpg";
ObjectMetadata objectMetadata = new ObjectMetadata();
try {
// 设置输入流长度为
objectMetadata.setContentLength(avatar.getInputStream().available());
// 设置 Content type, 默认是 application/octet-stream
objectMetadata.setContentType(avatar.getContentType());
cosClient.putObject(bucketName, key, avatar.getInputStream(), objectMetadata);
return MapUtil.builder().
put("remoteAddr", regionAddr)
.put("key", key).build();
} catch (IOException e) {
e.printStackTrace();
}
return null;
}
//删除头像
public void deleteAvatar(String key){
cosClient.deleteObject(bucketName, key);
}
}
然后在配置文件yml中将这些属性配上
接下来将获取这些配置值并将自己编写的类TencentCos放入IOC容器中
@Configuration
public class TencentConfig {
@Value("${cos.secretId}")
private String secretId;
@Value("${cos.secretKey}")
private String secretKey;
@Value("${cos.regionAddr}")
private String regionAddr;
@Value("${cos.bucketName}")
private String bucketName;
@Value("${cos.remoteAddr}")
private String remoteAddr;
@Bean
public TencentCos tencentCos(){
return new TencentCos(secretId, secretKey, regionAddr, bucketName, remoteAddr);
}
}
编写Controller层
controller层就只需要调用TencentCos类里面自己编写的方法就可以了
@RestController
@RequestMapping("/user")
public class UserController {
@Autowired
private TencentCos tencentCos;
@ApiOperation(value = "用户头像上传")
@PostMapping(value = "/avatarUpload")
public Result uploadAvatar(@RequestParam("avatar") MultipartFile avatar){
return Result.success("上传成功",tencentCos.uploadAvatar(avatar));
}
@ApiOperation(value = "用户头像删除")
@GetMapping(value = "/avatarDelete")
public Result uploadAvatar(@RequestParam("key") String key){
tencentCos.deleteAvatar(key);
return Result.success(null);
}
}
前端代码
请求工具类
以上传头像为例,先写出请求方法
request是自己封装的axios请求类
export function uploadAvatar(avatar) {
let param = new FormData()
param.append('avatar', avatar, avatar.name)
return request({
url: '/user/avatarUpload',
method: 'post',
config: {
headers: {'Content-Type': 'multipart/form-data'}
},
data: param
})
}
html代码
利用vant ui提供的文件上传组件实现头像上传功能
<div>
<van-uploader :max-count="1"
ref="avatar"
v-model="fileList"
name="avatar"
upload-text="头像上传"
:after-read="afterRead"
@delete="removeAvatar"
:max-size="10 * 1000 * 1024" @oversize="onOversize"
style="display: flex; justify-content: center; align-items: center"
/>
</div>
vue代码
图片上传成功后后端返回的是 储存桶的地址 和 图片的key,将他们拼接就是图片的地址了,删除图片方法参数只需要传图片的key就行了
<script>
import {Toast} from "vant";
import {uploadAvatar, deleteAvatar} from "../../api/individual";
export default {
name: "Register",
data(){
return{
user:{
username: '',
password: '',
avatar: this.avatarUrl,
phone: ''
},
//图片储存桶地址
remoteAddr: '',
//图片储存的key
avatarKey: '',
fileList: [],
}
},
computed: {
avatarUrl(){
return this.remoteAddr + this.avatarKey
}
},
methods:{
...mapActions('user', ['userRegister']),
//上传头像
afterRead(file) {
file.status = 'uploading'
file.message = '上传中...'
uploadAvatar(file.file).then((res) => {
this.remoteAddr = res.data.remoteAddr
this.avatarKey = res.data.key
this.fileList[0].url = this.user.avatar = this.avatarUrl
this.fileList[0].status = 'done'
this.fileList[0].message = '上传成功'
})
},
onOversize(file) {
Toast('文件大小不能超过 10Mb')
},
//删除头像
removeAvatar(file){
deleteAvatar(this.avatarKey).then((res) => {
this.fileList = []
this.user.avatar = this.remoteAddr = this.avatarKey = ''
Toast.success('移除成功')
})
}
}
}
</script>
最后效果