流程:前端传过去头像,后端接收,然后创建再项目的类路径下创建这个头像,然后把这个头像的地址放到数据库,更新该用户的头像,然后返回这个用户信息,前端接收到这个用户信息,获取到头像地址,访问到项目中保存的头像,但是有安全性的问题,之前打算上传到图床,但是碍于能力问题,一直出错,最后决定将图片保存到项目中。
效果图:
vue采用了第三方的组件,vue-image-crop-upload
步骤1:再前端vue项目中安装
npm install vue-image-crop-upload
npm install –save-dev babel-polyfill
步骤2:使用该组件
<div>
<my-upload
:params="params"//携带传给后端的参数,如何接收往下看后端代码
:modelValue.sync="imagecropperShow"//如果不这样写会出现点击关闭但是关不掉的情况
:key="imagecropperKey" //不用管
:width="300" //不用管
:height="300" //不用管
lang-type="zh" //zh是中文 en是英文
img-format="png" //传给后端图片的格式
:noRotate='false' //不用管
@crop-success="cropSuccess" //图片裁剪完成的回调函数
@crop-upload-success="cropUploadSuccess"//上传成功的回调函数
@crop-upload-fail="cropUploadFail" //上传失败的回调函数
url="/api/uploadAvatar"//访问后端的地址
></my-upload>
</div>
步骤3:js代码
<script>
import 'babel-polyfill'; // es6 shim 引入
import myUpload from 'vue-image-crop-upload';//引入组件
export default {
components: {
'my-upload': myUpload
},
data() {
return {
params:{
cid:this.$cookies.get('cid')//发给后端的携带的参数,按需求,不需要携带直接删掉
},
imagecropperShow: false,
imagecropperKey: 0
}
},
methods: {
cropSuccess(imgDataUrl, field) {
console.log('-------- crop success --------');
console.log(imgDataUrl);
this.avatar=imgDataUrl;
console.log(field);
},
//上传成功回调
cropUploadSuccess(res, originPicName) {//res是后端返回的结果,originPicName是后端接收到图片的名字
console.log('-------- upload success --------');
console.log(res);
console.log(originPicName);
},
//上传失败回调
cropUploadFail(status, field) {
console.log('-------- upload fail --------');
console.log('上传失败状态' + status);
console.log('field: ' + field);
}
}
}
</script>
这段文字请配合之后的代码好好阅读!方便理解
springboot代码,cid就是前端param中的参数,files.get("avatar")好像是因为用了这个第三方组件导致传过来的图片好像都变成avatar.png格式的了,不大清楚,如果直接复制运行发现有问题,可以debug一下,看看接收到的文件她名字是什么,然后把avatar改成你的就可以了,ApiResult是我的返回值,你们可以直接设为void,return就不需要了,先看有没有成功再项目对应位置保存下图片,注意:项目的绝对路径不要有中文!!!否则会创建一个新的文件夹,中文名字是一乱英文的那种,然后通过浏览器去访问项目的图片好像会访问不到。 try中的代码studentService.changeImg(cid, img);
Student student = studentService.findById(cid);
是我为了把项目中的图片地址保存到数据库然后再查找出这个修改之后的学生返回给前端,参考的时候可以先看是否成功保存下来图片,再去考虑添加到数据库这个图片的地址
@Autowired
ServerConfig serverConfig;
@PostMapping("/uploadAvatar")
public ApiResult uploadAvatar(long cid, MultipartHttpServletRequest multipartHttpServletRequest, HttpServletRequest request) throws IOException {
//得到文件map对象
Map<String, MultipartFile> files = multipartHttpServletRequest.getFileMap();
// 得到图片file
MultipartFile file = files.get("avatar");
// 获得项目绝对路径的static/headImage/学号/ 的位置
String path = ResourceUtils.getURL("classpath:").getPath() + "static/headImage/students/"+cid+"/";
// 获得项目的根路径+/headImage/ 即/headImage/
String url = request.getContextPath() + "/headImage/students/"+cid+"/";
// 创建一个文件
File filePath = new File(path);
System.out.println("文件的保存路径:" + path);
if (!filePath.exists() && !filePath.isDirectory()) {
System.out.println("目录不存在,建立目录:" + filePath);
filePath.mkdirs(); // mkdir()不会建立目录,找不到相应路径时返回false;而mkdirs()当目录不存在时则会建立相应目录
}
//获取原始文件名称(包含格式)
String originalFileName = file.getOriginalFilename();
//获取文件类型,以最后一个`.`为标识 png
String type = originalFileName.substring(originalFileName.lastIndexOf(".") + 1);
// 新文件名,这里能够根据须要更名
String fileName = cid+"_"+ SaltUtil.getSalt(8)+ "."+ type;
//在指定路径下建立一个文件
File targetFile = new File(path, fileName); // 未使用outputStream.write()的时候,是一个File对象,保存在内存中,硬盘中看不到,可是可使用这个对象
try {
// 使用springmvc的transferTo方法上传文件
file.transferTo(targetFile);
// http://192.168.220.1:8080 +
String HostAndPortUrl=serverConfig.getUrl();
// 获取该项目的主机和端口号 192.168.220.1:8080 +/headImage/学号/+图片名
String img=HostAndPortUrl+ url + fileName;
System.out.println(img);
studentService.changeImg(cid, img);
Student student = studentService.findById(cid);
return ApiResultHandler.buildApiResult(200,"头像上传到本地成功",student);
} catch (IOException e) {
e.printStackTrace();
}
return ApiResultHandler.buildApiResult(400,"头像上传到本地失败",null);
}
SaltUtil类,获取随即码用了,方便每个图片名字不同
public class SaltUtil {
public static String getSalt(int n){
char[] chars="ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz1234567890".toCharArray();
StringBuilder sb=new StringBuilder();
for (int i = 0; i < n; i++) {
char aChar = chars[new Random().nextInt(chars.length)];
sb.append(aChar);
}
return sb.toString();
}
public static void main(String[] args) {
String salt = getSalt(8);
System.out.println(salt);
}
}
ServerConfig类,用来获取当前项目的host和端口号
@Component
public class ServerConfig implements ApplicationListener<WebServerInitializedEvent> {
private int serverPort;
public String getUrl() {
InetAddress address = null;
try {
// 192.168.220.1
address = InetAddress.getLocalHost();
} catch (UnknownHostException e) {
e.printStackTrace();
}
return "http://"+address.getHostAddress() +":"+this.serverPort;
}
@Override
public void onApplicationEvent(WebServerInitializedEvent event) {
this.serverPort = event.getWebServer().getPort();
}
}
如果有帮到你的话,帮忙点个👍吧。有问题可以评论或者私信联系,相信各位的能力应该都能成功完成该简单的功能。最后,该功能安全性很低,因为返回的图片地址就是后端项目的地址,如果只是简单的毕设功能,可以参考使用。