Spring Boot+Vue 文件上传,如何携带令牌信息?

栏目: IT技术 · 发布时间: 5年前

今日干货

Spring Boot+Vue 文件上传,如何携带令牌信息?

刚刚发表

查看: 66666 回复:666

公众号后台回复 ssm,免费获取松哥纯手敲的 SSM 框架学习干货。

关于文件上传这块,松哥之前也写了好几篇文章了,甚至还有视频:

但是,之前和小伙伴们提到的方案,是基于 session 来做认证的,所以并不需要考虑携带令牌的问题,但是在前后端分离开发中,我们可能采用 JWT 或者是 OAuth2+JWT 的方式来做认证,如果是这样的话,那我们就要手动传递令牌了。

今天就来和大家说说手动传递令牌的事。

1.传统方案

我们先来看看,基于 session 认证,文件上传要怎么做。

在 Vue.js 中,如果网络请求使用 axios ,并且使用了 ElementUI 库,那么一般来说,文件上传有两种不同的实现方案:

  1. 通过 Ajax 实现文件上传

  2. 通过 ElementUI 里边的 Upload 组件实现文件上传

两种方案,各有优缺点,我们分别来看。

1.1 准备工作

首先我们需要一点点准备工作,就是在后端提供一个文件上传接口,这是一个普通的 Spring Boot 项目,如下:

SimpleDateFormat sdf = new SimpleDateFormat("/yyyy/MM/dd/");
@PostMapping("/import")
public RespBean importData(MultipartFile file, HttpServletRequest req) throws IOException {
    String format = sdf.format(new Date());
    String realPath = req.getServletContext().getRealPath("/upload") + format;
    File folder = new File(realPath);
    if (!folder.exists()) {
        folder.mkdirs();
    }
    String oldName = file.getOriginalFilename();
    String newName = UUID.randomUUID().toString() + oldName.substring(oldName.lastIndexOf("."));
    file.transferTo(new File(folder,newName));
    String url = req.getScheme() + "://" + req.getServerName() + ":" + req.getServerPort() + "/upload" + format + newName;
    System.out.println(url);
    return RespBean.ok("上传成功!");
}

这里的文件上传比较简单,上传的文件按照日期进行归类,使用 UUID 给文件重命名。

「这里为了简化代码,我省略掉了异常捕获,上传结果直接返回成功,后端代码大伙可根据自己的实际情况自行修改。」

这是为了方便,我直接将文件存储到本地,小伙伴们也可以结合 FastDFS 将文件上传做的更加专业一些,可以参考松哥这篇文章: Spring Boot+Vue+FastDFS 实现前后端分离文件上传

1.2 Ajax 上传

在 Vue 中,通过 Ajax 实现文件上传,方案和传统 Ajax 实现文件上传基本上是一致的,唯一不同的是查找元素的方式。

<input type="file" ref="myfile">
<el-button @click="importData" type="success" size="mini" icon="el-icon-upload2">导入数据</el-button>

在这里,首先提供一个文件导入 input 组件,再来一个导入按钮,在导入按钮的事件中来完成导入的逻辑。

importData() {
  let myfile = this.$refs.myfile;
  let files = myfile.files;
  let file = files[0];
  var formData = new FormData();
  formData.append("file", file);
  this.uploadFileRequest("/system/basic/jl/import",formData).then(resp=>{
    if (resp) {
      console.log(resp);
    }
  })
}

关于这段上传核心逻辑,解释如下:

  1. 首先利用 Vue 中的 $refs 查找到存放文件的元素。

  2. type 为 file 的 input 元素内部有一个 files 数组,里边存放了所有选择的 file,由于文件上传时,文件可以多选,因此这里拿到的 files 对象是一个数组。

  3. 从 files 对象中,获取自己要上传的文件,由于这里是单选,所以其实就是数组中的第一项。

  4. 构造一个 FormData ,用来存放上传的数据,FormData 不可以像 Java 中的 StringBuffer 使用链式配置。

  5. 构造好 FromData 后,就可以直接上传数据了,FormData 就是要上传的数据。

  6. 文件上传注意两点,1. 请求方法为 post,2. 设置 Content-Type 为   multipart/form-data

这种文件上传方式,实际上就是传统的 Ajax 上传文件,和大家常见的 jQuery 中写法不同的是,这里元素查找的方式不一样(实际上元素查找也可以按照JavaScript 中原本的写法来实现),其他写法一模一样。这种方式是一个通用的方式,和使用哪一种前端框架无关。最后再和大家来看下封装的上传方法:

export const uploadFileRequest = (url, params) => {
  return axios({
    method: 'post',
    url: `${base}${url}`,
    data: params,
    headers: {
      'Content-Type': 'multipart/form-data'
    }
  });
}

经过这几步的配置后,前端就算上传完成了,可以进行文件上传了。

1.3 使用 el-upload 组件

如果使用 el-upload ,则需要引入 ElementUI,所以一般建议,如果使用了 ElementUI 做 UI 控件的话,则可以考虑使用 el-upload 组件来实现文件上传,如果没有使用 ElementUI 的话,则不建议使用 el-upload 组件,至于其他的 UI 控件,各自都有自己的文件上传组件,具体使用可以参考各自文档。

<el-upload
 
  :show-file-list="false"
  :on-success="onSuccess"
  :on-error="onError"
  :before-upload="beforeUpload"
  action="/system/basic/jl/import">
  <el-button size="mini" type="success" :disabled="!enabledUploadBtn" :icon="uploadBtnIcon">{{btnText}}</el-button>
</el-upload>
  1. show-file-list 表示是否展示上传文件列表,默认为true,这里设置为不展示。

  2. before-upload 表示上传之前的回调,可以在该方法中,做一些准备工作,例如展示一个进度条给用户 。

  3. on-success 和 on-error 分别表示上传成功和失败时候的回调,可以在这两个方法中,给用户一个相应的提示,如果有进度条,还需要在这两个方法中关闭进度条。

  4. action 指文件上传地址。

  5. 上传按钮的点击状态和图标都设置为变量 ,在文件上传过程中,修改上传按钮的点击状态为不可点击,同时修改图标为一个正在加载的图标 loading。

  6. 上传的文本也设为变量,默认上传 button 的文本是 数据导入 ,当开始上传后,将找个 button 上的文本修改为 正在导入

相应的回调如下:

onSuccess(response, file, fileList) {
  this.enabledUploadBtn = true;
  this.uploadBtnIcon = 'el-icon-upload2';
  this.btnText = '数据导入';
},
onError(err, file, fileList) {
  this.enabledUploadBtn = true;
  this.uploadBtnIcon = 'el-icon-upload2';
  this.btnText = '数据导入';
},
beforeUpload(file) {
  this.enabledUploadBtn = false;
  this.uploadBtnIcon = 'el-icon-loading';
  this.btnText = '正在导入';
}
  1. 在文件开始上传时,修改上传按钮为不可点击,同时修改上传按钮的图标和文本。

  2. 文件上传成功或者失败时,修改上传按钮的状态为可以点击,同时恢复上传按钮的图标和文本。

上传效果图如下:

Spring Boot+Vue 文件上传,如何携带令牌信息?

使用 el-upload 做文件上传,松哥之前也录过一个视频,小伙伴们可以参考(本视频节选自松哥自制的 Spring Boot+Vue+微人事系列视频教程 ):

1.4 两种方式比较

两种上传方式各有优缺点:

  1. 第一种方式最大的优势是通用,一招鲜吃遍天,到哪里都能用,但是对于上传过程的监控,进度条的展示等等逻辑都需要自己来实现。

  2. 第二种方式不够通用,因为它是 ElementUI 中的组件,得引入 ElementUI 才能使用,不过这种方式很明显有需多比较方便的回调,可以实现非常方便的处理常见的各种上传问题。

  3. 常规的上传需求第二种方式可以满足,但是如果要对上传的方法进行定制,则还是建议使用第一种上传方案。

2.手动传递令牌

对于上面不同的文件上传方式,手动上传令牌也有不同的方案,松哥来和大家挨个介绍。我这里服务端认证是 OAuth2+JWT 的方式,所以接下来令牌传递主要是按照 OAuth2 的格式来传递令牌,其实都是修改请求头,只要这种方式会了,其他方式也就会了。

「关于 OAuth2,如果小伙伴们还不熟悉,可以看看松哥之前写的系列教程:OAuth2系列」

2.1 Ajax 传递令牌

Ajax 传递令牌实际上是非常容易的,我们只需要稍微修改请求头即可。我给大家举一个简单例子。

如果你用的 axios 来做网络请求,那么按照如下方式添加请求头即可(或者在请求拦截器中统一添加):

export const uploadFileRequest = (url, params) => {
  return axios({
    method: 'post',
    url: `${base}${url}`,
    data: params,
    headers: {
      'Content-Type': 'multipart/form-data',
      'Authorization': 'Bearer ' + token
    }
  });
}

如果你用了 jQuery 的话,那么按照如下方式添加请求头即可:

$("#btnClick").click(function () {
        var formData = new FormData();
        formData.append("file", $("#userface")[0].files[0]);
        $.ajax({
            url: '/fileupload',
            type: 'post',
            headers: {
                'Authorization': 'Bearer ' + token
            },
            data: formData,
            processData: false,
            contentType: false,
            success: function (msg) {
                alert(msg);
            }
        });
    });

无非就是修改请求头,只要是自己发送请求的,请求头都是可以自由定制的,无论你用 jQuery 还是 axios 还是原生的 XMLHttpRequest。

2.2 el-upload 处理令牌

如果使用了 el-upload,我们就得在人家框架里边玩了,得符合框架要求,这虽然多了一些掣肘,但是也不是不能实现,松哥这里和大家介绍两种方案。

2.2.1 方案一

方案一是我目前采用的方案,因为 el-upload 支持定制请求头,这就好办了:

<el-upload
  ref="upload"
 
  :data="category"
  :multiple="false"
  :limit="1"
  :headers="myHeaders"
  :auto-upload="false"
  :on-success="onSuccess"
  :on-error="onError"
  :file-list="fileList"
  action="/appmanager/app/categories/"
>
  <el-button size="mini" type="primary">选择图标</el-button>
</el-upload>

其中,:headers="myHeaders" 就是我定制的请求头,然后在 data 中定义该变量即可:

data() {
  return {
    myHeaders: { Authorization: 'Bearer ' + getToken() }
  }
},

2.2.2 方案二

方案二则是利用 el-upload 的 before-upload 钩子函数,开发者可以在这个钩子函数中自己手动上传,上传完成之后,返回一个 false,这时 el-upload 就会停止它自己的上传逻辑。这种方式我看到有别的小伙伴在用,所以给大家一个简单的案例参考下:

<el-upload action="http://www.javaboy.org" :before-upload="beforeUpload"></el-upload>
beforeUpload (file) {
    //参考上面的 ajax 或者 axios 上传文件
    return false
}

这里有几个细节大家需要注意下:

  1. el-upload 的 action 属性随意给一个值,使之不报错,因为真正的上传地址我们将在 beforeUpload 方法中给出。

  2. beforeUpload 方法的上传逻辑跟我们第一小节介绍的一致,我就不重复写了,注意上传的文件对象是 file.raw
  3. beforeUpload 方法最终返回 false,终止 el-upload 自己的上传逻辑。

好了,和小伙伴们介绍了几种文件上传时候的令牌传递方式,不知道大家有没有 GET 到呢?有问题欢迎留言讨论,如果学到了,记得点个在看鼓励下松哥哦~

今日干货

Spring Boot+Vue 文件上传,如何携带令牌信息?

刚刚发表

查看: 13500 回复: 135

公众号后台回复 2TB,免费获取 2TB Java 学习资料。


以上所述就是小编给大家介绍的《Spring Boot+Vue 文件上传,如何携带令牌信息?》,希望对大家有所帮助,如果大家有任何疑问请给我留言,小编会及时回复大家的。在此也非常感谢大家对 码农网 的支持!

查看所有标签

猜你喜欢:

本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们

Web Data Mining

Web Data Mining

Bing Liu / Springer / 2006-12-28 / USD 59.95

Web mining aims to discover useful information and knowledge from the Web hyperlink structure, page contents, and usage data. Although Web mining uses many conventional data mining techniques, it is n......一起来看看 《Web Data Mining》 这本书的介绍吧!

MD5 加密
MD5 加密

MD5 加密工具

RGB HSV 转换
RGB HSV 转换

RGB HSV 互转工具