图片上传
一、七牛云oss介绍
1.1 图片存储介绍
在实际开发中,我们会有很多处理不同功能的服务器。例如:
应用服务器:负责部署我们的应用
数据库服务器:运行我们的数据库
文件服务器:负责存储用户上传文件的服务器

分服务器处理的目的是让服务器各司其职,从而提高我们项目的运行效率。
常见的图片存储方案:
方案一:使用nginx搭建图片服务器(最不常用)
方案二:使用开源的分布式文件存储系统,例如Fastdfs、HDFS等
方案三:使用云存储,例如阿里云、七牛云等
1.2 使用
1.2.1 注册账号
1.2.2 创建存储空间

1.2.3 开发文档
快速入门文档: https://developer.qiniu.com/kodo/1233/console-quickstart
java 开发SDK文档: https://developer.qiniu.com/kodo/1239/java
1.2.4 鉴权
鉴权:Java SDK的所有的功能,都需要合法的授权。授权凭证的签算需要七牛账号下的一对有效的Access Key和Secret Key
1.2.5 工具类封装
1)添加依赖
<!--七牛云的图片上传依赖-->
<dependency>
<groupId>com.qiniu</groupId>
<artifactId>qiniu-java-sdk</artifactId>
<version>7.16.0</version>
</dependency>
2)编写工具类
package com.woniuxy.portal.utils;
import com.google.gson.Gson;
import com.qiniu.common.QiniuException;
import com.qiniu.http.Response;
import com.qiniu.storage.BucketManager;
import com.qiniu.storage.Configuration;
import com.qiniu.storage.Region;
import com.qiniu.storage.UploadManager;
import com.qiniu.storage.model.DefaultPutRet;
import com.qiniu.util.Auth;
public class QiNiuUploadUtils {
/**
* 图片上传
* @param uploadBytes
* @param filename
*/
public static String uploadFile(byte[] uploadBytes, String filename){
//构造一个带指定 Region 对象的配置类
Configuration cfg = new Configuration(Region.region2());
cfg.resumableUploadAPIVersion = Configuration.ResumableUploadAPIVersion.V2;// 指定分片上传版本
//...其他参数参考类注释
UploadManager uploadManager = new UploadManager(cfg);
//...生成上传凭证,然后准备上传
String accessKey = "2Zoe5PP-D0Jxf3pcIHjVzgOaVxxxx";
String secretKey = "w4nWQuFo_0VpybJ6pnesFmOZ9xxxx";
String bucket = "xxxx";
//外链接域名
String url = "http://smgw1dpx5.hn-bkt.xxxx";
//默认不指定key的情况下,以文件内容的hash值作为文件名 文件的名称
String key = filename;
// 签名(密码)
Auth auth = Auth.create(accessKey, secretKey);
String upToken = auth.uploadToken(bucket);
try {
Response response = uploadManager.put(uploadBytes, key, upToken);
//解析上传成功的结果
DefaultPutRet putRet = new Gson().fromJson(response.bodyString(), DefaultPutRet.class);
// http://smgw1dpx5.hn-bxxxx/zs.jpg
return url +"/" +filename;
} catch (QiniuException ex) {
Response r = ex.response;
System.err.println(r.toString());
try {
System.err.println(r.bodyString());
} catch (QiniuException ex2) {
//ignore
}
}
return "";
}
/**
* 删除文件
* @param fileName
*/
public static void deleteFile(String fileName){
//构造一个带指定 Region 对象的配置类
Configuration cfg = new Configuration(Region.region2());
//...其他参数参考类注释
String accessKey = "2Zoe5PP-D0Jxf3pcIHjVzgOaVKAxxxx";
String secretKey = "w4nWQuFo_0VpybJ6pnesFmOZ9xxxx";
String bucket = "xxxx";
//外链接域名
Auth auth = Auth.create(accessKey, secretKey);
BucketManager bucketManager = new BucketManager(auth, cfg);
try {
bucketManager.delete(bucket, fileName);
} catch (QiniuException ex) {
//如果遇到异常,说明删除失败
System.err.println(ex.code());
System.err.println(ex.response.toString());
}
}
}
二、头像上传
2.1 后端上传图片开发
2.2.1 编写上传图片的控制器
package com.woniuxy.portal.controller;
import com.woniuxy.portal.utils.QiNiuUploadUtils;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;
import java.io.IOException;
import java.util.UUID;
@RestController
@RequestMapping("/upload")
@Api(tags = "文件上传")
public class UploadController{
// @RequestPart 接受 前端 传递过来的图片
@ApiOperation("文件上传")
@PostMapping("/images")
public ResponseEntity<String> upload(@RequestPart MultipartFile file) throws IOException {
// 1. 获取文件名称
String originalFilename = file.getOriginalFilename();
// 2. 重新设置文件的名称
String uuid = UUID.randomUUID().toString();
// 文件的名称 = uuid + 源文件的后缀
String substring = originalFilename.substring(originalFilename.lastIndexOf("."));
String fileName = uuid + substring;
fileName = fileName.replaceAll("-", "");
// 3. 调用图片上传的工具类
String pathUrl = QiNiuUploadUtils.uploadFile(file.getBytes(), fileName);
// 4. 响应数据
return ResponseEntity.ok(pathUrl);
}
@ApiOperation("删除图片")
@GetMapping("/delete")
public ResponseEntity delete(String fileName){
QiNiuUploadUtils.deleteFile(fileName);
return ResponseEntity.ok().build();
}
}
2.2.2 swagger测试
注意:springmvc处理上传的文件,要想通过swagger测试,需要添加注解@RequestPart,声明是一个文件上传表单
2.2.3 图片上传优化
存在的问题
String accessKey = "xxx";
String secretKey = "xxx";
String bucket = "xxx";
七牛云的账号全部是写在代码里面的,将来要修改的话不是非常方便,而且有可能会漏掉,所以,将配置项全部移到配置文件中
1)将账号配置到配置文件中
# 七牛云账号相关配置
qiNiu:
accessKey: xxx
secretKey: xxx
bucket: xxx
2)定义常量类
在common工程中定义一个常量类
package com.woniu.entity;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;
import javax.annotation.PostConstruct;
/**
* 常量类,定义各种常量
*/
@Component
public class Constant {
@Value("${qiNiu.accessKey}")
private String accessKey;
@Value("${qiNiu.secretKey}")
private String secretKey;
@Value("${qiNiu.bucket}")
private String bucket;
public static String ACCESSKEY;
public static String SECRETKEY;
public static String BUCKET;
// 对象创建之后执行该方法
@PostConstruct
public void init(){
ACCESSKEY = this.accessKey;
SECRETKEY = this.secretKey;
BUCKET = this.bucket;
}
}
3)修改工具类
String accessKey = Constant.ACCESSKEY;
String secretKey = Constant.SECRETKEY;
String bucket = Constant.BUCKET;
2.2 前端上传图片开发
2.2.1 从官网拷贝组件
<script setup>
import { ref } from 'vue'
import { ElMessage } from 'element-plus'
const imgUrl = ref('')
const handleAvatarSuccess = (response) => {
console.log(response);
// 文件上传成功后的处理,通常是返回头像的 URL
imgUrl.value =response;
}
const submitAvatar = () => {
//提交数据
const user = {
username:"zs",
age:"30",
url:imgUrl.value
}
if (imgUrl.value) {
ElMessage.success('头像修改成功'+ user.url + ",用户信息进行修改")
} else {
ElMessage.error('请先上传头像')
}
}
</script>
<template>
<el-row class="avatar-uploader-container">
<el-col :span="12" class="avatar-uploader-col">
<el-upload
action="http://localhost:8080/upload/images"
class="avatar-uploader"
:show-file-list="false"
:on-success="handleAvatarSuccess">
<img v-if="imgUrl" :src="imgUrl" class="avatar" />
<img v-else src="@/assets/logo.png" class="default-avatar" />
</el-upload>
<el-button
type="success"
size="large"
@click="submitAvatar"
class="upload-button">
上传头像
</el-button>
</el-col>
</el-row>
</template>
<style scoped>
.avatar-uploader-container {
display: flex;
justify-content: center;
align-items: center;
margin-top: 30px;
}
.avatar-uploader-col {
display: flex;
flex-direction: column;
justify-content: center;
align-items: center;
}
.avatar-uploader {
border: 2px solid #e4e7ed;
border-radius: 50%;
width: 120px;
height: 120px;
background-color: #f3f4f6;
display: flex;
justify-content: center;
align-items: center;
cursor: pointer;
transition: border-color 0.3s ease;
}
.avatar-uploader:hover {
border-color: #409eff;
}
.avatar {
width: 100%;
height: 100%;
object-fit: cover;
border-radius: 50%;
}
.default-avatar {
width: 60%;
height: 60%;
object-fit: contain;
}
.upload-button {
margin-top: 15px;
background-color: #409eff;
border-color: #409eff;
color: white;
border-radius: 20px;
padding: 10px 30px;
font-size: 16px;
transition: background-color 0.3s ease, border-color 0.3s ease;
}
.upload-button:hover {
background-color: #66b1ff;
border-color: #66b1ff;
}
.upload-button:focus {
outline: none;
}
.upload-button i {
margin-right: 8px;
}
</style>
2.2.3 修改上传成功的回调
//上传成功回调的处理方法
const handleAvatarSuccess = (response) => {
console.log(response);
// 文件上传成功后的处理,通常是返回头像的 URL
imgUrl.value =response;
}
2.2.3效果图:

1317

被折叠的 条评论
为什么被折叠?



