vue+springboot 上传文件、图片、视频,回显到前端。
效果图
预览:
视频:
设计逻辑
数据库表
前端vue
html
<div class="right-pannel"><div class="data-box"><!--上传的作业--><div style="display: block" id=""><div class="title clearfix"><div class="all fl" data-folderid="0"><a class="here">上传附件(上传项目演示视频应为mp4格式)</a></div></div><div class="container_con"><!--作业超时提示--><el-dialogtitle="提示":visible.sync="workLateTip"width="30%"><span>作业已截止,禁止提交,请联系任课老师</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"><iclass="iconfont iconshanchu1"></i>批量删除</div></div><el-progress id="showProgress" style="display:none;" :stroke-width="16":percentage="progressPercent"></el-progress><el-tableref="multipleTable":data="tableFileList"tooltip-effect="dark"style="width: 100%"@selection-change="handleSelectionChange"><el-table-columntype="selection"width="55"></el-table-column><el-table-columnprop="submitHomeworkFileName"label="文件名"width="350"></el-table-column><el-table-columnprop="submitHomeworkFileSize"label="大小"width="150"></el-table-column><el-table-columnprop="submitHomeworkGrade"label="成绩状态"width="100"></el-table-column><el-table-columnprop="submitHomeworkCreateTime"label="上传时间"width="220"></el-table-column><el-table-columnwidth="300"><template slot-scope="scope"><a @click="preview(scope.row.submitHomeworkFilePath)"class="homework-operation"style="margin-left: 50px">预览</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: '上传文件应小于1G',type: 'error',duration: 3000});return}//初始化为0,表示不是项目介绍视频this.submitWork.submitHomeworkIntroduceVideo = "0"// console.log(inputFile)//视频类型:video/mp4if (inputFile.type === "video/mp4") {this.$message({message: '上传视频将作为视频介绍',type: 'info',duration: 5000});//设置 1,表示标记为项目介绍视频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.fileNamethis.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: '作业信息提交成功',type: 'success'});this.addZiYuanDis = false;//提交作业的id存储在会话中sessionStorage.setItem("finishWorkId", res.data.submitWork.submitHomeworkId)//当已经存进数据库之后再进行修改this.submit();}).catch(() => {this.$message({message: '作业信息提交失败!请重试!',type: 'error'});})},//文件提交到本地云端存储submit() {var formData = new FormData();const submitHomeworkId = sessionStorage.getItem("finishWorkId")let file = this.$refs.filElem.files[0]formData.append('file', file) // 'file' 这个名字要和后台获取文件的名字一样;//显示进度条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) { //是否存在进度this.progressPercent = parseInt((progressEvent.loaded / progressEvent.total) * 100)}},}this.$axios.post('submitHomework/submitHomeworkFile/' + submitHomeworkId, formData, configs).then(res => {this.$message({message: '作业上传成功',type: 'success'});document.getElementById("showProgress").style.display = "none";document.getElementById("submit-display").style.display = "block";this.getAllZiYuan();}).catch(error => {this.$message({message: '作业上传失败!请重试!',type: 'error'});document.getElementById("showProgress").style.display = "none";document.getElementById("submit-display").style.display = "block";})},
前端思路
分成两部,1.通过前端将文件的基本信息传送到后端进行储存,返回已储存的文件id,2.再将文件发送到后端储存。
储存文件信息
上传文件对象
后端上传下载代码
@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/resourceString realPath = "D:" + "/store" + format;
// String realPath = "/www/wwwroot/resource" + "/store" + format;
// String realPath = req.getServletContext().getRealPath("/")+"/store"+format;
// getRealPath("/")方法返回的是项目在服务器的绝对路径(C:\Users\29395\AppData\Local\Temp\tomcat-docbase.4782946598994668439.8888\/store/2023/02/19/)
//由于是在temp临时文件,每次重启服务器,都找不到之前的文件url.File fileDir = new File(realPath);if (!fileDir.exists()) {fileDir.mkdirs();}if (multipartFile != null) {String fileName = multipartFile.getOriginalFilename();//获取名字
// 172.17.160.1为服务器的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) 将接收到的文件传输到给定的目标文件。multipartFile.transferTo(new File(realPath, fileName));String fileReal = fileDir + "//" + 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", "*"); // 允许所有//设置响应response.setContentType("application/octet-stream;charset=UTF-8");// 将响应头中的Content-Disposition暴露出来,不然前端获取不到response.setHeader("Access-Control-Expose-Headers", "Content-Disposition");// 在响应头中的Content-Disposition里设置文件名称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盘下面,需要修改映射路径
@Overridepublic void addResourceHandlers(ResourceHandlerRegistry registry) {// 访问相对路径// PS:注意文件路径最后的斜杠(文件分隔符),如果缺少了,就不能够正确的映射到相应的目录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/resourceregistry.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;">提交作业</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;
"> 有关作业的基本信息</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="作业题目" style="color: #34373D;"><el-input v-model="homeworkForm.homeworkTitle" disabled></el-input></el-form-item><el-form-item prop="fullScore"label="分数"><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="作业描述"><!--渲染--><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;
"> 项目相关介绍</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"><videoid="my-video"class="video-js"controlspreload="auto"width="1152"height="680"data-setup="{}":src=vedioSrc></video></div><div class="right-pannel"><div class="data-box"><!--上传的作业--><div style="display: block" id=""><div class="title clearfix"><div class="all fl" data-folderid="0"><a class="here">上传附件(上传项目演示视频应为mp4格式)</a></div></div><div class="container_con"><!--作业超时提示--><el-dialogtitle="提示":visible.sync="workLateTip"width="30%"><span>作业已截止,禁止提交,请联系任课老师</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"><iclass="iconfont iconshanchu1"></i>批量删除</div></div><el-progress id="showProgress" style="display:none;" :stroke-width="16":percentage="progressPercent"></el-progress><el-tableref="multipleTable":data="tableFileList"tooltip-effect="dark"style="width: 100%"@selection-change="handleSelectionChange"><el-table-columntype="selection"width="55"></el-table-column><el-table-columnprop="submitHomeworkFileName"label="文件名"width="350"></el-table-column><el-table-columnprop="submitHomeworkFileSize"label="大小"width="150"></el-table-column><el-table-columnprop="submitHomeworkGrade"label="成绩状态"width="100"></el-table-column><el-table-columnprop="submitHomeworkCreateTime"label="上传时间"width="220"></el-table-column><el-table-columnwidth="300"><template slot-scope="scope"><a @click="preview(scope.row.submitHomeworkFilePath)"class="homework-operation"style="margin-left: 50px">预览</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 中使用此方法创建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: '',//项目视频的srcfinishWorkId: '', //用于更新提交时传递到后台覆盖原纪录isLiuYanEmpty: true, //留言是否为空,默认都是空isUpload: false, //是否提交了该作业workLateTip: false, //作业提交超时提醒fileSize: [], //上传的文件大小readWorkTipDisplay: false, //定义批阅作业的提醒弹框tableData: [], //定义作业提交详情总览introduceVideo: '', //标记是否为视频input1: '',hide: '',gradeList: [],similarityList: [],submitList: [],shareList: [],selected: false,givePoints: '',managecheck: false,courseName: sessionStorage.getItem("courseName"),homeworkId: '',submitWorkId: '',//提交作业后端返回的idcourse: {id: '',courseName: '',className: '',year: '',semester: ''},homework: {},classmateCount: '',submitCount: '',submittedList: [], //定义提交详情所有学生的信息展示 包括 已批 未批 未交submitInfo: {score: '',id: '',name: '',number: '',bestScore: '',publishTime: '',fileAddress: ''},submitWork: {},read: '未阅',score: '',beginScore: [],state: '',tempFileSize: '', //暂时存的文件大小fileSizeType: '', //文件大小类型 MB KBfileName: '',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}},//进入页面内容全部渲染完成后自动引函数mounted() {this.getProjectHomeworkInfo();this.getAllZiYuan();},methods: {getProjectHomeworkInfo() {let homeworkId = sessionStorage.getItem("homeworkId");let studentId = sessionStorage.getItem("studentId");//获取作业的基本信息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.projectHomeworkIntroduceTextthis.dynamicValidateForm.projectHomeworkTeamNumber = res.data.projectHomework.projectHomeworkTeamNumberthis.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//对项目视频介绍标记,判断introduceVideo是否为1,如果为1,则为视频介绍,赋值videoSrc,并显示视频标签.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";}}})},//学生端预览文件preview(url) {//console.log(indexurl);//要预览文件的访问地址window.open(url);},//单个删除deleteOne(id) {console.log(id)this.deleteIdList.push(id)this.$confirm('此操作将删除该资料, 是否继续?', '提示', {confirmButtonText: '确定',cancelButtonText: '取消',type: 'warning'}).then(() => {//异步请求删除homeworkApi.removeSubmitHomework(this.deleteIdList).then(res => {this.deleteIdList = [] //进行置空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('此操作将删除该资料, 是否继续?', '提示', {confirmButtonText: '确定',cancelButtonText: '取消',type: 'warning'}).then(() => {//异步请求删除homeworkApi.removeSubmitHomework(this.deleteIdList).then(res => {this.deleteIdList = [] //进行置空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("选中值发生了改变")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: '上传文件应小于1G',type: 'error',duration: 3000});return}//初始化为0,表示不是项目介绍视频this.submitWork.submitHomeworkIntroduceVideo = "0"// console.log(inputFile)//视频类型:video/mp4if (inputFile.type === "video/mp4") {this.$message({message: '上传视频将作为视频介绍',type: 'info',duration: 5000});//设置 1,表示标记为项目介绍视频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.fileNamethis.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: '作业信息提交成功',type: 'success'});this.addZiYuanDis = false;//提交作业的id存储在会话中sessionStorage.setItem("finishWorkId", res.data.submitWork.submitHomeworkId)//当已经存进数据库之后再进行修改this.submit();}).catch(() => {this.$message({message: '作业信息提交失败!请重试!',type: 'error'});})},//文件提交到本地云端存储submit() {var formData = new FormData();const submitHomeworkId = sessionStorage.getItem("finishWorkId")let file = this.$refs.filElem.files[0]formData.append('file', file) // 'file' 这个名字要和后台获取文件的名字一样;//显示进度条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) { //是否存在进度this.progressPercent = parseInt((progressEvent.loaded / progressEvent.total) * 100)}},}this.$axios.post('submitHomework/submitHomeworkFile/' + submitHomeworkId, formData, configs).then(res => {this.$message({message: '作业上传成功',type: 'success'});document.getElementById("showProgress").style.display = "none";document.getElementById("submit-display").style.display = "block";this.getAllZiYuan();}).catch(error => {this.$message({message: '作业上传失败!请重试!',type: 'error'});document.getElementById("showProgress").style.display = "none";document.getElementById("submit-display").style.display = "block";})},//跳转到作业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=???????.docxconst 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 解码后:软件项目计划表.docxvar fileName = decodeURIComponent(fileNameUtf8)console.log("res:" + res.headers['content-disposition'])console.log("fileName:" + fileName)//对于<a>标签,只有 Firefox 和 Chrome(内核) 支持 download 属性//IE10以上支持blob,但是依然不支持download//支持a标签download的浏览器const link = document.createElement('a');//创建a标签link.download = fileName;//a标签添加属性link.style.display = 'none';link.href = URL.createObjectURL(blob);document.body.appendChild(link);link.click();//执行下载URL.revokeObjectURL(link.href); //释放urldocument.body.removeChild(link);//释放标签this.$message.success("作业下载成功!")}).catch((res) => {this.$message.error("作业下载失败!请重试!")});},//提交表单submitForm(formName) {//进行校验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.projectHomeworkTeamNumberthis.dynamicValidateForm.projectHomeworkIntroduceText = res.data.projectHomework.projectHomeworkIntroduceTextthis.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 {/*** 服务对象*/@Resourceprivate SubmitHomeworkService submitHomeworkService;//根据课程号和人员id获取交的作业@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 = "提交作业")@PostMapping("/submitHomework")public R submitHomework(@RequestBody SubmitHomework submitHomework) {SubmitHomework submitWork = submitHomeworkService.increaseSubmitHomework(submitHomework);return R.ok().data("submitWork", submitWork);}// @ApiOperation(value = "根据课程号和用户id获取交的所有作业")@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")@Transactionalpublic R removeSubmitHomework(@RequestBody long[] submitHomeworkIds) {boolean removeResult = false;for (long submitHomeworkId : submitHomeworkIds) {//通过id获取文件的物理地址,并对其删除。// 将"\"替换成"/",java将“\”当成转义符。转化为:“C:/Users/29395/AppData/Local/...”String filePath = this.submitHomeworkService.findFileRealPathById(submitHomeworkId);if(filePath == null){
// 当路径为空removeResult = submitHomeworkService.dropSubmitHomeworkById(submitHomeworkId);}else{
// 不为空的时候File file = new File(filePath.replace("\\", "/"));removeResult = submitHomeworkService.dropSubmitHomeworkById(submitHomeworkId) && file.delete() ;}}return removeResult ? R.ok() : R.error().message("删除失败!若视频为项目介绍,请先上传新的视频,才能删除旧视频。");}// 根据id获取提交的作业打分@PostMapping("/markSubmitHomework")public R markSubmitHomework(@RequestParam long studentId, @RequestParam String grade) {boolean updateResult = submitHomeworkService.modifyGradeByStudentId(studentId,grade);return updateResult?R.ok():R.error().message("打分失败!!!");}// "打回作业"@PostMapping("/backSubmitHomework/{studentId}")public R backSubmitHomework(@PathVariable long studentId) {boolean updateResult = submitHomeworkService.modifyGradeBackByStudentId(studentId);return updateResult?R.ok():R.error().message("打回作业失败!!!");}@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/resourceString realPath = "D:" + "/store" + format;
// String realPath = "/www/wwwroot/resource" + "/store" + format;
// String realPath = req.getServletContext().getRealPath("/")+"/store"+format;
// getRealPath("/")方法返回的是项目在服务器的绝对路径(C:\Users\29395\AppData\Local\Temp\tomcat-docbase.4782946598994668439.8888\/store/2023/02/19/)
//由于是在temp临时文件,每次重启服务器,都找不到之前的文件url.File fileDir = new File(realPath);if (!fileDir.exists()) {fileDir.mkdirs();}if (multipartFile != null) {String fileName = multipartFile.getOriginalFilename();//获取名字
// 172.17.160.1为服务器的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) 将接收到的文件传输到给定的目标文件。multipartFile.transferTo(new File(realPath, fileName));String fileReal = fileDir + "//" + 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", "*"); // 允许所有//设置响应response.setContentType("application/octet-stream;charset=UTF-8");// 将响应头中的Content-Disposition暴露出来,不然前端获取不到response.setHeader("Access-Control-Expose-Headers", "Content-Disposition");// 在响应头中的Content-Disposition里设置文件名称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{@Overridepublic void addCorsMappings(CorsRegistry registry) {// 允许跨域访问的路径 '/**'表示应用的所有方法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") //本机的ip// 允许跨域访问的来源 '*'表示所有域名来源.allowedMethods("GET", "HEAD", "POST", "PUT", "DELETE", "OPTIONS")// 是否允许发送cookie true-允许 false-不允许 默认false。对服务器有特殊要求的请求,比如请求方法是PUT或DELETE,或者Content-Type字段的类型是application/json,这个值只能设为true.allowCredentials(true)// 预检间隔时间1小时,单位为秒。指定本次预检请求的有效期,在有效期间,不用发出另一条预检请求。// 浏览器发出CORS简单请求,只需要在头信息之中增加一个Origin字段// 浏览器发出CORS非简单请求,会在正式通信之前,增加一次OPTIONS查询请求,称为"预检"请求(preflight)。浏览器先询问服务器,当前网页所在的域名是否在服务器的许可名单之中,以及可以使用哪些HTTP动词和头信息字段。只有得到肯定答复,浏览器才会发出正式的XMLHttpRequest请求,否则就报错。.maxAge(3600)// 允许跨域请求可携带的header,'*'表所有header头。CORS请求时,XMLHttpRequest对象的getResponseHeader()方法只能拿到6个基本字段:Cache-Control、Content-Language、Content-Type、Expires、Last-Modified、Pragma。如果想拿到其他字段,就必须在Access-Control-Expose-Headers里面指定.allowedHeaders("*");}@Overridepublic void addResourceHandlers(ResourceHandlerRegistry registry) {// 访问相对路径// PS:注意文件路径最后的斜杠(文件分隔符),如果缺少了,就不能够正确的映射到相应的目录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/resourceregistry.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/**"); //}}
相关文章:

vue+springboot 上传文件、图片、视频,回显到前端。
效果图 预览: 视频: 设计逻辑 数据库表 前端vue html <div class"right-pannel"><div class"data-box"><!--上传的作业--><div style"display: block" id""><div class"tit…...
java入门-W3(K81-K143)
一. 什么是对象 什么是对象?之前我们讲过,对象就是计算机中的虚拟物体。例如 System.out,System.in 等等。然而,要开发自己的应用程序,只有这些现成的对象还远远不够。需要我们自己来创建新的对象。 例如,…...
English Learning - L2 语音作业打卡 复习元音 [ɜː] [æ] 辅元连读技巧 Day42 2023.4.3 周一
English Learning - L2 语音作业打卡 复习元音 [ɜː] [] 辅元连读技巧 Day42 2023.4.3 周一💌发音小贴士:💌当日目标音发音规则/技巧:中元音 [ɜː]前元音 []辅元连读技巧🍭 Part 1【热身练习】🍭 Part2【练习内容】&…...
Thinkphp 6.0图像处理功能
本节课我们来学习一下图像处理功能,这功能是外置的,并非系统内置。 一.图像处理功能 1. 图像处理功能不是系统内置的功能了,需要通过 composer 引入进来; composer require topthink/think-image 2. 引入进来之后&…...

表格软件界的卷王,Excel、access、foxpro全靠边,WPS:真荣幸
Excel和Access就是表格软件的选择? 现在,铺天盖地的Excel的技能教程可谓是满天飞,有网上的教程,也有视频直播课程。 很多办公人员用Excel这种表格软件与VBA结合,甚至用不遗余力去学习Python编程语法,但Exce…...

Node.js -- http模块
1. 什么是http模块 在网络节点中,负责消费资源的电脑,叫客户端;负责对外提供网络资源的电脑,叫做服务器。 http模块是Node.js官方提供的,用来创建web服务器的模块。通过http模块提供的http.createServer()方法&#…...

静态库与动态库
库是已经写好的、成熟的、可复用的代码。在我们的开发的应用中经常有一些公共代码是需要反复使用的,就把这些代码编译为库文件。库可以简单看成一组目标文件的集合,将这些目标文件经过压缩打包之后形成的一个可执行代码的二进制文件。库有两种࿱…...
问题 A: C语言11.1
题目描述: 完成一个对候选人得票的统计程序。假设有3个候选人,名字分别为Li,Zhang和Fun。使用结构体存储每一个候选人的名字和得票数。记录每一张选票的得票人名,输出每个候选人最终的得票数。结构体可以定义成如下的格式&#x…...

SLAM中后端优化的技术细节总结与回答
SLAM中后端优化的技术细节 本文档主要收集总结了一些SLAM大佬们讲解后端优化中偏理论的技术细节的博客和回答以及一些学习教材。 Written by wincent 位姿估计以及李群相关的概述 Lie theory is by no means simple ———— 谎言理论绝不简单doge 《A micro Lie theory for st…...
小白快速学习Markdown
这里写自定义目录标题欢迎使用Markdown编辑器新的改变功能快捷键合理的创建标题,有助于目录的生成如何改变文本的样式插入链接与图片如何插入一段漂亮的代码片生成一个适合你的列表创建一个表格设定内容居中、居左、居右SmartyPants创建一个自定义列表如何创建一个注…...

ToBeWritten之物联网WI-FI协议
也许每个人出生的时候都以为这世界都是为他一个人而存在的,当他发现自己错的时候,他便开始长大 少走了弯路,也就错过了风景,无论如何,感谢经历 转移发布平台通知:将不再在CSDN博客发布新文章,敬…...
C++模板元编程深度解析:探索编译时计算的神奇之旅
C模板元编程深度解析:探索编译时计算的神奇之旅引言C模板元编程的概念与作用模板元编程在现代C编程中的应用模板元编程基础类型萃取(Type Traits)编译时条件(静态if)模板元编程中的递归与终止条件模板元编程技巧与工具…...
姿态变换及坐标变换
目录0. 空见间变换&基变换0.0 空间变换0.1 基变换1.缩放、旋转、平移机器人齐次变换坐标系变换0. 空见间变换&基变换 这是矩阵分析的相关知识,有兴趣的参考第一篇知乎文章[1]. 0.0 空间变换 空间变换是指在同一组绝对基下的变换,可以想象为世…...
从命令行管理文件
目录标题文件命名规则创建、删除普通文件创建普通文件格式创建多个普通文件删除普通文件目录操作命令创建目录--mkdir命令统计目录及文件的空间占用情况--du命令删除目录文件复制、移动文件复制(copy)文件或目录--cp命令移动(mv)文…...

电脑无法正常关机?点了关机又会自动重启
“真木马”相信不少朋友遇到过电脑关机自动重启现象,一点关机,但随后电脑有会进入重启状态,就是一直不会停,属实是很难崩。 目录 一、问题症状 二、问题原因 三、解决方案 方法一: 1.关闭系统发生错误时电脑自动…...
English Learning - L2 语音作业打卡 复习双元音 [eɪ] [aɪ] r 谦让型爆破技巧 Day46 2023.4.7 周五
English Learning - L2 语音作业打卡 复习双元音 [eɪ] [aɪ] r 谦让型爆破技巧 Day46 2023.4.7 周五💌发音小贴士:💌当日目标音发音规则/技巧:[eɪ][aɪ]谦让型爆破🍭 Part 1【热身练习】🍭 Part2【练习内容】&#x…...

webgl-画任意多边形
注意: let canvas document.getElementById(webgl) canvas.width window.innerWidth canvas.height window.innerHeight let radio window.innerWidth/window.innerHeight; let ctx canvas.getContext(webgl) 由于屏幕长宽像素不一样,导致了长宽像素…...
代码随想录打卡第51天|309.最佳买卖股票时机含冷冻期;714.买卖股票的最佳时机含手续费
309.最佳买卖股票时机含冷冻期 关键点1:dp数组的含义 1-1:dp[i][0] 第i天持有股票的最大金钱 1-2:dp[i][1] 第i天卖出股票的最大金钱 1-3:dp[i][2] 第i天处于冷冻期的最大金钱 1-4:dp[i][3] 第i天保持卖出股票的最大金…...

Spark Shuffle介绍
文章目录1. 简介2. Hash Shuffle和Sort Shuffle2.1 Hash Shuffle2.1.1 未经优化的hashShuffleManager2.1.2 经优化的hashShuffleManager2.1.3 优化前后磁盘文件数对比2.2 Srot Shuffle Manager3. Shuffle配置选项1. 简介 Spark在DAG调度阶段会将一个Job划分为多个Stage&#x…...

【数据库原理 • 三】关系数据库标准语言SQL
前言 数据库技术是计算机科学技术中发展最快,应用最广的技术之一,它是专门研究如何科学的组织和存储数据,如何高效地获取和处理数据的技术。它已成为各行各业存储数据、管理信息、共享资源和决策支持的最先进,最常用的技术。 当前…...

深度学习在微纳光子学中的应用
深度学习在微纳光子学中的主要应用方向 深度学习与微纳光子学的结合主要集中在以下几个方向: 逆向设计 通过神经网络快速预测微纳结构的光学响应,替代传统耗时的数值模拟方法。例如设计超表面、光子晶体等结构。 特征提取与优化 从复杂的光学数据中自…...

Lombok 的 @Data 注解失效,未生成 getter/setter 方法引发的HTTP 406 错误
HTTP 状态码 406 (Not Acceptable) 和 500 (Internal Server Error) 是两类完全不同的错误,它们的含义、原因和解决方法都有显著区别。以下是详细对比: 1. HTTP 406 (Not Acceptable) 含义: 客户端请求的内容类型与服务器支持的内容类型不匹…...
论文解读:交大港大上海AI Lab开源论文 | 宇树机器人多姿态起立控制强化学习框架(二)
HoST框架核心实现方法详解 - 论文深度解读(第二部分) 《Learning Humanoid Standing-up Control across Diverse Postures》 系列文章: 论文深度解读 + 算法与代码分析(二) 作者机构: 上海AI Lab, 上海交通大学, 香港大学, 浙江大学, 香港中文大学 论文主题: 人形机器人…...
C++:std::is_convertible
C++标志库中提供is_convertible,可以测试一种类型是否可以转换为另一只类型: template <class From, class To> struct is_convertible; 使用举例: #include <iostream> #include <string>using namespace std;struct A { }; struct B : A { };int main…...
MySQL 隔离级别:脏读、幻读及不可重复读的原理与示例
一、MySQL 隔离级别 MySQL 提供了四种隔离级别,用于控制事务之间的并发访问以及数据的可见性,不同隔离级别对脏读、幻读、不可重复读这几种并发数据问题有着不同的处理方式,具体如下: 隔离级别脏读不可重复读幻读性能特点及锁机制读未提交(READ UNCOMMITTED)允许出现允许…...
从零实现富文本编辑器#5-编辑器选区模型的状态结构表达
先前我们总结了浏览器选区模型的交互策略,并且实现了基本的选区操作,还调研了自绘选区的实现。那么相对的,我们还需要设计编辑器的选区表达,也可以称为模型选区。编辑器中应用变更时的操作范围,就是以模型选区为基准来…...

高频面试之3Zookeeper
高频面试之3Zookeeper 文章目录 高频面试之3Zookeeper3.1 常用命令3.2 选举机制3.3 Zookeeper符合法则中哪两个?3.4 Zookeeper脑裂3.5 Zookeeper用来干嘛了 3.1 常用命令 ls、get、create、delete、deleteall3.2 选举机制 半数机制(过半机制࿰…...

Ascend NPU上适配Step-Audio模型
1 概述 1.1 简述 Step-Audio 是业界首个集语音理解与生成控制一体化的产品级开源实时语音对话系统,支持多语言对话(如 中文,英文,日语),语音情感(如 开心,悲伤)&#x…...

【Java_EE】Spring MVC
目录 Spring Web MVC 编辑注解 RestController RequestMapping RequestParam RequestParam RequestBody PathVariable RequestPart 参数传递 注意事项 编辑参数重命名 RequestParam 编辑编辑传递集合 RequestParam 传递JSON数据 编辑RequestBody …...
HTML前端开发:JavaScript 常用事件详解
作为前端开发的核心,JavaScript 事件是用户与网页交互的基础。以下是常见事件的详细说明和用法示例: 1. onclick - 点击事件 当元素被单击时触发(左键点击) button.onclick function() {alert("按钮被点击了!&…...