vue+springboot上傳文件、圖片、視頻及回顯到前端詳解
效果圖



預(yù)覽:

設(shè)計(jì)邏輯

數(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">上傳附件(上傳項(xiàng)目演示視頻應(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,表示不是項(xiàng)目介紹視頻
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)記為項(xiàng)目介紹視頻
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());//時間
// 獲得項(xiàng)目在磁盤的地址,如: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("/")方法返回的是項(xiàng)目在服務(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;
"> 項(xiàng)目相關(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="項(xiàng)目名稱">
<el-input v-model="dynamicValidateForm.projectHomeworkName"></el-input>
</el-form-item>
<el-form-item prop="projectHomeworkIntroduceText"
label="項(xiàng)目介紹">
<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">上傳附件(上傳項(xiàng)目演示視頻應(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("項(xiàng)目名稱不能為空"));
} 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("項(xiàng)目介紹不能為空"));
} else {
callback();
}
};
return {
vedioSrc: '',//項(xiàng)目視頻的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
//對項(xiàng)目視頻介紹標(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: '已取消刪除'
});
});
},
//刪除資源(點(diǎn)擊批量刪除)
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,表示不是項(xiàng)目介紹視頻
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)記為項(xiàng)目介紹視頻
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 解碼后:軟件項(xiàng)目計(jì)劃表.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)行校驗(yà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("刪除失?。∪粢曨l為項(xiàng)目介紹,請先上傳新的視頻,才能刪除舊視頻。");
}
// 根據(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());//時間
// 獲得項(xiàng)目在磁盤的地址,如: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("/")方法返回的是項(xiàng)目在服務(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驗(yàn)證的接口 一般是全部接口
.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-08
springboot整合xxl-job的實(shí)現(xiàn)示例
本文主要介紹了springboot整合xxl-job的實(shí)現(xiàn)示例,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2023-06-06
Redis 集成Spring的示例代碼(spring-data-redis)
本篇文章主要介紹了Redis 集成Spring的示例代碼(spring-data-redis) ,具有一定的參考價值,感興趣的小伙伴們可以參考一下2017-09-09
MyBatis-plus實(shí)現(xiàn)逆向生成器
本文主要介紹了MyBatis-plus實(shí)現(xiàn)逆向生成器,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2022-08-08
java中關(guān)于文本文件的讀寫方法實(shí)例總結(jié)
這篇文章主要介紹了java中關(guān)于文本文件的讀寫方法,實(shí)例總結(jié)了Java針對文本文件讀寫的幾種常用方法,并對比了各個方法的優(yōu)劣及特點(diǎn),具有一定參考借鑒價值,需要的朋友可以參考下2015-11-11

