项目源码与所需资料
链接:https://pan.baidu.com/s/1azwRyyFwXz5elhQL0BhkCA?pwd=8z59
提取码:8z59
demo06-上传讲师头像
1.阿里云oss
1.1介绍
为什么要使用对象存储oss?
我们在javaweb阶段应该也做过上传,那时候我们要么把文件存到tomcat中,要么把文件存到本地路径中,比如说我是存到本地路径中,那么你在你的电脑上是访问不到我电脑中的文件的(除非做特殊处理)。
所以我们需要把内容存到一个所有人都能访问到的地方,这个地方就是对象存储oss:存到oss中的文件可以被别人访问
1.2开通"对象存储oss"服务
1.进入阿里云官网https://www.aliyun.com
2.有账号的点击"登录",没有账号的点击"立即注册"来注册账号(建议使用支付宝注册,因为注册后需要做实名认证,使用支付宝注册的话比较方便)
3.注册成功后登录账号,进行实名认证
4.在搜索栏搜索"对象存储oss",点击"对象存储OSS"
5.开通oss服务
1.3创建Bucket
Bucket就相当于一个电脑中的包,或者说是文件夹
1.点击"创建Bucket"
2.填写信息
- Bucket名称随便填写,但是别写中文
- 存储类型选择"低频访问存储"就够用了
- 区域使用默认的就可以了
- 读写权限设为"公共读"或"公共读写"都可以,我设置的是"公共读"
1.4在阿里云后台上传默认头像
1.点击文件管理–>上传文件来上传讲师默认头像
2.将图片拖拽过来
3.可以看到此时显示"已扫描待上传",然后我们点击"上传文件"即可
4.回到"文件管理",点击"详情"就可以显示出我们刚刚上传的照片的详细信息
5.在这张照片的详细信息中我们可以看到oss为我们生成的图片地址https://edu-mxy.oss-cn-hangzhou.aliyuncs.com/default.jpg
6.在浏览器地址栏输入 https://edu-mxy.oss-cn-hangzhou.aliyuncs.com/default.jpg就可以下载保存这张图片了
1.5创建操作阿里云oss的许可证
实际开发中,是要使用java代码操作阿里云oss,然后上传文件到阿里云oss,使用java代码操作阿里云oss是需要许可证的(许可证就是阿里云给你颁发一个id和秘钥,只有拿着id和秘钥才可以操作).下面我们来创建许可证
1.点击头像中的"AccessKey 管理"
2.点击"继续使用 AccessKey"
3.点击"创建 AccessKey"
4.就会生成id和秘钥
2.后端环境搭建——后端集成oss
2.1在service下创建子模块service_oss
1.在service上右键,选择New–>Module…
2.我们这里是创建一个maven工程
3.填写信息
2.2添加依赖
在service_oss中添加下面这些依赖(在service中添加下面这些依赖也是可以的,但因为这些依赖只会在service_oss中使用,所以我们在service_oss添加就可以了)
<dependencies>
<!-- 阿里云oss依赖 -->
<dependency>
<groupId>com.aliyun.oss</groupId>
<artifactId>aliyun-sdk-oss</artifactId>
</dependency>
<!-- 日期工具栏依赖 -->
<dependency>
<groupId>joda-time</groupId>
<artifactId>joda-time</artifactId>
</dependency>
</dependencies>
2.3配置
1.进行配置前先看一下我们的地域节点:
点击对象存储–>Bucket列表–>edu-mxy–>概览,可以看到我的地域节点是oss-cn-hangzhou.aliyuncs.com(咱俩的地域节点可能不一样,你就看你的就行)
2.创建配置文件application.properties并编写配置
#服务端口
server.port=8002
#服务名
spring.application.name=service-oss
#环境设置:dev、test、prod
spring.profiles.active=dev
#阿里云 OSS
#不同的服务器,地址不同
aliyun.oss.file.endpoint=oss-cn-hangzhou.aliyuncs.com
aliyun.oss.file.keyid=LTAI5tMUCkxmE6ouUc2dmbXm
aliyun.oss.file.keysecret=0Py10jHOPVkeFp6MiIm88c9QqyykUE
#bucket可以在控制台创建,也可以使用java代码创建
aliyun.oss.file.bucketname=edu-mxy
aliyun.oss.file.endpoint=oss-cn-hangzhou.aliyuncs.com
是地域节点,就是第1步我让你看的那个aliyun.oss.file.keyid=LTAI5tMUCkxmE6ouUc2dmbXm
、aliyun.oss.file.keysecret=0Py10jHOPVkeFp6MiIm88c9QqyykUE
分别是id和秘钥(我们在"1.5创建操作阿里云oss的许可证"的第4步得到的)- 我平时习惯在等号(=)两边加空格,但是这里的id、秘钥一定不能在等号(=)右边加空格,加的空格会被识别为id、秘钥的一部分(地域节点和Bucket名称我不知道是不是也这样,但我懒得去试,我索性在等号右边都不加空格不就行了)
aliyun.oss.file.bucketname=edu-mxy
是Bucket的名称,我们在"1.3创建Bucket"的第2步填写信息时填的Bucket名称
注意:
- 因为地域节点、id、秘钥、Bucket名称,这些都是固定的,所以我们写到配置文件中,后面再使用常量类来读取("3.创建常量类"实现的)
- 地域节点、id、秘钥、Bucket名称,都填你们自己的,别写成我的了
2.4创建启动类
创建包com.atguigu.oss,然后在该包下创建主启动类OssApplication,并在类中编写代码
@SpringBootApplication
@ComponentScan(basePackages = {
"com.atguigu"})
public class OssApplication {
public static void main(String[] args) {
SpringApplication.run(OssApplication.class, args);
}
}
2.5启动项目
1.在"main"上右键选择"Run ‘OssApplication’"启动项目
2.发现项目不能正常启动,我们来看一下报错描述
我们大概能够理解这段描述:就是说启动项目时会找数据库的配置使得能和数据库建立连接,但是我们这个service_oss项目并不需要和数据库建立连接,所以也就没有添加数据库的配置,最后结果就是无法正常启动项目
3.有两种解决方法(我这里使用的是方法二)
解决方法一:
在配置文件application.properties中添加数据库的配置
解决方法二(推荐):
给启动类的注解@SpringBootApplication添加属性exclude = DataSourceAutoConfiguration.class
,该属性作用是:默认不加载数据库配置
4.再次启动该项目,发现现在可以正常启动了
3.创建常量类
1.在service_oss模块的oss包下创建包utils,然后在该包下创建常量类ConstantPropertiesUtils,该类的作用是读取配置文件application.properties中的地域节点、id、秘钥、Bucket名称
@Component
public class ConstantPropertiesUtils {
//读取配置文件内容
@Value("${aliyun.oss.file.endpoint}")
private String endpoint;
@Value("${aliyun.oss.file.keyid}")
private String keyId;
@Value("${aliyun.oss.file.keysecret}")
private String keySecret;
@Value("${aliyun.oss.file.bucketname}")
private String bucketName;
}
注意:这里的@Value注解导的是Spring里面的,别导错包了。该注解的作用是:就拿属性endpoint
及其注解@Value("${aliyun.oss.file.endpoint}")
来举例:在初始化bean时会读取到配置文件中aliyun.oss.file.endpoint的值并赋值给属性endpoint
2.我们确认读取到配置文件中的内容并且赋值给了属性,但是这些属性都是私有的呀,我们怎么才能获取到这些属性的值呢?
这就要借助于InitializingBean接口了:实现了InitializingBean接口的类在初始化bean时都会执行接口中的方法afterPropertiesSet。
完整的实现流程:
- 给常量类添加注解@Component将其交给Spring管理
- 给属性添加@Value
- 定义public的静态常量
- 让常量类实现InitializingBean接口,重写接口的方法afterPropertiesSet,方法内部将私有属性的值赋值给public的静态常量
这样的话,启动service_oss项目后,因为常量类被@Component修饰,所以会初始化bean,在初始化bean的过程中,会先读取配置文件的内容并赋值给私有属性,然后执行重写的afterPropertiesSet方法,方法内部将私有属性的值赋值给public的静态常量
@Component
public class ConstantPropertiesUtils implements InitializingBean {
//读取配置文件内容
@Value("${aliyun.oss.file.endpoint}")
private String endpoint;
@Value("${aliyun.oss.file.keyid}")
private String keyId;
@Value("${aliyun.oss.file.keysecret}")
private String keySecret;
@Value("${aliyun.oss.file.bucketname}")
private String bucketName;
//定义public的静态常量
public static String END_POINT;
public static String ACCESS_KEY_ID;
public static String ACCESS_KEY_SECRET;
public static String BUCKET_NAME;
@Override
public void afterPropertiesSet() throws Exception {
END_POINT = endpoint;
ACCESS_KEY_ID = keyId;
ACCESS_KEY_SECRET = keySecret;
BUCKET_NAME = bucketName;
}
}
4.后端接口实现
因为项目service_oss没有用到数据表,所以没办法用代码生成器来生成代码,只能我们全部手敲
4.1controller层
1.在oss包下创建包service,然后在service包下创建接口OssService、在service包下创建包impl,然后在impl包下创建类OssServiceImpl并且:①让该类其实现接口OssService②给该类添加注解@Service将其交给Spring管理
2.在oss包下创建包controller,然后在controller包下创建类OssController,并在类中编写代码
@RestController
@RequestMapping("/eduoss/fileoss")
@CrossOrigin //解决跨域问题
public class OssController {
@Autowired
private OssService ossService;
//上传头像的方法
@PostMapping
public R uploadOssFile(
MultipartFile file) {
//MultipartFile file用来得到用户上传的文件
//上传文件到oss,并得到文件的url
String url = ossService.uploadFileAvatar(file);
return R.ok().data("url",url);
}
}
-
得到用户上传的文件后,我们需要将文件上传到阿里云oss,上传的方法在service层定义,控制层负责调用service层定义的上传文件的方法uploadFileAvatar(后面我们会去service层定义该方法)
-
数据表edu_teacher的avatar字段用来存用户头像,但存的并不是头像文件,而是头像的地址:oss会为图片生成地址("1.4在阿里云后台上传默认头像"的第5步说过),我们将这个地址存到avatar字段中
- 所以说,我们后面在service层定义的uploadFileAvatar方法需要返回图片的地址,然后在controller层用一个变量来接收这个地址,所以有了这行代码:
String url = ossService.uploadFileAvatar(file);
- 所以说,我们后面在service层定义的uploadFileAvatar方法需要返回图片的地址,然后在controller层用一个变量来接收这个地址,所以有了这行代码:
4.2service层
4.2.1在接口OssService定义方法
public interface OssService {
//上传头像到oss
String uploadFileAvatar(MultipartFile file);
}
4.2.2在实现类OssServiceImpl实现方法
@Service
public class OssServiceImpl implements OssService {
//上传头像到oss
@Override
public String uploadFileAvatar(MultipartFile file) {
//1.工具类获取数据
String endpoint = ConstantPropertiesUtils.END_POINT;
String accessKeyId = ConstantPropertiesUtils.ACCESS_KEY_ID;
String accessKeySecret = ConstantPropertiesUtils.ACCESS_KEY_SECRET;
String bucketName = ConstantPropertiesUtils.BUCKET_NAME;
//2.创建OSS实例
OSS ossClient = new OSSClientBuilder().build(endpoint, accessKeyId, accessKeySecret);
try {
//3.获取到将要上传的文件的输入流
InputStream inputStream = file.getInputStream();
//4.获取到将要上传的文件的名称
String fileName = file.getOriginalFilename();
//5.调用oss的方法实现上传
ossClient.putObject(bucketName, fileName, inputStream);
//6.关闭OSS对象
ossClient.shutdown();
//7.拼接路径
String url = "https://" + bucketName + "." + endpoint + "/" + fileName;
return url;
} catch (Exception e) {
e.printStackTrace();
return null;
}
}
}
注意点一:putObject方法的三个参数:
- 第一个参数:Bucket名称
- 第二个参数:文件上传到oss的哪个地方(即文件路径)和文件名称。比如:/aa/bb/1.jpg
- 我们目前是把图片全部存到oss的根目录下,所以参数只需要文件名称就可以了。我们以后可能会分类存图片,那么参数就需要是
文件路径+文件名称
比如:/aa/bb/1.jpg(在"4.4.2把文件进行分类管理"中实现了)
- 我们目前是把图片全部存到oss的根目录下,所以参数只需要文件名称就可以了。我们以后可能会分类存图片,那么参数就需要是
- 第三个参数:上传的文件的输入流
注意点二:阿里云oss会为我们生成图片路径,但是人家没有给我们提供可以直接得到路径的接口,所以需要我们手动拼接图片路径。我们在"1.4在阿里云后台上传默认头像"的第5步看过阿里云oss为我们生成的图片路径,是:https://edu-mxy.oss-cn-hangzhou.aliyuncs.com/default.jpg,从这个路径中我们可以推出路径格式是:https//+Bucket名称+小数点+地域节点+单斜杠+文件名称
,所以代码是String url = "https://" + bucketName + "." + endpoint + "/" + fileName;
4.3测试
接下来我们使用swagger进行测试:
1.先从控制台中将我们在"1.4在阿里云后台上传默认头像"上传的默认头像删掉
2.启动service_oss项目
3.在地址栏输入http://localhost:8002/swagger-ui.html
4.点击"选择文件",选择我们我们要上传的图片
5.点击"Try it out!"进行测试
6.可以看到测试成功,并且返回的数据中有图片的地址
7.刷新控制台,可以看到图片成功上传到了阿里云oss中
4.4后端接口完善
4.4.1文件名重复
如果这个用户上传了名字为default.jpg的图片,另一个用户后来也上传了名字为default.jpg的图片,那么后来上传的default.jpg会覆盖掉以前上传的default.jpg
解决方法:在文件名称中添加随机唯一值,使得每个文件的名称都不相同
接下来我们在实现类OssServiceImpl的uploadFileAvatar方法中添加如下代码:
//完善:在文件名称里面添加随机唯一的值
//wer4-43u5-323oo-...
String uuid = UUID.randomUUID().toString().replaceAll("-", "");
fileName = uuid + fileName;
使用UUID的方式生成的随机值里面会有横杠(-),比如:wer4-43u5-323oo-…
这个横杠想去掉就去掉,不想去掉就不去掉,我这里使用replaceAll方法将横杠去掉了
4.4.2把文件进行分类管理
这里我们根据日期进行分类
//完善:把文件按照日期进行分类:2022/08/17/01.jpg
//1.获取当前时间
String datePath = new DateTime().toString("yyyy/MM/dd");
//2.拼接
fileName = datePath + "/" + fileName;
获取当前日期:我们可以先new Date(),然后用SimpleDateFormat对日期进行格式转换,转换为我们想要的形式:2022/08/17,但这样做太麻烦了,我们在"2.2添加依赖"中添加了日期工具栏依赖,我们用这个依赖提供的方法来达到我们想要的效果
4.4.3测试
接下来我们使用swagger进行测试:
1.先从控制台中将我们在"1.4在阿里云后台上传默认头像"上传的默认头像删掉
2.重启service_oss项目
3.在地址栏输入http://localhost:8002/swagger-ui.html
4.点击"选择文件",选择我们我们要上传的图片,然后点击"Try it out!"进行测试
5.可以看到测试成功,并且返回的数据中有图片的地址
6.刷新控制台,可以看到图片成功上传到了阿里云oss中,并且把文件按照日期进行分类
5.nginx
5.1简介
nginx的官方描述:反向代理服务器
nginx的常用功能:
- 请求转发
- 负载均衡
- 动静分离
5.2nginx常用功能
5.2.1请求转发
假设我们现在有一个9001端口的nginx,还有两个服务器,一个是8001端口的eduservice,一个是8002端口的eduoss。我们先通过浏览器发送请求到nginx,然后nginx根据不同的请求转发到对应的服务器中
问题:我们有好几个服务器,那么nginx是怎么找到对应的服务器呢?方式有很多种,我们这里说一种常用的方式:根据路径匹配进行转发。比如说,如果关于eduservice服务器的所有请求路径中都含有eduservice,那么我们就在nginx中设置一个规则:当请求路径中包含有eduservice,就把请求转发到8001端口
5.2.2负载均衡
要做负载均衡有一个特点:需要用到集群。集群:比如说我现在有两台服务器,一个端口是8081,另一个端口是8082,但是这两台服务器放的都是edu这个项目
假设我现在有两台服务器,一个端口是8081,另一个端口是8082,但是这两台服务器放的都是edu这个项目,我们先通过浏览器发送请求到nginx,然后nginx会将请求平均分摊到这两个服务器中,假设我们现在有四个请求,那么8081端口的服务器和8082端口的服务器就会分别处理两个请求
问题:nginx是怎么做到平均分摊请求的呢?nginx中有很多算法:①轮询:一个一个来,先给第一个服务器一个请求,然后给第二个服务器一个请求,再给第一个服务器一个请求,然后再给第二个服务器一个请求,直到将nginx中的请求全都分出去②根据请求时间,谁的时间最短就先去访问谁③权重…
我们以后做负载均衡不会使用nginx,会使用网关,因为网关帮我们将功能做了封装,更加方便、简单
5.2.3动静分离
我们在tomcat里面放了java代码部分,然后又专门找了个服务器放静态资源(html、图片…),当我们访问java代码时就去请求tomcat,当我们访问静态资源时就去请求我们的静态服务器
5.3为什么需要使用nginx
我们以前是只有一个端口号为8001的服务器,所以在前端项目的config–>dev.env.js中写了BASE_API: '"http://localhost:8001"',
(忘了这行代码作用的去看"demo05-讲师管理前端"的"3.1修改前端项目访问路径"的第3步),但是我们现在又有了一个端口号为8002的服务器(阿里云oss项目),那么我们怎么应该怎么在前端项目中改呢?如下图,在dev.env.js中加一行代码BASE_API1: '"http://localhost:8002"',
(注意:马上就会说到,这种做法是不可行的,我加了这行代码并截图后就立马把这行代码删掉了)
这种做法是不可行的:如果这样做,那么前端项目中的很多规则就都要改,比如src–>utils–>request.js,如下图所示,画方框的这部分代码就需要修改,修改后的代码中需要有判断
这个时候就要用到我们的nginx了:我们将config–>dev.env.js的BASE_API: '"http://localhost:8001"',
中的端口号改为nginx的9001,然后nginx再做请求转发
5.4安装nginx
1.nginx的压缩包在资料里面有(和老师的版本一样),我们将其解压
2.在解压后的在地址栏中输入cmd后按回车进入命令行窗口
3.使用命令nginx.exe启动nginx,如果看到光标在闪就说明启动成功
5.5重启nginx
1.关闭nginx
在上一步使用cmd启动nginx后,如果关闭cmd窗口,nginx不会停止,我们需要使用命令nginx.exe -s stop关闭nginx
2.启动nginx
使用命令nginx.exe启动nginx(具体操作看"5.4安装nginx"的第2步和第3步)
5.6使用nginx配置项目请求转发
1.打开nginx的配置文件nginx.conf
2.nginx默认端口号是80,我们将它改为81(不改也可以,但可能有冲突)
3.配置nginx转发规则
在http{…}里面编写以下代码来创建配置
server {
listen 9001;
server_name localhost;
location ~ /eduservice/ {
proxy_pass http://localhost:8001;
}
location ~ /eduoss/ {
proxy_pass http://localhost:8002;
}
}
listen 9001;
表示对外的监听端口是9001location ~ /eduoss/ {...}
中的~
表示此时的匹配方式是正则匹配,这样的话只要路径里面包含/eduoss/就可以匹配上,不加~
的话代表只有路径就是/eduoss/时才可以匹配上location ~ /eduservice/ {...}
和location ~ /eduoss/ {...}
里面的/eduservice/、/eduoss/的来源如下截图:
4.在config–>dev.env.js中将前端请求地址修改为nginx的地址
5.7测试
1.修改nginx配置后需要重启nginx(忘了的可以去看"5.5重启nginx")
2.启动8001项目和8002项目
3.修改了前端了配置文件,所以需要重启前端项目
①在终端按Ctrl+c,然后输入y并按回车即可停掉前端项目
②在终端使用命令npm run dev启动前端项目
4.在地址栏输入http://localhost:9528可以看到登录页面,此时按F12点开开发者工具,然后点击按钮"Sign in"按钮
5.在"NetWork"菜单栏下的"Fetch/XHR"菜单栏下,这两个请求我们随便点一个看看,发现请求路径中的端口号是9001,这说明我们成功配置请求转发。
再说一下具体请求流程:浏览器先将请求发送给nginx,然后nginx根据路径匹配规则将请求发送给相应的服务器
6.前端页面(在save.html整合上传组件)
6.1得到上传组件
1.我们可以像以前一样,去element-ui官网复制一个上传组件过来,但里面的组件都太难看了。还记不记得"demo05-讲师管理前端"的"1.搭建项目前端页面环境"的第1步?我们当时说了资料中有一个"vue-element-admin"的压缩文件,我们开发过程中想要什么功能都可以从这里去找
2.可以看到vue-element-admin–>src–>components下有很多组件,其中我们上传需要的组件是"ImageCropper"和"PanThumb"
3.你不用将资料中的"vue-element-admin.zip"解压缩,然后从解压后的文件中找到上传组件。我直接将上传组件的这两个文件夹放到了资料中
4.将上传组件的两个文件夹复制到前端项目的src–>components中
6.2在save.html添加上传组件
在save.html中添加如下代码(只要会修改就可以了,不需要手敲)
<!-- 讲师头像:TODO -->
<el-form-item label="讲师头像">
<!-- 头衔缩略图 -->
<pan-thumb :image="teacher.avatar"/>
<!-- 文件上传按钮 -->
<el-button type="primary" icon="el-icon-upload" @click="imagecropperShow=true">更换头像
</el-button>
<image-cropper
v-show="imagecropperShow"
:width="300"
:height="300"
:key="imagecropperKey"
:url="BASE_API+'/admin/oss/file/upload'"
field="file"
@close="close"
@crop-upload-success="cropSuccess"/>
</el-form-item>
-
image-cropper
是真正的上传组件,是一个表单,用来上传头像- 我们以前发送请求都是使用ajax,但是ajax不能直接上传文件,所以我们需要用提交表单的方式来上传文件
-
:v-show
:是否显示上传组件- 当点击"更换头像"后,会触发
@click="imagecropperShow=true"
,此时就会显示上传组件
- 当点击"更换头像"后,会触发
-
:key
:类似于标签的id属性 -
:url
:表单提交的路径 -
field="file"
:我们在前端学过,上传按钮的代码是:<input type="file" name="file"/>
。field="file"
就相当于以前上传按钮中的name="file"
-
@close
:关闭上传组件 -
@crop-upload-success
:上传成功后会调用这里面的方法
6.3使用组件
在data() {...}
中创建数据模型
imagecropperShow: false, //上传组件是否显示(默认不显示)
imagecropperKey: 0, //上传组件的key值
BASE_API: process.env.BASE_API, //固定写法,表示获得dev.env.js里面的BASE_API值
6.4引入组件和声明组件
1.引入组件模块
import ImageCropper from '@/components/ImageCropper'
import PanThumb from '@/components/PanThumb'
2.在export default {...}
中做一个声明,这样才可以使用这个组件
components: {
ImageCropper, PanThumb },
6.5修改上传接口地址
6.6定义close和cropSuccess方法
定义close方法,点击弹框的关闭按钮时执行此方法,方法内部来关闭弹框;
定义cropSuccess方法,上传成功后回调
//点击弹框的关闭按钮时执行此方法
close() {
//关掉弹框
this.imagecropperShow = false
},
//上传成功后回调
cropSuccess(data) {
//1.关掉弹框
this.imagecropperShow = false
//2.得到图片地址并赋值
this.teacher.avatar = data.url
},
cropSuccess(data) {...}
的参数data是后端返回的数据,就和"demo04-前端技术"的"4.axios"的第7步的②里面的.then(response => {...})
中的参数response类似,只是后者想要得到url需要response.data.data.url
,而前者因为人家给做了封装,想要得到url只需要data.url
6.7设置默认头像
我们在"4.4.3测试"中上传的默认头像的地址是https://edu-mxy.oss-cn-hangzhou.aliyuncs.com/2022/08/17/66e307e5727c41d7a3617891509278dcdefault.jpg所以我们在init方法中添加如下一行代码来设置默认头像
this.teacher.avatar = 'https://edu-mxy.oss-cn-hangzhou.aliyuncs.com/2022/08/17/66e307e5727c41d7a3617891509278dcdefault.jpg'
6.8测试
1.刷新页面,在"添加讲师"路由上传图片
2.点击"保存"后就成功添加了这条讲师数据
3.去数据库看,可以看到确实成功添加讲师数据
4.去阿里云控制台看刚刚上传的图片的详情:
发现一个问题:红框圈的这里是file而不是我们本地的文件名233
这是因为:考虑到我们有的人给文件起名会起中文,所以上传组件内部给我们做了优化:我们通过该组件上传的所有文件这个位置都固定是file而不再是本地的文件名
6.9bug
1.点击"更换头像"成功上传头像后,如果再点"更换头像",会出现下图所示的弹框。这个弹框显示"上传成功"而不是让我们选择图片重新上传,这显然不是我们想要的弹框
2.我们只有将这个弹框关闭后再次点击"更换头像"才会出现我们想要的弹框
3.想要解决这个bug需要每次关闭弹框或上传成功后都初始化上传组件:
给close方法和cropSuccess方法都添加一行代码this.imagecropperKey = this.imagecropperKey + 1;
为什么这行代码可以初始化上传组件?
- 在这两处都加上这行代码后,无论是关闭弹框还是成功上传头像,imagecropperKey的值都会自增1,且在"6.2在save.html添加上传组件"中我们说过
:key="imagecropperKey"
的作用类似于标签的id属性,也就说无论是关闭弹框还是成功上传头像,上传组件的id都会自增1,所以每次点击"更换头像"后打开的都是新的上传组件,这样就实现了初始化上传组件- 当然,我这里是每次让imagecropperKey自增1,其实,让他自增多少,自减多少都是可以的,因为我们的目的仅仅是让每次的imagecropperKey的值不一样就可以了