vue+springboot上傳文件、圖片、視頻及回顯到前端詳解
效果圖
預(yù)覽:
設(shè)計邏輯
數(shù)據(jù)庫表
前端vue
html
<div class="right-pannel"> <div class="data-box"> <!--上傳的作業(yè)--> <div style="display: block" id=""> <div class="title clearfix"> <div class="all fl" data-folderid="0"> <a class="here">上傳附件(上傳項目演示視頻應(yīng)為mp4格式)</a> </div> </div> <div class="container_con"> <!--作業(yè)超時提示--> <el-dialog title="提示" :visible.sync="workLateTip" width="30%"> <span>作業(yè)已截止,禁止提交,請聯(lián)系任課老師</span> <span slot="footer" class="dialog-footer"> <el-button @click="workLateTip = false">取 消</el-button> <el-button type="primary" @click="workLateTip = false">確 定</el-button> </span> </el-dialog> <!--展示如下界面--> <div> <div class="operation" id="submit-display"> <div class="add-resource-btn fl" @click="choiceImg"> <span class="tips"><i class="iconfont"></i>上傳文件</span> <input type="file" name="file" class="webuploader-element-invisible" @change="getFile" ref="filElem" id="submitFile"> </div> <div class="multidelete fl" style="display: none;" id="piliang-delete" @click="deleteZiYuan"><i class="iconfont iconshanchu1"></i>批量刪除 </div> </div> <el-progress id="showProgress" style="display:none;" :stroke-width="16" :percentage="progressPercent"></el-progress> <el-table ref="multipleTable" :data="tableFileList" tooltip-effect="dark" style="width: 100%" @selection-change="handleSelectionChange"> <el-table-column type="selection" width="55"> </el-table-column> <el-table-column prop="submitHomeworkFileName" label="文件名" width="350"> </el-table-column> <el-table-column prop="submitHomeworkFileSize" label="大小" width="150"> </el-table-column> <el-table-column prop="submitHomeworkGrade" label="成績狀態(tài)" width="100"> </el-table-column> <el-table-column prop="submitHomeworkCreateTime" label="上傳時間" width="220"> </el-table-column> <el-table-column width="300"> <template slot-scope="scope"> <a @click="preview(scope.row.submitHomeworkFilePath)" class="homework-operation" style="margin-left: 50px">預(yù)覽</a> <a class="homework-operation" @click="saveFile(scope.row.submitHomeworkId)">下載</a> <a @click="deleteOne(scope.row.submitHomeworkId)" class="homework-operation">刪除</a> </template> </el-table-column> </el-table> </div> </div> </div> </div> </div>
js代碼
//上傳本地文件 choiceImg() { this.$refs.filElem.dispatchEvent(new MouseEvent('click')) }, getFile() { const inputFile = this.$refs.filElem.files[0]; //如果大于1G,提示用戶 if (inputFile.size > 1048576000) { this.$message({ message: '上傳文件應(yīng)小于1G', type: 'error', duration: 3000 }); return } //初始化為0,表示不是項目介紹視頻 this.submitWork.submitHomeworkIntroduceVideo = "0" // console.log(inputFile) //視頻類型:video/mp4 if (inputFile.type === "video/mp4") { this.$message({ message: '上傳視頻將作為視頻介紹', type: 'info', duration: 5000 }); //設(shè)置 1,表示標(biāo)記為項目介紹視頻 this.submitWork.submitHomeworkIntroduceVideo = "1" } let fileSize = inputFile.size / 1000; let finalSize = 0; if (fileSize > 1000) { finalSize = fileSize / 1000; this.fileSizeType = "MB" } else { finalSize = fileSize; this.fileSizeType = "KB" } this.tempFileSize = finalSize; this.fileName = inputFile.fileName this.upload() }, //上傳一個新的資源 upload() { this.submitWork.homeworkId = sessionStorage.getItem("homeworkId") this.submitWork.studentId = sessionStorage.getItem("studentId") this.submitWork.submitHomeworkFileSize = this.tempFileSize + "" + this.fileSizeType // console.log(this.submitWork) homeworkApi.submitHomework(this.submitWork) .then(res => { this.$message({ message: '作業(yè)信息提交成功', type: 'success' }); this.addZiYuanDis = false; //提交作業(yè)的id存儲在會話中 sessionStorage.setItem("finishWorkId", res.data.submitWork.submitHomeworkId) //當(dāng)已經(jīng)存進(jìn)數(shù)據(jù)庫之后再進(jìn)行修改 this.submit(); }).catch( () => { this.$message({ message: '作業(yè)信息提交失??!請重試!', type: 'error' }); } ) }, //文件提交到本地云端存儲 submit() { var formData = new FormData(); const submitHomeworkId = sessionStorage.getItem("finishWorkId") let file = this.$refs.filElem.files[0] formData.append('file', file) // 'file' 這個名字要和后臺獲取文件的名字一樣; //顯示進(jìn)度條 document.getElementById("showProgress").style.display = "block"; document.getElementById("submit-display").style.display = "none"; let configs = { headers: { 'Content-Type': 'multipart/form-data', token: sessionStorage.getItem("token") }, onUploadProgress: (progressEvent) => { if (progressEvent.lengthComputable) { //是否存在進(jìn)度 this.progressPercent = parseInt((progressEvent.loaded / progressEvent.total) * 100) } }, } this.$axios.post('submitHomework/submitHomeworkFile/' + submitHomeworkId, formData, configs) .then( res => { this.$message({ message: '作業(yè)上傳成功', type: 'success' }); document.getElementById("showProgress").style.display = "none"; document.getElementById("submit-display").style.display = "block"; this.getAllZiYuan(); }).catch(error => { this.$message({ message: '作業(yè)上傳失敗!請重試!', type: 'error' }); document.getElementById("showProgress").style.display = "none"; document.getElementById("submit-display").style.display = "block"; }) },
前端思路
分成兩部,1.通過前端將文件的基本信息傳送到后端進(jìn)行儲存,返回已儲存的文件id,2.再將文件發(fā)送到后端儲存。
儲存文件信息
上傳文件對象
后端上傳下載代碼
@RequestMapping("/submitHomeworkFile/{submitHomeworkId}") public R submitHomeworkFile(@RequestParam("file") MultipartFile multipartFile, @PathVariable long submitHomeworkId, HttpServletRequest req) throws IOException { System.out.println("id___________________"+submitHomeworkId); SimpleDateFormat sdf = new SimpleDateFormat("/yyyy/MM/dd/"); String format = sdf.format(new Date());//時間 // 獲得項目在磁盤的地址,如:D:/eclipse-workspace/studyProject/youketangV0.0/youketang_ssm/target/classes//store/2023/02/19/ // String realPath = ResourceUtils.getURL("classpath:").getPath() + "/store" + format; // /www/wwwroot/resource String realPath = "D:" + "/store" + format; // String realPath = "/www/wwwroot/resource" + "/store" + format; // String realPath = req.getServletContext().getRealPath("/")+"/store"+format; // getRealPath("/")方法返回的是項目在服務(wù)器的絕對路徑(C:\Users\29395\AppData\Local\Temp\tomcat-docbase.4782946598994668439.8888\/store/2023/02/19/) //由于是在temp臨時文件,每次重啟服務(wù)器,都找不到之前的文件url. File fileDir = new File(realPath); if (!fileDir.exists()) { fileDir.mkdirs(); } if (multipartFile != null) { String fileName = multipartFile.getOriginalFilename();//獲取名字 // 172.17.160.1為服務(wù)器的IP地址 // String url = req.getScheme() + "://" + "47.94.255.44" + ":" + req.getServerPort() + "/store" + format + fileName; String url = req.getScheme() + "://" + "localhost" + ":" + req.getServerPort() + "/store" + format + fileName; // transferTo(File dest) 將接收到的文件傳輸?shù)浇o定的目標(biāo)文件。 multipartFile.transferTo(new File(realPath, fileName)); String fileReal = fileDir + "http://" + fileName; // System.out.println(fileReal); SubmitHomework submitHomework = submitHomeworkService.findSubmitHomeworkById(submitHomeworkId); submitHomework.setSubmitHomeworkFileRealPath(fileReal); submitHomework.setSubmitHomeworkFilePath(url); submitHomework.setSubmitHomeworkFileName(multipartFile.getOriginalFilename()); submitHomeworkService.modifySubmitHomework(submitHomework); return R.ok().data("path", url); } else { return R.ok().message("請選中文件"); } } @GetMapping("/downloadSubmitHomeworkFile/{submitHomeworkId}") public void downloadSubmitHomeworkFile(@PathVariable("submitHomeworkId") long submitHomeworkId, HttpServletResponse response) { SubmitHomework submitHomework = submitHomeworkService.findSubmitHomeworkById(submitHomeworkId); String fileRealPath = submitHomework.getSubmitHomeworkFileRealPath(); String fileName = submitHomework.getSubmitHomeworkFileName(); File file = new File(fileRealPath); byte[] buffer = new byte[1024]; BufferedInputStream bis = null; OutputStream os = null; try { //文件是否存在 if (file.exists()) { response.setHeader("Access-Control-Allow-Origin", "*"); // 允許所有 //設(shè)置響應(yīng) response.setContentType("application/octet-stream;charset=UTF-8"); // 將響應(yīng)頭中的Content-Disposition暴露出來,不然前端獲取不到 response.setHeader("Access-Control-Expose-Headers", "Content-Disposition"); // 在響應(yīng)頭中的Content-Disposition里設(shè)置文件名稱 response.setHeader("Content-Disposition", "attachment;filename=" + URLEncoder.encode(fileName, "UTF-8")); // response.setHeader("Content-Disposition", "attachment;filename=" + fileName); os = response.getOutputStream(); bis = new BufferedInputStream(new FileInputStream(file)); while (bis.read(buffer) != -1) { os.write(buffer); } } } catch (Exception e) { e.printStackTrace(); } finally { try { if (bis != null) { bis.close(); } if (os != null) { os.flush(); os.close(); } } catch (IOException e) { e.printStackTrace(); } } }
這個我放在d盤下面,需要修改映射路徑
@Override public void addResourceHandlers(ResourceHandlerRegistry registry) { // 訪問相對路徑 // PS:注意文件路徑最后的斜杠(文件分隔符),如果缺少了,就不能夠正確的映射到相應(yīng)的目錄 String baseDocumentPath = "file:D:/document/"; String baseStorePath = "file:D:/store/"; // String baseDocumentPath = "file:/www/wwwroot/resource/document/"; // String baseStorePath = "file:/www/wwwroot/resource/store/"; // /www/wwwroot/resource registry.addResourceHandler("/document/**").addResourceLocations(baseDocumentPath); registry.addResourceHandler("/store/**").addResourceLocations(baseStorePath); WebMvcConfigurer.super.addResourceHandlers(registry); }
完整代碼
workinfo.vue
<template> <div> <!--頭部--> <div class="header"> <div class="header-left"> <span class="header-icon" @click="jumpToHomework"><i class="iconfont iconfanhui" style="font-size:38px;color:#5F6368;"></i></span> <span class="courseName" @click="jumpToHomework">{{ courseName }}</span> </div> <div class="header-center"> <span style="border-bottom: 4px solid #2C58AB;">提交作業(yè)</span> </div> <div class="header-right"> <ul class="nav-menu-right"> </ul> </div> </div> <div class="data-page cWidth-new" style="width: 81%; padding: 0;"> <div class="resources-area"> <div class="right-pannel"> <div class="introduce" style=" height: 55px; line-height: 55px; border-radius: 8px 8px 0 0; background: #F1F3F4;padding-left: 15px; "> 有關(guān)作業(yè)的基本信息 </div> <!--在這里加入一個表單--> <el-form :model="homeworkForm" ref="homeworkForm" class="demo-dynamic" :rules="rules" label-width="80px" style="margin-top: 30px;"> <el-form-item prop="title" label="作業(yè)題目" style="color: #34373D;"> <el-input v-model="homeworkForm.homeworkTitle" disabled></el-input> </el-form-item> <el-form-item prop="fullScore" label="分?jǐn)?shù)"> <el-input v-model="homeworkForm.homeworkFullScore" disabled></el-input> </el-form-item> <el-form-item prop="deadline" label="截止日期"> <el-input style="color: black" v-model="homeworkForm.homeworkDeadline" disabled></el-input> </el-form-item> <el-form-item prop="description" label="作業(yè)描述"> <!--渲染--> <span> <p v-html="homeworkForm.homeworkDescription"></p></span> </el-form-item> </el-form> </div> <div class="right-pannel"> <div class="introduce" style=" height: 55px; line-height: 55px; border-radius: 8px 8px 0 0; background: #F1F3F4;padding-left: 15px; "> 項目相關(guān)介紹 </div> <!-- 在這里加入一個表單--> <el-form :model="dynamicValidateForm" ref="dynamicValidateForm" class="demo-dynamic" :rules="rules" label-width="80px" style="margin-top: 30px;"> <el-form-item prop="projectHomeworkName" label="項目名稱"> <el-input v-model="dynamicValidateForm.projectHomeworkName"></el-input> </el-form-item> <el-form-item prop="projectHomeworkIntroduceText" label="項目介紹"> <el-input v-model="dynamicValidateForm.projectHomeworkIntroduceText"></el-input> </el-form-item> <el-form-item prop="projectHomeworkTeamNumber" label="小組成員"> <el-input v-model="dynamicValidateForm.projectHomeworkTeamNumber"></el-input> </el-form-item> <el-form-item> <el-button type="primary" @click="submitForm('dynamicValidateForm')" v-preventReClick>提交 </el-button> <el-button @click="resetForm('dynamicValidateForm')">重置</el-button> </el-form-item> </el-form> </div> <div style="display: none" id="video"> <video id="my-video" class="video-js" controls preload="auto" width="1152" height="680" data-setup="{}" :src=vedioSrc> </video> </div> <div class="right-pannel"> <div class="data-box"> <!--上傳的作業(yè)--> <div style="display: block" id=""> <div class="title clearfix"> <div class="all fl" data-folderid="0"> <a class="here">上傳附件(上傳項目演示視頻應(yīng)為mp4格式)</a> </div> </div> <div class="container_con"> <!--作業(yè)超時提示--> <el-dialog title="提示" :visible.sync="workLateTip" width="30%"> <span>作業(yè)已截止,禁止提交,請聯(lián)系任課老師</span> <span slot="footer" class="dialog-footer"> <el-button @click="workLateTip = false">取 消</el-button> <el-button type="primary" @click="workLateTip = false">確 定</el-button> </span> </el-dialog> <!--展示如下界面--> <div> <div class="operation" id="submit-display"> <div class="add-resource-btn fl" @click="choiceImg"> <span class="tips"><i class="iconfont"></i>上傳文件</span> <input type="file" name="file" class="webuploader-element-invisible" @change="getFile" ref="filElem" id="submitFile"> </div> <div class="multidelete fl" style="display: none;" id="piliang-delete" @click="deleteZiYuan"><i class="iconfont iconshanchu1"></i>批量刪除 </div> </div> <el-progress id="showProgress" style="display:none;" :stroke-width="16" :percentage="progressPercent"></el-progress> <el-table ref="multipleTable" :data="tableFileList" tooltip-effect="dark" style="width: 100%" @selection-change="handleSelectionChange"> <el-table-column type="selection" width="55"> </el-table-column> <el-table-column prop="submitHomeworkFileName" label="文件名" width="350"> </el-table-column> <el-table-column prop="submitHomeworkFileSize" label="大小" width="150"> </el-table-column> <el-table-column prop="submitHomeworkGrade" label="成績狀態(tài)" width="100"> </el-table-column> <el-table-column prop="submitHomeworkCreateTime" label="上傳時間" width="220"> </el-table-column> <el-table-column width="300"> <template slot-scope="scope"> <a @click="preview(scope.row.submitHomeworkFilePath)" class="homework-operation" style="margin-left: 50px">預(yù)覽</a> <a class="homework-operation" @click="saveFile(scope.row.submitHomeworkId)">下載</a> <a @click="deleteOne(scope.row.submitHomeworkId)" class="homework-operation">刪除</a> </template> </el-table-column> </el-table> </div> </div> </div> </div> </div> </div> </div> </div> </template> <script> import homeworkApi from "@/api/homework"; var formData = new window.FormData() // vue 中使用此方法創(chuàng)建FromData對象 window.FormData(),否則會報 'FormData isn't definded' export default { data() { var validateName = (rule, value, callback) => { if (!value) { return callback(new Error("項目名稱不能為空")); } else { callback(); } }; var validateTeamNumber = (rule, value, callback) => { if (!value) { return callback(new Error("小組成員不能為空")); } else { callback(); } }; var validateIntroduce = (rule, value, callback) => { if (!value) { return callback(new Error("項目介紹不能為空")); } else { callback(); } }; return { vedioSrc: '',//項目視頻的src finishWorkId: '', //用于更新提交時傳遞到后臺覆蓋原紀(jì)錄 isLiuYanEmpty: true, //留言是否為空,默認(rèn)都是空 isUpload: false, //是否提交了該作業(yè) workLateTip: false, //作業(yè)提交超時提醒 fileSize: [], //上傳的文件大小 readWorkTipDisplay: false, //定義批閱作業(yè)的提醒彈框 tableData: [], //定義作業(yè)提交詳情總覽 introduceVideo: '', //標(biāo)記是否為視頻 input1: '', hide: '', gradeList: [], similarityList: [], submitList: [], shareList: [], selected: false, givePoints: '', managecheck: false, courseName: sessionStorage.getItem("courseName"), homeworkId: '', submitWorkId: '',//提交作業(yè)后端返回的id course: { id: '', courseName: '', className: '', year: '', semester: '' }, homework: {}, classmateCount: '', submitCount: '', submittedList: [], //定義提交詳情所有學(xué)生的信息展示 包括 已批 未批 未交 submitInfo: { score: '', id: '', name: '', number: '', bestScore: '', publishTime: '', fileAddress: '' }, submitWork: {}, read: '未閱', score: '', beginScore: [], state: '', tempFileSize: '', //暫時存的文件大小 fileSizeType: '', //文件大小類型 MB KB fileName: '', multipleSelection: [],//選中的文件 addZiYuanDis: false, tableFileList: [], deleteIdList: [], //每次刪除完以后記得賦空值 dynamicValidateForm: { projectHomeworkName: '', projectHomeworkIntroduceText: '', projectHomeworkTeamNumber: '' }, homeworkForm: { title: '', description: '', fullScore: '', deadline: '' }, rules: { projectHomeworkName: [{validator: validateName, trigger: 'blur'}], projectHomeworkTeamNumber: [{validator: validateTeamNumber, trigger: 'blur'}], projectHomeworkIntroduceText: [{validator: validateIntroduce, trigger: 'blur'}], }, dialogImageUrl: '', dialogVisible: false, progressPercent: 0 } }, //進(jìn)入頁面內(nèi)容全部渲染完成后自動引函數(shù) mounted() { this.getProjectHomeworkInfo(); this.getAllZiYuan(); }, methods: { getProjectHomeworkInfo() { let homeworkId = sessionStorage.getItem("homeworkId"); let studentId = sessionStorage.getItem("studentId"); //獲取作業(yè)的基本信息 homeworkApi.getHomeworkById(homeworkId).then( res => { // console.log(res.data) this.homeworkForm = res.data.homework } ) homeworkApi.getProjectHomeworkInfo(homeworkId, studentId).then(res => { this.dynamicValidateForm.projectHomeworkIntroduceText = res.data.projectHomework.projectHomeworkIntroduceText this.dynamicValidateForm.projectHomeworkTeamNumber = res.data.projectHomework.projectHomeworkTeamNumber this.dynamicValidateForm.projectHomeworkName = res.data.projectHomework.projectHomeworkName }) }, //獲取所有資源 getAllZiYuan() { let homeworkId = sessionStorage.getItem("homeworkId"); let studentId = sessionStorage.getItem("studentId"); homeworkApi.getSubmitHomework(homeworkId, studentId).then(res => { //賦值給文件表格 this.tableFileList = res.data.submitHomeworkList //對項目視頻介紹標(biāo)記,判斷introduceVideo是否為1,如果為1,則為視頻介紹,賦值videoSrc,并顯示視頻標(biāo)簽. for (var i = 0; i < this.tableFileList.length; i++) { if (this.tableFileList[i].introduceVideo === 1) { this.vedioSrc = this.tableFileList[i].filePath; document.getElementById("video").style.display = "block"; } } }) }, //學(xué)生端預(yù)覽文件 preview(url) { //console.log(indexurl); //要預(yù)覽文件的訪問地址 window.open(url); }, //單個刪除 deleteOne(id) { console.log(id) this.deleteIdList.push(id) this.$confirm('此操作將刪除該資料, 是否繼續(xù)?', '提示', { confirmButtonText: '確定', cancelButtonText: '取消', type: 'warning' }).then(() => { //異步請求刪除 homeworkApi.removeSubmitHomework(this.deleteIdList) .then(res => { this.deleteIdList = [] //進(jìn)行置空 this.$message({ message: '刪除成功', type: 'success' }); this.getAllZiYuan() }) }).catch(() => { this.$message({ type: 'info', message: '已取消刪除' }); }); }, //刪除資源(點擊批量刪除) deleteZiYuan() { let list = this.multipleSelection; for (let i = 0; i < list.length; i++) { this.deleteIdList.push(list[i].id); } this.$confirm('此操作將刪除該資料, 是否繼續(xù)?', '提示', { confirmButtonText: '確定', cancelButtonText: '取消', type: 'warning' }).then(() => { //異步請求刪除 homeworkApi.removeSubmitHomework(this.deleteIdList) .then(res => { this.deleteIdList = [] //進(jìn)行置空 this.$message({ message: '刪除成功', type: 'success' }); //重新加載界面 this.$router.go(0) }) }).catch(() => { this.$message({ type: 'info', message: '已取消刪除' }); }); }, handleEdit(index, row) { console.log(index, row); }, handleSelectionChange(val) { //console.log("選中值發(fā)生了改變") this.multipleSelection = val; if (this.multipleSelection.length !== 0) { document.getElementById("piliang-delete").style.display = "block"; } else { document.getElementById("piliang-delete").style.display = "none"; } }, //上傳本地文件 choiceImg() { this.$refs.filElem.dispatchEvent(new MouseEvent('click')) }, getFile() { const inputFile = this.$refs.filElem.files[0]; //如果大于1G,提示用戶 if (inputFile.size > 1048576000) { this.$message({ message: '上傳文件應(yīng)小于1G', type: 'error', duration: 3000 }); return } //初始化為0,表示不是項目介紹視頻 this.submitWork.submitHomeworkIntroduceVideo = "0" // console.log(inputFile) //視頻類型:video/mp4 if (inputFile.type === "video/mp4") { this.$message({ message: '上傳視頻將作為視頻介紹', type: 'info', duration: 5000 }); //設(shè)置 1,表示標(biāo)記為項目介紹視頻 this.submitWork.submitHomeworkIntroduceVideo = "1" } let fileSize = inputFile.size / 1000; let finalSize = 0; if (fileSize > 1000) { finalSize = fileSize / 1000; this.fileSizeType = "MB" } else { finalSize = fileSize; this.fileSizeType = "KB" } this.tempFileSize = finalSize; this.fileName = inputFile.fileName this.upload() }, //上傳一個新的資源 upload() { this.submitWork.homeworkId = sessionStorage.getItem("homeworkId") this.submitWork.studentId = sessionStorage.getItem("studentId") this.submitWork.submitHomeworkFileSize = this.tempFileSize + "" + this.fileSizeType // console.log(this.submitWork) homeworkApi.submitHomework(this.submitWork) .then(res => { this.$message({ message: '作業(yè)信息提交成功', type: 'success' }); this.addZiYuanDis = false; //提交作業(yè)的id存儲在會話中 sessionStorage.setItem("finishWorkId", res.data.submitWork.submitHomeworkId) //當(dāng)已經(jīng)存進(jìn)數(shù)據(jù)庫之后再進(jìn)行修改 this.submit(); }).catch( () => { this.$message({ message: '作業(yè)信息提交失??!請重試!', type: 'error' }); } ) }, //文件提交到本地云端存儲 submit() { var formData = new FormData(); const submitHomeworkId = sessionStorage.getItem("finishWorkId") let file = this.$refs.filElem.files[0] formData.append('file', file) // 'file' 這個名字要和后臺獲取文件的名字一樣; //顯示進(jìn)度條 document.getElementById("showProgress").style.display = "block"; document.getElementById("submit-display").style.display = "none"; let configs = { headers: { 'Content-Type': 'multipart/form-data', token: sessionStorage.getItem("token") }, onUploadProgress: (progressEvent) => { if (progressEvent.lengthComputable) { //是否存在進(jìn)度 this.progressPercent = parseInt((progressEvent.loaded / progressEvent.total) * 100) } }, } this.$axios.post('submitHomework/submitHomeworkFile/' + submitHomeworkId, formData, configs) .then( res => { this.$message({ message: '作業(yè)上傳成功', type: 'success' }); document.getElementById("showProgress").style.display = "none"; document.getElementById("submit-display").style.display = "block"; this.getAllZiYuan(); }).catch(error => { this.$message({ message: '作業(yè)上傳失?。≌堉卦?!', type: 'error' }); document.getElementById("showProgress").style.display = "none"; document.getElementById("submit-display").style.display = "block"; }) }, //跳轉(zhuǎn)到作業(yè) jumpToHomework() { sessionStorage.setItem("homeworkId", ''); this.$router.push({name: 'SHomework'}); }, saveFile(submitHomeworkId) { this.$axios.get('submitHomework/downloadSubmitHomeworkFile/' + submitHomeworkId, { responseType: 'blob' , headers: { 'token': sessionStorage.getItem("token") } }) .then((res) => { // console.log('文件下載成功'); const blob = new Blob([res.data]); // 獲取文件名稱, res.headers['content-disposition']: attachment;filename=???????.docx const fileNameUtf8 = res.headers['content-disposition'].split(";")[1].split("filename=")[1]; //%E8%BD%AF%E4%BB%B6%E9%A1%B9%E7%9B%AE%E8%AE%A1%E5%88%92%E8%A1%A8.docx 解碼后:軟件項目計劃表.docx var fileName = decodeURIComponent(fileNameUtf8) console.log("res:" + res.headers['content-disposition']) console.log("fileName:" + fileName) //對于<a>標(biāo)簽,只有 Firefox 和 Chrome(內(nèi)核) 支持 download 屬性 //IE10以上支持blob,但是依然不支持download //支持a標(biāo)簽download的瀏覽器 const link = document.createElement('a');//創(chuàng)建a標(biāo)簽 link.download = fileName;//a標(biāo)簽添加屬性 link.style.display = 'none'; link.href = URL.createObjectURL(blob); document.body.appendChild(link); link.click();//執(zhí)行下載 URL.revokeObjectURL(link.href); //釋放url document.body.removeChild(link);//釋放標(biāo)簽 this.$message.success("作業(yè)下載成功!") }).catch((res) => { this.$message.error("作業(yè)下載失敗!請重試!") }); }, //提交表單 submitForm(formName) { //進(jìn)行校驗 this.$refs[formName].validate((valid) => { if (valid) { let homeworkId = sessionStorage.getItem("homeworkId") let studentId = sessionStorage.getItem("studentId") let projectData = { homeworkId: homeworkId, studentId: studentId, projectHomeworkTeamNumber: this.dynamicValidateForm.projectHomeworkTeamNumber, projectHomeworkIntroduceText: this.dynamicValidateForm.projectHomeworkIntroduceText, projectHomeworkName: this.dynamicValidateForm.projectHomeworkName } homeworkApi.saveProjectHomework(projectData) .then(res => { this.$message({ message: '提交成功', type: 'success' }); this.dynamicValidateForm.projectHomeworkTeamNumber = res.data.projectHomework.projectHomeworkTeamNumber this.dynamicValidateForm.projectHomeworkIntroduceText = res.data.projectHomework.projectHomeworkIntroduceText this.dynamicValidateForm.projectHomeworkName = res.data.projectHomework.projectHomeworkName }) } else { this.$message({ message: '請檢查格式,再提交!', type: 'error' }); } }); }, //重制表單 resetForm(formName) { this.$refs[formName].resetFields(); this.dynamicValidateForm.projectHomeworkName = "" this.dynamicValidateForm.projectHomeworkIntroduceText = "" this.dynamicValidateForm.projectHomeworkTeamNumber = "" }, } } </script> <style scoped src="../../assets/discuss_css/coursewarev3.css"></style> <style scoped> a { text-decoration: none; } li { list-style-type: none; } .right-pannel .operation { padding: 24px 24px 0; height: 42px; } .right-pannel .operation > div { width: 130px; height: 40px; line-height: 40px; color: #32BAF0; border: 1px solid #32BAF0; border-radius: 4px; padding-left: 22px; margin-right: 15px; cursor: pointer; } .fl { float: left; } .right-pannel .operation div i { font-size: 14px; padding-right: 10px; } .homework-operation { color: #4d90fe; font-size: 10px; margin-left: 20px; cursor: pointer; } </style> <style scoped> @import url('../../assets/file/iconfont.css'); .header { box-shadow: 0px 1px 3px 0px rgba(0, 0, 0, 0.04); background: none repeat scroll 0% 0% #fff; display: flex; justify-content: space-between; margin-top: 20px; height: 45px; } .header-icon { cursor: pointer; } .courseName { background: #2c58ab; color: white; padding: 6px 20px; border-radius: 16px; font-size: 14px; font-family: PingFangSC-Medium; font-weight: 500; position: relative; bottom: 16px; right: 45px; } .header-left { position: relative; left: 50px; } .header-right { position: relative; right: 100px; } .header-center span { height: 74px; padding-left: 50px; padding-right: 50px; font-size: 16px; font-weight: 500; color: rgba(59, 61, 69, 1); padding-bottom: 20px; cursor: pointer; } .header-center span:hover { border-bottom: 4px solid #2C58AB; } .head-title h2 { font-size: 18px; color: #2d2d2d; font-weight: 400; display: inline-block; } .head-title .togsh p { padding: 5px 20px; margin-right: 10px; background: rgba(0, 0, 0, .1); } .head-title .togsh p { padding: 5px 20px; margin-right: 10px; background: rgba(0, 0, 0, .1); font-size: 14px; width: 175px; margin-top: -5px; } .classify dt { color: #5A5A5A; line-height: 46px; height: 46px; width: 150px; border-right: 1px solid #DCDCDC; background: #F2F2F2; text-indent: 30px; font-size: 12px; margin-right: 36px; border-bottom: 1px dashed #eaeaea; margin-bottom: -1px; } .classify li { width: 48px; height: 20px; line-height: 20px; margin-right: 30px; border: 1px solid transparent; cursor: pointer; font-size: 12px; text-align: center; } .classify el-checkbox { padding-left: 25px; font-size: 12px; color: #5a5a5a; border-radius: 3px; height: 33px; line-height: 33px; width: 83px; cursor: pointer; } li { list-style: none; } .typehead li { display: inline-block; float: left; vertical-align: middle; } .typehead li div { display: block; width: 100px; line-height: 38px; border: 1px solid transparent; margin-left: -1px; color: #595959; font-size: 12px; } .backwork /deep/ span { position: relative; bottom: 3px; right: 4px; font-size: 12px; } .nav-menu-right { float: right; margin-right: 65px; margin-top: -4px; } .iconfont { font-family: iconfont !important; font-size: 16px; font-style: normal; -webkit-font-smoothing: antialiased; -moz-osx-font-smoothing: grayscale; } .cWidth-new { width: 1224px; margin-left: auto; margin-right: auto; } .cWidth-new { width: 1224px; margin-left: auto; margin-right: auto; } .clearfix { zoom: 1; } </style>
SubmitHomeworkController
package com.wang.youketang.controller; import com.wang.youketang.common.result.R; import com.wang.youketang.entity.SubmitHomework; import com.wang.youketang.service.SubmitHomeworkService; import io.swagger.annotations.ApiOperation; import org.springframework.transaction.annotation.Transactional; import org.springframework.util.ResourceUtils; import org.springframework.web.bind.annotation.*; import org.springframework.web.multipart.MultipartFile; import javax.annotation.Resource; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import java.io.*; import java.net.URLEncoder; import java.text.SimpleDateFormat; import java.util.Date; import java.util.List; /** * (SubmitHomework)表控制層 */ @RestController @RequestMapping("/submitHomework") @CrossOrigin public class SubmitHomeworkController { /** * 服務(wù)對象 */ @Resource private SubmitHomeworkService submitHomeworkService; //根據(jù)課程號和人員id獲取交的作業(yè) @GetMapping("/getSubmitHomework") public R getSubmitHomework(@RequestParam long homeworkId, @RequestParam long studentId) { List<SubmitHomework> submitHomeWork = submitHomeworkService.selectHWByIds(homeworkId, studentId); return R.ok().data("submitHomeworkList", submitHomeWork); } // @ApiOperation(value = "提交作業(yè)") @PostMapping("/submitHomework") public R submitHomework(@RequestBody SubmitHomework submitHomework) { SubmitHomework submitWork = submitHomeworkService.increaseSubmitHomework(submitHomework); return R.ok().data("submitWork", submitWork); } // @ApiOperation(value = "根據(jù)課程號和用戶id獲取交的所有作業(yè)") @GetMapping("/getSubmitHomeworkList") public R getSubmitHomeworkList(@RequestParam long courseId, @RequestParam long studentId) { List<SubmitHomework> submitHomeworkList = submitHomeworkService.getSubmitHomeworkList(courseId, studentId); return R.ok().data("submitHomeworkList", submitHomeworkList); } // 刪除 @PostMapping("/removeSubmitHomework") @Transactional public R removeSubmitHomework(@RequestBody long[] submitHomeworkIds) { boolean removeResult = false; for (long submitHomeworkId : submitHomeworkIds) { //通過id獲取文件的物理地址,并對其刪除。 // 將"\"替換成"/",java將“\”當(dāng)成轉(zhuǎn)義符。轉(zhuǎn)化為:“C:/Users/29395/AppData/Local/...” String filePath = this.submitHomeworkService.findFileRealPathById(submitHomeworkId); if(filePath == null){ // 當(dāng)路徑為空 removeResult = submitHomeworkService.dropSubmitHomeworkById(submitHomeworkId); }else{ // 不為空的時候 File file = new File(filePath.replace("\\", "/")); removeResult = submitHomeworkService.dropSubmitHomeworkById(submitHomeworkId) && file.delete() ; } } return removeResult ? R.ok() : R.error().message("刪除失敗!若視頻為項目介紹,請先上傳新的視頻,才能刪除舊視頻。"); } // 根據(jù)id獲取提交的作業(yè)打分 @PostMapping("/markSubmitHomework") public R markSubmitHomework(@RequestParam long studentId, @RequestParam String grade) { boolean updateResult = submitHomeworkService.modifyGradeByStudentId(studentId,grade); return updateResult?R.ok():R.error().message("打分失敗?。?!"); } // "打回作業(yè)" @PostMapping("/backSubmitHomework/{studentId}") public R backSubmitHomework(@PathVariable long studentId) { boolean updateResult = submitHomeworkService.modifyGradeBackByStudentId(studentId); return updateResult?R.ok():R.error().message("打回作業(yè)失?。。?!"); } @RequestMapping("/submitHomeworkFile/{submitHomeworkId}") public R submitHomeworkFile(@RequestParam("file") MultipartFile multipartFile, @PathVariable long submitHomeworkId, HttpServletRequest req) throws IOException { System.out.println("id___________________"+submitHomeworkId); SimpleDateFormat sdf = new SimpleDateFormat("/yyyy/MM/dd/"); String format = sdf.format(new Date());//時間 // 獲得項目在磁盤的地址,如:D:/eclipse-workspace/studyProject/youketangV0.0/youketang_ssm/target/classes//store/2023/02/19/ // String realPath = ResourceUtils.getURL("classpath:").getPath() + "/store" + format; // /www/wwwroot/resource String realPath = "D:" + "/store" + format; // String realPath = "/www/wwwroot/resource" + "/store" + format; // String realPath = req.getServletContext().getRealPath("/")+"/store"+format; // getRealPath("/")方法返回的是項目在服務(wù)器的絕對路徑(C:\Users\29395\AppData\Local\Temp\tomcat-docbase.4782946598994668439.8888\/store/2023/02/19/) //由于是在temp臨時文件,每次重啟服務(wù)器,都找不到之前的文件url. File fileDir = new File(realPath); if (!fileDir.exists()) { fileDir.mkdirs(); } if (multipartFile != null) { String fileName = multipartFile.getOriginalFilename();//獲取名字 // 172.17.160.1為服務(wù)器的IP地址 // String url = req.getScheme() + "://" + "47.94.255.44" + ":" + req.getServerPort() + "/store" + format + fileName; String url = req.getScheme() + "://" + "localhost" + ":" + req.getServerPort() + "/store" + format + fileName; // transferTo(File dest) 將接收到的文件傳輸?shù)浇o定的目標(biāo)文件。 multipartFile.transferTo(new File(realPath, fileName)); String fileReal = fileDir + "http://" + fileName; // System.out.println(fileReal); SubmitHomework submitHomework = submitHomeworkService.findSubmitHomeworkById(submitHomeworkId); submitHomework.setSubmitHomeworkFileRealPath(fileReal); submitHomework.setSubmitHomeworkFilePath(url); submitHomework.setSubmitHomeworkFileName(multipartFile.getOriginalFilename()); submitHomeworkService.modifySubmitHomework(submitHomework); return R.ok().data("path", url); } else { return R.ok().message("請選中文件"); } } @GetMapping("/downloadSubmitHomeworkFile/{submitHomeworkId}") public void downloadSubmitHomeworkFile(@PathVariable("submitHomeworkId") long submitHomeworkId, HttpServletResponse response) { SubmitHomework submitHomework = submitHomeworkService.findSubmitHomeworkById(submitHomeworkId); String fileRealPath = submitHomework.getSubmitHomeworkFileRealPath(); String fileName = submitHomework.getSubmitHomeworkFileName(); File file = new File(fileRealPath); byte[] buffer = new byte[1024]; BufferedInputStream bis = null; OutputStream os = null; try { //文件是否存在 if (file.exists()) { response.setHeader("Access-Control-Allow-Origin", "*"); // 允許所有 //設(shè)置響應(yīng) response.setContentType("application/octet-stream;charset=UTF-8"); // 將響應(yīng)頭中的Content-Disposition暴露出來,不然前端獲取不到 response.setHeader("Access-Control-Expose-Headers", "Content-Disposition"); // 在響應(yīng)頭中的Content-Disposition里設(shè)置文件名稱 response.setHeader("Content-Disposition", "attachment;filename=" + URLEncoder.encode(fileName, "UTF-8")); // response.setHeader("Content-Disposition", "attachment;filename=" + fileName); os = response.getOutputStream(); bis = new BufferedInputStream(new FileInputStream(file)); while (bis.read(buffer) != -1) { os.write(buffer); } } } catch (Exception e) { e.printStackTrace(); } finally { try { if (bis != null) { bis.close(); } if (os != null) { os.flush(); os.close(); } } catch (IOException e) { e.printStackTrace(); } } } }
CorsConfig.java
package com.wang.youketang.common.config; import com.wang.youketang.common.interceptor.JWTInterceptor; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.util.ResourceUtils; import org.springframework.web.servlet.config.annotation.CorsRegistry; import org.springframework.web.servlet.config.annotation.InterceptorRegistry; import org.springframework.web.servlet.config.annotation.ResourceHandlerRegistry; import org.springframework.web.servlet.config.annotation.WebMvcConfigurer; @Configuration public class CorsConfig implements WebMvcConfigurer{ @Override public void addCorsMappings(CorsRegistry registry) { // 允許跨域訪問的路徑 '/**'表示應(yīng)用的所有方法 registry.addMapping("/**") .allowedOrigins("*") // .allowedOrigins("http://172.17.160.1:8080") //ip地址+端口號 // .allowedOrigins("http://172.18.29.108:8080") //前端vue的ip // .allowedOrigins("http://172.17.160.1:8080") //本機(jī)的ip // 允許跨域訪問的來源 '*'表示所有域名來源 .allowedMethods("GET", "HEAD", "POST", "PUT", "DELETE", "OPTIONS") // 是否允許發(fā)送cookie true-允許 false-不允許 默認(rèn)false。對服務(wù)器有特殊要求的請求,比如請求方法是PUT或DELETE,或者Content-Type字段的類型是application/json,這個值只能設(shè)為true .allowCredentials(true) // 預(yù)檢間隔時間1小時,單位為秒。指定本次預(yù)檢請求的有效期,在有效期間,不用發(fā)出另一條預(yù)檢請求。 // 瀏覽器發(fā)出CORS簡單請求,只需要在頭信息之中增加一個Origin字段 // 瀏覽器發(fā)出CORS非簡單請求,會在正式通信之前,增加一次OPTIONS查詢請求,稱為"預(yù)檢"請求(preflight)。瀏覽器先詢問服務(wù)器,當(dāng)前網(wǎng)頁所在的域名是否在服務(wù)器的許可名單之中,以及可以使用哪些HTTP動詞和頭信息字段。只有得到肯定答復(fù),瀏覽器才會發(fā)出正式的XMLHttpRequest請求,否則就報錯。 .maxAge(3600) // 允許跨域請求可攜帶的header,'*'表所有header頭。CORS請求時,XMLHttpRequest對象的getResponseHeader()方法只能拿到6個基本字段:Cache-Control、Content-Language、Content-Type、Expires、Last-Modified、Pragma。如果想拿到其他字段,就必須在Access-Control-Expose-Headers里面指定 .allowedHeaders("*"); } @Override public void addResourceHandlers(ResourceHandlerRegistry registry) { // 訪問相對路徑 // PS:注意文件路徑最后的斜杠(文件分隔符),如果缺少了,就不能夠正確的映射到相應(yīng)的目錄 String baseDocumentPath = "file:D:/document/"; String baseStorePath = "file:D:/store/"; // String baseDocumentPath = "file:/www/wwwroot/resource/document/"; // String baseStorePath = "file:/www/wwwroot/resource/store/"; // /www/wwwroot/resource registry.addResourceHandler("/document/**").addResourceLocations(baseDocumentPath); registry.addResourceHandler("/store/**").addResourceLocations(baseStorePath); WebMvcConfigurer.super.addResourceHandlers(registry); } //注冊攔截器 public void addInterceptors(InterceptorRegistry registry) { registry.addInterceptor(new JWTInterceptor()) .addPathPatterns("/**") //需要token驗證的接口 一般是全部接口 .excludePathPatterns("/student/**","/teacher/**","/document/**","/store/**"); // } }
總結(jié)
到此這篇關(guān)于vue+springboot上傳文件、圖片、視頻及回顯到前端的文章就介紹到這了,更多相關(guān)vue springboot上傳文件及回顯內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
Java代碼的三根頂梁柱:循環(huán)結(jié)構(gòu)
這篇文章主要介紹了JAVA 循環(huán)結(jié)構(gòu)的相關(guān)資料,文中講解的非常細(xì)致,示例代碼幫助大家更好的理解和學(xué)習(xí),感興趣的朋友可以了解下2021-08-08springboot整合xxl-job的實現(xiàn)示例
本文主要介紹了springboot整合xxl-job的實現(xiàn)示例,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2023-06-06Redis 集成Spring的示例代碼(spring-data-redis)
本篇文章主要介紹了Redis 集成Spring的示例代碼(spring-data-redis) ,具有一定的參考價值,感興趣的小伙伴們可以參考一下2017-09-09java中關(guān)于文本文件的讀寫方法實例總結(jié)
這篇文章主要介紹了java中關(guān)于文本文件的讀寫方法,實例總結(jié)了Java針對文本文件讀寫的幾種常用方法,并對比了各個方法的優(yōu)劣及特點,具有一定參考借鑒價值,需要的朋友可以參考下2015-11-11