今日记录通过elementui上传时得到的问题。
我们在本地部署的服务,前端服务请求后端接口,存在跨域问题,
跨域问题确实是由Web浏览器的同源策略引起的。同源策略是浏览器的一项安全机制,它限制了从一个源加载的文档或脚本如何与来自其他源的资源进行交互。
同源策略要求在以下三个方面完全匹配时才被认为是同源:
为什么后端服务跟后端服务的交互,没有跨域;而浏览器和服务器的交互有?
因为,后端服务之间不存在同源策略的限制。
另外,我们通常前端向后端的通信请求,一般依赖的是浏览器的通信API来完成的,当我们请求时,浏览器会检测我们请求的url是否与当前存在跨域问题。
解决跨域:
1.可以利用springboot解决跨域问题,这里不列举
2.利用vue配置进行反向代理。
在vue.config.js文件中配置
- module.exports = {
- devServer: {
- proxy: {
- '/api': { // 请求的代称,写在Axios里的BaseUrl
- target: 'http://localhost:8088', // 真实请求URl
- ws: true,
- changeOrigin: true, // 允许跨域
- pathRewrite: { //替换,通配/api的替换成对应字符
- // /* 重写路径,当我们在浏览器中看到请求的地址为:http://localhost:8080/api/core/getData/userInfo 时
- // 实际上访问的地址是:http://localhost:8088/core/getData/userInfo,因为重写了 /api
- // */
- '^/api': '' //当你的接口中没有/api字眼时,采用这种,直接替换成空即可
- // '^/api': '/api' //当你的接口中刚好有/api 时,采用这种方式
- }
- }
- }
- }
- }
换句话说,在本地创建了一个代理服务器,我们的请求全发到代理服务器上了 ,由代理服务器替我们发请求到后端服务器,拿到响应数据接着响应给我。
java代码如下:
- @RestController
- @RequestMapping("/common")
- @Api(tags = "文件controller")
- public class CommonController {
-
- @Value("${reggie.path}")
- private String basePath;
-
- @ApiOperation("文件上传")
- @PostMapping("/upload")
- public Result upLoad(@RequestParam("file") MultipartFile file) {
-
- // 原始文件名 abc.jpc
- String originalFilename = file.getOriginalFilename();
- // 获取文件类型(jpg、png) .jpc
- String suffix = originalFilename.substring(originalFilename.lastIndexOf("."));
-
- // 使用UUID重新生成文件名,防止文件名重复
- String fileName = UUID.randomUUID() + suffix;
-
- // 创建目录
- File dir = new File(basePath);
- if(!dir.exists()) {
- dir.mkdirs();
- }
-
- try {
-
- file.transferTo(new File(basePath + fileName)); // 当前目录下,生成图片,我们将这个路径返回
- } catch (IOException e) {
- e.printStackTrace();
- }
- return Result.success("文件上传成功", fileName);
- }
-
- @ApiOperation("文件下载")
- @GetMapping("/download")
- public void downLoad(String name, HttpServletResponse response) {
- try {
- // 输入流,通过输入流读取文件内容
- FileInputStream fileInputStream = new FileInputStream(new File(basePath + name));
-
- // 输出流,通过输出流将文件写回浏览器
- ServletOutputStream outputStream = response.getOutputStream();
-
- response.setContentType("image/jpeg");
-
- int len = 0;
- byte[] bytes = new byte[1024]; // 缓存
- while ((len = fileInputStream.read(bytes)) != -1) {
- outputStream.write(bytes, 0, len);
- outputStream.flush();
- }
-
- //关闭资源
- outputStream.close();
- fileInputStream.close();
- } catch (Exception e) {
- e.printStackTrace();
- }
- }
-
-
- }
vue代码如下:
-
"/api/common/upload" //后端请求上传图片接口 - list-type="picture-card"
- :show-file-list="false" // 开启上传图片列表
- :on-success="handleAvatarSuccess" // 成功响应后调用api,主要是这个
- :before-upload="beforeAvatarUpload" //上传之前调用api
- >
- <i class="el-icon-plus">i>
<img :src="infoForm.avatar" alt="编辑头像" class="update-img">
我们后端指定上传图片路径如上,当我们点击上传图片时,请求后端接口,图片会缓存到上述位置 ,并且会被如下函数接收到。
-
- // 获得上传图片的url
- handleAvatarSuccess(res, file) {
- console.log(file, res);
- this.infoForm.avatar = 'images/' + res.data
-
- // 拿到二进制数据,是blob类型,存储到浏览器内存中,一刷新数据会消失
- // console.log("imgUrl:", URL.createObjectURL(file.raw));
- },
具体接受结果。
以上,我们可以2种方式,拿到图片url:
具体就是: 我们后端缓存路径就是,vue项目中的public/images文件夹。
为什么这样使用呢?
浅谈一下:
1.经过webpack打包的vue项目结构会发生改变,我们原有的图片路径会失效。
2.public文件下,相当于是静态资源,不会经过webpack打包。
3.vue对于静态路径和动态路径(变量)的解析不一样。
具体看如下: