当前位置:   article > 正文

基于SpringBoot + Vue实现单个文件上传(带上Token和其它表单信息)的前后端完整过程_springboot vue 导入excel时如果传递 authorization

springboot vue 导入excel时如果传递 authorization

前言

有时遇到这种需求,在上传文件的同时还需要带上token凭据和其它表单信息,那么这个需求前端可以使用FormData数据类型来实现。FormData和JSON一样也是通过body传递的,前者支持字符串和二进制文件,后者只能是字符串,如下图1,图2所示。

图一

  图二

一、后端代码

(1)控制层(GameController.java)

  1. @PostMapping(value = "uploadSingleFile")
  2. @ResponseBody
  3. public CommonResponse uploadSingleFile(@RequestHeader("Authorization") String token,
  4. @RequestParam("file") MultipartFile file,
  5. @RequestParam("username") String username) {
  6. return gameService.uploadSingleFile(token, file, username);
  7. }

(2)接口层(IGameService.java)

CommonResponse uploadSingleFile(String token, MultipartFile file, String username);

(3)实现层(GameServiceImpl.java)

  1. @Value("${system.upload-file-path}")
  2. private String UploadFilePath;
  3. @Override
  4. public CommonResponse uploadSingleFile(String token, MultipartFile file, String username) {
  5. System.out.println(token);
  6. System.out.println(username);
  7. try {
  8. String uuidStr = UUID.randomUUID().toString();
  9. String uuid = uuidStr.substring(0, 8) + uuidStr.substring(9, 13) + uuidStr.substring(14, 18) + uuidStr.substring(19, 23) + uuidStr.substring(24);
  10. String originFileName = file.getOriginalFilename(); // 原文件名,如:HelloWorld.xlsx
  11. int beginIndex = originFileName.lastIndexOf("."); // 从后匹配"."
  12. String newFileName = uuid + originFileName.substring(beginIndex); // 新文件名,如:uuid.xlsx
  13. String destFileName = UploadFilePath + File.separator + newFileName; // 完整文件名 = 存储路径 + 原文件名
  14. // 复制文件到指定目录
  15. File destFile = new File(destFileName);
  16. destFile.getParentFile().mkdirs();
  17. file.transferTo(destFile);
  18. // 返回文件名
  19. return CommonResponse.ok(newFileName);
  20. } catch (FileNotFoundException e) {
  21. e.printStackTrace();
  22. return CommonResponse.fail(e.getMessage());
  23. } catch (IOException e) {
  24. e.printStackTrace();
  25. return CommonResponse.fail(e.getMessage());
  26. }
  27. }

二、前端代码

(1)视图页面(/src/view/Example/UploadFormData/index.vue)

  1. <template>
  2. <div>
  3. <el-dialog
  4. width="400"
  5. title="导入 Excel"
  6. class="import-excel-dialog"
  7. align-center
  8. destroy-on-close
  9. draggable
  10. center
  11. v-model="importExcelDialog.isVisible"
  12. :before-close="handleCloseImportExcelDialogClick"
  13. >
  14. <div>
  15. <p style="margin: 0 auto 7px 0; font-size: 13px">请上传Excel文件</p>
  16. <el-upload
  17. ref="importExcelUploadRef"
  18. drag
  19. action=""
  20. :limit="1"
  21. :on-exceed="handleUploadFileExceed"
  22. :on-change="handleUploadFileChange"
  23. :auto-upload="false"
  24. >
  25. <el-icon class="el-icon--upload"><upload-filled /></el-icon>
  26. <div class="el-upload__text" style="font-size: 13px">
  27. 拖动文件到此处进行上传 或 <em>点击上传</em>
  28. </div>
  29. <template #tip>
  30. <div class="el-upload__tip">支持格式 : xls/xlsx/xlsm</div>
  31. </template>
  32. </el-upload>
  33. <el-input
  34. size="small"
  35. v-model="importExcelDialog.username"
  36. style="width: 100%; background-color: #eee"
  37. placeholder="请输入用户"
  38. >
  39. </el-input>
  40. </div>
  41. <template #footer>
  42. <div>
  43. <el-button size="small" type="primary" @click="handleUploadFileComfirm($event)">
  44. <el-icon :size="18" style="margin-right: 5px"><Check /></el-icon>
  45. <small>确定</small>
  46. </el-button>
  47. </div>
  48. </template>
  49. </el-dialog>
  50. </div>
  51. </template>
  52. <script>
  53. export default {
  54. data: () => {
  55. return {
  56. // 导入Excel弹窗
  57. importExcelDialog: {
  58. isVisible: false,
  59. username: '帅龍之龍',
  60. uploadFileList: [], // 校验通过的上传文件列表
  61. },
  62. }
  63. },
  64. created() {
  65. // ...
  66. },
  67. mounted() {
  68. this.handleOpenImportExcelDialogClick()
  69. },
  70. methods: {
  71. /**
  72. * 打开导入Excel弹窗事件句柄
  73. */
  74. handleOpenImportExcelDialogClick() {
  75. this.importExcelDialog.isVisible = true
  76. },
  77. /**
  78. * 文件上传 - 文件超过句柄方法
  79. */
  80. async handleUploadFileExceed(files, uploadFiles) {
  81. console.log(
  82. '%c 文件超过句柄方法 %c handleUploadFileExceed',
  83. 'padding: 1px; background-color: #35495e; color: #fff',
  84. 'padding: 1px; background-color: #5e7ce0; color: #fff',
  85. )
  86. console.log('%c ∟ %c files %c =>', 'text-indent: 10px', 'padding: 1px; background-color: #41b883; color: #fff', 'color: #000', files)
  87. console.log('%c ∟ %c uploadFiles %c =>', 'text-indent: 10px', 'padding: 1px; background-color: #41b883; color: #fff', 'color: #000', uploadFiles)
  88. const refs = await this.$refs
  89. const importExcelUploadRef = refs.importExcelUploadRef
  90. const uploadFile = files[0]
  91. const fileName = uploadFile.name // xxxxxx.xlsx
  92. const index = fileName.lastIndexOf('.')
  93. const type = fileName.substring(index) // .xlsx
  94. if (!(type == '.xls' || type == '.xlsx' || type == '.xlsm')) {
  95. this.$message({ message: '文件格式错误,应为 xls/xlsx/xlsm 类型文件', type: 'warning', duration: 3000 })
  96. // 清空
  97. importExcelUploadRef.clearFiles()
  98. } else {
  99. // 清空
  100. importExcelUploadRef.clearFiles()
  101. // 回显
  102. const file = files[0]
  103. importExcelUploadRef.handleStart(file)
  104. // 文件上传列表重新赋值
  105. this.importExcelDialog.uploadFileList = []
  106. this.importExcelDialog.uploadFileList.push(uploadFile)
  107. }
  108. },
  109. /**
  110. * 文件上传 - 文件改变句柄方法
  111. */
  112. async handleUploadFileChange(uploadFile, uploadFiles) {
  113. console.log(
  114. '%c 文件改变句柄方法 %c handleUploadFileChange',
  115. 'padding: 1px; background-color: #35495e; color: #fff',
  116. 'padding: 1px; background-color: #5e7ce0; color: #fff',
  117. )
  118. console.log('%c ∟ %c uploadFile %c =>', 'text-indent: 10px', 'padding: 1px; background-color: #41b883; color: #fff', 'color: #000', uploadFile)
  119. console.log('%c ∟ %c uploadFiles %c =>', 'text-indent: 10px', 'padding: 1px; background-color: #41b883; color: #fff', 'color: #000', uploadFiles)
  120. const refs = await this.$refs
  121. const importExcelUploadRef = refs.importExcelUploadRef
  122. const fileName = uploadFile.name // xxxxxx.xlsx
  123. const index = fileName.lastIndexOf('.')
  124. const type = fileName.substring(index) // .xlsx
  125. if (!(type == '.xls' || type == '.xlsx' || type == '.xlsm')) {
  126. this.$message({ message: '文件格式错误,应为 xls/xlsx/xlsm 类型文件', type: 'warning', duration: 3000 })
  127. // 清空
  128. importExcelUploadRef.clearFiles()
  129. } else {
  130. // 文件上传列表重新赋值
  131. this.importExcelDialog.uploadFileList = []
  132. this.importExcelDialog.uploadFileList.push(uploadFile)
  133. }
  134. console.log('%c ∟ %c uploadFileList %c =>', 'text-indent: 10px', 'padding: 1px; background-color: #41b883; color: #fff', 'color: #000', this.importExcelDialog.uploadFileList)
  135. },
  136. /**
  137. * 文件上传 - 确认上传句柄方法
  138. */
  139. async handleUploadFileComfirm(evt) {
  140. this.$elementUtil.handleElButtonBlur(evt)
  141. if (this.importExcelDialog.uploadFileList.length == 0) {
  142. this.$message({ message: '请上传文件', type: 'warning', duration: 3000 })
  143. return
  144. }
  145. let formData = new FormData()
  146. this.importExcelDialog.uploadFileList.map(uploadFile => {
  147. formData.append('file', uploadFile.raw)
  148. })
  149. formData.append('username', this.importExcelDialog.username.trim())
  150. this.$axios.post(
  151. `/api/uploadSingleFile`,
  152. formData,
  153. {
  154. headers: {
  155. 'Access-Control-Allow-Origin': '*',
  156. 'Content-Type': 'multipart/form-data',
  157. 'Authorization': 'Bearer token'
  158. },
  159. }
  160. )
  161. .then((res) => {
  162. console.log('get =>', res)
  163. if (res.status == 200 && res.data) {
  164. const result = res.data
  165. if (result.code == 200 && result.success) {
  166. this.$elementUtil.handleAutoCloseMessage(`上传成功,新文件名为:${result.data}`, 'success', 5, true)
  167. } else {
  168. this.$elementUtil.handleAutoCloseMessage(`上传失败,服务端出错,请联系管理员`, 'error', 5, true)
  169. }
  170. }
  171. setTimeout(() => { this.importExcelDialog.isVisible = false }, 1000)
  172. }).catch(err =>{
  173. this.$elementUtil.handleAutoCloseMessage(err, 'error', 5, true)
  174. console.error(err)
  175. })
  176. const refs = await this.$refs
  177. const importExcelUploadRef = refs.importExcelUploadRef
  178. // 清空
  179. importExcelUploadRef.clearFiles()
  180. // 文件上传列表重置
  181. this.importExcelDialog.uploadFileList = []
  182. },
  183. /**
  184. * 关闭导入Excel弹窗事件句柄
  185. */
  186. handleCloseImportExcelDialogClick() {
  187. this.importExcelDialog.isVisible = false
  188. },
  189. }
  190. }
  191. </script>
  192. <style lang="less" scoped>
  193. :deep(.import-excel-dialog) {
  194. .el-dialog__header {
  195. margin-right: 0;
  196. padding: 25px 20px;
  197. border-bottom: 1px solid #efefef;
  198. .el-dialog__title {
  199. font-size: 15px;
  200. word-wrap: break-word;
  201. word-break: normal
  202. }
  203. .el-dialog__headerbtn {
  204. top: 15px;
  205. font-size: 20px;
  206. }
  207. }
  208. .el-dialog__body {
  209. padding: calc(var(--el-dialog-padding-primary) + 10px) var(--el-dialog-padding-primary);
  210. .el-select {
  211. .el-input {
  212. .el-input__wrapper {
  213. background-color: transparent;
  214. }
  215. }
  216. }
  217. .el-input {
  218. .el-input__wrapper {
  219. background-color: #eee;
  220. }
  221. }
  222. }
  223. .el-dialog__footer {
  224. padding: var(--el-dialog-padding-primary);
  225. border-top: 1px solid #efefef;
  226. }
  227. }
  228. </style>

三、运行效果

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/我家小花儿/article/detail/283649
推荐阅读
相关标签
  

闽ICP备14008679号