一、技術棧
1、前端 Vue3 + Element Plus + TypeSprict
2、后端 Spring Boot 3.2.12 + Mybatis Plus
3、模型特點
3.1、表格展示列表數據
3.2、行點擊,彈出對話框
3.3、前端使用 FormData 提交混合表單數據,包含普通字段和文件字段
3.4、文件對應數據庫結構類型為 image
3.5、Spring MVC 注解?@RequestPart、@ModelAttribute
2、應用效果
3、Vue3 前端
對話框表單?QualityFileInfoDialog.vue
<script setup lang="ts" name="QualityFileInfoDialog">
......
// 上傳,防抖
const onUploadClick = debounce(() => {// 模擬點擊元素if (fileInputRef.value) {// 重置以允許重復選擇相同文件fileInputRef.value.value = "";fileInputRef.value.click();}},1000,{ leading: true, trailing: true, maxWait: 1000 }
);// 點擊【上傳】觸發,實現 SQL Server image 類型文件上傳
const handleUpload = async (e: Event) => {// 打印 FormData 表單數據的內容// FormData對象不能直接通過 console.log(formData)輸出完整內容(控制臺僅顯示 FormData {}的抽象表示)// console.log("formData = ", formData);// 使用 Object.fromEntries()將 FormData 轉為普通對象,再通過 console.log 打印完整內容// const data = Object.fromEntries(formData.entries());// console.log(data);// 清空 FormData 表單數據的內容:遍歷刪除所有字段// formData.keys() 返回的迭代器會實時跟蹤 FormData的當前狀態。當調用 delete(key) 后,迭代器的內部指針可能因數據變化而跳過后續鍵。// 先將將迭代器轉為靜態數組,避免動態變化的影響// 使用 Array.from() 將迭代器轉為靜態數組// const keys = Array.from(formData.keys());// 使用 擴展運算符 將迭代器轉為靜態數組// const keys = [...formData.keys()];// for (let key of keys) {// formData.delete(key);// }// 清空 FormData 表單數據的內容:重新賦值,創建新實例,舊數據被丟棄(完全清空),需要使用 let 聲明對象,不能使用 const 聲明對象formData = new FormData();// 獲取文件對象const input = e.target as HTMLInputElement;if (!input.files?.length) return;const file = input.files[0];// 校驗文件大小if (file.size > 1024 * 1024 * 10) {ElMessage.warning("文件大小不能超過10MB");return;}if (file) {// 獲取文件名的擴展名(后綴)extension.value = getExtension(file.name);// 新增模式if (props.isNew) {if (upperCase(extension.value) === upperCase("pdf")) {// 將文件對象 file 添加到 formData 對象中,uploadFile 需要與后端接口中接收文件的參數名一致,如果不一致,則后端需要指定參數名,如 @RequestPart("uploadFile") MultipartFile fileformData.append("uploadFile", file);} else if (upperCase(extension.value) === upperCase("xls") || upperCase(extension.value) === upperCase("xlsx")) {// 將文件對象 file 添加到 formData 對象中,uploadFile 需要與后端接口中接收文件的參數名一致,如果不一致,則后端需要指定參數名,如 @RequestPart("uploadFile") MultipartFile fileformData.append("uploadFile", file);// 將普通對象 qualityFileObj 的屬性添加到 formData 對象中formData.append("fileNo", qualityFileObj.value.fileNo);formData.append("fileName", qualityFileObj.value.fileName);formData.append("edition", qualityFileObj.value.edition as string);formData.append("orderNo", qualityFileObj.value.orderNo as string);formData.append("issueDept", qualityFileObj.value.issueDept as string);formData.append("issueDate", qualityFileObj.value.issueDate as string);formData.append("smallCategory", qualityFileObj.value.smallCategory as string);formData.append("detailCategory", qualityFileObj.value.detailCategory as string);formData.append("modifyRecord", qualityFileObj.value.modifyRecord as string);formData.append("remark", qualityFileObj.value.remark as string);} else {// 將文件對象 file 添加到 formData 對象中,uploadFile 需要與后端接口中接收文件的參數名一致,如果不一致,則后端需要指定參數名,如 @RequestPart("uploadFile") MultipartFile fileformData.append("uploadFile", file);// 將普通對象 qualityFileObj 轉換為 json 字符串 添加到 formData 對象中formData.append("qualityFile", JSON.stringify(qualityFileObj.value));}}// 查改模式else {if (upperCase(extension.value) === upperCase("pdf")) {// 將文件對象 file 添加到 formData 對象中,uploadFile 需要與后端接口中接收文件的參數名一致,如果不一致,則后端需要指定參數名,如 @RequestPart("uploadFile") MultipartFile fileformData.append("uploadFile", file);// 無需點擊確定,直接發送請求,上傳文件到數據庫,實現 SQL Server image 類型文件上傳await qualityFileUploadFileWithPutService(qualityFileObj.value.fileNo, formData);} else {// 將文件對象 file 添加到 formData 對象中,uploadFile 需要與后端接口中接收文件的參數名一致,如果不一致,則后端需要指定參數名,如 @RequestPart("uploadFile") MultipartFile fileformData.append("uploadFile", file);// 將普通對象 qualityFileObj 的 fileNo 屬性添加到 formData 對象中formData.append("fileNo", qualityFileObj.value.fileNo);// 無需點擊確定,直接發送請求,上傳文件到數據庫,實現 SQL Server image 類型文件上傳await qualityFileUploadFileService(formData);}// 點擊【上傳/重傳】選擇文件后,上傳文件完成,通知父組件更新文件路徑名稱和是否空內容的操作emit("upload-file-complete", file.name);}// 同步更新表單數據qualityFileObj.value.filePathname = file.name;qualityFileObj.value.isNullContent = false;}
};// 確定
const onConfirmClick = async () => {// 檢查if (!check()) {return;}// 新增模式if (props.isNew) {if (upperCase(extension.value) === upperCase("pdf")) {// 發送請求,使用 put 發送請求,發送的數據有:請求體數據(文件數據 file),請求參數數據(普通對象數據 qualityFile)await qualityFileAddAttachUploadFileWithPutService(qualityFileObj.value, formData);} else if (upperCase(extension.value) === upperCase("xls") || upperCase(extension.value) === upperCase("xlsx")) {// 發送請求,使用 patch 發送請求,通過請求體發送表單數據 formData,表單數據,包含的數據有:文件數據(uploadFile)和// 普通對象的屬性數據(fileNo、fileName、edition、orderNo、issueDept、issueDate、smallCategory、detailCategory、modifyRecord、remark)await qualityFileAddAttachUploadFileWithPatchService(formData);} else {// 發送請求,使用 post 發送請求,通過請求體發送表單數據 formData,表單數據,包含的數據有:文件數據(uploadFile)和 普通對象的json字符串數據(qualityFile)await qualityFileAddAttachUploadFileService(formData);}}// 查改模式else {// 兩個對象不相同,需要更新數據;如果兩個對象相同(所有屬性值都相同),不需要更新數據if (!isEqual(props.qualityFileInfo, qualityFileObj.value)) {// 點擊【確定】,確定質量體系文件信息,通知父組件執行相應的操作emit("confirm-quality-file", qualityFileObj.value);}}dialogVisible.value = false;
};
......
</script><template><el-dialogclass="quality-file-dialog"title="基礎信息"width="640px"top="0vh"centerstyle="border-radius: 10px"v-model="dialogVisible":close-on-press-escape="true":close-on-click-modal="false":show-close="true"@close="onCancelClick"><template #default><el-form :model="qualityFileObj" label-width="auto" style="margin: 8px 16px"><el-row :gutter="10"><el-col :span="12"><el-form-item label="序號" label-position="right"><el-input v-model="qualityFileObj.orderNo" clearable /></el-form-item></el-col><el-col :span="12"><el-form-item label="文件編號" label-position="right"><el-input v-model="qualityFileObj.fileNo" clearable :disabled="!props.isNew" /></el-form-item></el-col></el-row><el-row :gutter="10"><el-col :span="24"><el-form-item label="文件名稱" label-position="right"><el-input v-model="qualityFileObj.fileName" clearable /></el-form-item></el-col></el-row><el-row :gutter="10"><el-col :span="12"><el-form-item label="版本號" label-position="right"><el-input v-model="qualityFileObj.edition" clearable /></el-form-item></el-col><el-col :span="12"><el-form-item label="修改記錄" label-position="right"><el-input v-model="qualityFileObj.modifyRecord" clearable /></el-form-item></el-col></el-row><el-row :gutter="10"><el-col :span="12"><el-form-item label="所屬小類" label-position="right"><el-selectv-model="qualityFileObj.smallCategory"placeholder="請選擇"clearable@clear="handleSmallCategoryClear"><el-option v-for="item in fileSmallCategoryList" :label="item.label" :value="item.value" /></el-select></el-form-item></el-col><el-col :span="12"><el-form-item label="所屬類別" label-position="right"><el-selectv-model="qualityFileObj.detailCategory"placeholder="請選擇"clearablefilterabledefault-first-option><el-option v-for="item in fileDetailCategoryList" :label="item.label" :value="item.label" /></el-select></el-form-item></el-col></el-row><el-row :gutter="10"><el-col :span="12"><el-form-item label="發布部門" label-position="right"><el-selectv-model="qualityFileObj.issueDept"placeholder="請選擇"clearablefilterableallow-createdefault-first-option:value-on-clear="``"><el-option v-for="item in departmentList" :label="item.deptName" :value="item.deptName" /></el-select></el-form-item></el-col><el-col :span="12"><el-form-item label="發布日期" label-position="right"><el-date-pickerv-model="qualityFileObj.issueDate"type="date"format="YYYY-MM-DD"value-format="YYYY-MM-DD"clearablestyle="width: 100%" /></el-form-item></el-col></el-row><el-row :gutter="10"><el-col :span="24"><el-form-item label="備注" label-position="right"><el-input v-model="qualityFileObj.remark" clearable /></el-form-item></el-col></el-row><el-row :gutter="10"><el-col :span="15"><el-form-item label="附件" label-position="right"><el-input class="input-readonly" v-model="qualityFileObj.filePathname" readonly /></el-form-item></el-col><el-col :span="9"><el-form-item label="" label-position="right"><BasePreventReClickButton type="primary" plain :loading="false" @click="onUploadClick">{{qualityFileObj.isNullContent ? "上傳" : "重傳"}}</BasePreventReClickButton><BasePreventReClickButton:loading="false":disabled="qualityFileObj.isNullContent"@click="onDownloadClick">下載</BasePreventReClickButton><BasePreventReClickButtontype="danger"plain:loading="false":disabled="qualityFileObj.isNullContent"@click="onClearClick">清除</BasePreventReClickButton><!-- 文件輸入元素,不顯示,通過點擊按鈕【上傳/重傳】執行 onUploadClick,模擬點擊該元素,從而觸發 handleUpload 事件 --><input ref="fileInputRef" type="file" style="display: none" @change="handleUpload" /></el-form-item></el-col></el-row></el-form></template><!-- 模態框底部插槽,就算沒有內容,也要寫一個空的插槽,否則會影響布局 --><template #footer><div class="footer-div"><BasePreventReClickButton class="btn" type="primary" @click="onConfirmClick">確定</BasePreventReClickButton><el-button class="btn" @click="onCancelClick">取消</el-button></div></template></el-dialog>
</template><style scoped lang="scss">
.el-form {margin: 0 15px;
}// 設置等同于disabled的樣式效果,背景色 #f5f7fa,字體顏色 #c0c4cc
// 設置類名為 input-readonly 的元素的背景顏色
.input-readonly :deep(.el-input__wrapper) {background-color: #f5f7fa;
}
// 設置只讀的input的字體顏色,不使用類名,使用類屬性選擇器(.類名[屬性名])
:deep(.el-input__inner[readonly]) {color: #c0c4cc;
}
</style>
qualityFile.ts
import request from "@/utils/request";
import type { IQualityFile, IQualityFileQueryObj } from "@/views/resources/QualityFile/types";/*** 新增質量體系文件信息,附帶上傳文件,使用 put 發送請求,發送的數據有:請求體數據(文件數據 uploadFile),請求參數數據(普通對象數據 qualityFile)* @param qualityFile 質量體系文件信息 {@link IQualityFile}* @param formData 表單數據,包含的數據只有:文件數據(uploadFile) {@link FormData}* @returns*/
export const qualityFileAddAttachUploadFileWithPutService = (qualityFile: IQualityFile, formData: FormData) => {// 發送請求,發送的數據有:請求體數據(文件數據 uploadFile),請求參數數據(普通對象數據 qualityFile)return request.put("/resources/qualityFile/addAttachUploadFile", formData, {params: qualityFile,// 上傳文件,需設置 headers 信息,將"Content-Type"設置為"multipart/form-data"headers: {"Content-Type": "multipart/form-data"}});
};/*** 新增質量體系文件信息,附帶上傳文件,使用 patch 發送請求,通過請求體發送表單數據 formData* @param formData 表單數據,包含的數據有:文件數據(uploadFile)和* 普通對象的屬性數據(fileNo、fileName、edition、orderNo、issueDept、issueDate、smallCategory、detailCategory、modifyRecord、remark) {@link FormData}* @returns*/
export const qualityFileAddAttachUploadFileWithPatchService = (formData: FormData) => {return request.patch("/resources/qualityFile/addAttachUploadFile", formData, {// 上傳文件,需設置 headers 信息,將"Content-Type"設置為"multipart/form-data"headers: {"Content-Type": "multipart/form-data"}});
};/*** 新增質量體系文件信息,附帶上傳文件,使用 post 發送請求,通過請求體發送表單數據 formData* @param formData 表單數據,包含的數據有:文件數據(uploadFile)和 普通對象的json字符串數據(qualityFile) {@link FormData}* @returns*/
export const qualityFileAddAttachUploadFileService = (formData: FormData) => {return request.post("/resources/qualityFile/addAttachUploadFile", formData, {// 上傳文件,需設置 headers 信息,將"Content-Type"設置為"multipart/form-data"headers: {"Content-Type": "multipart/form-data"}});
};
4、Spring Boot 后端
DTO?
QualityFile.java
package com.weiyu.pojo;import com.fasterxml.jackson.annotation.JsonFormat;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;import java.time.LocalDate;/*** 質量體系文件*/
@Schema(description = "質量體系文件實體")
@Data
@AllArgsConstructor
@NoArgsConstructor
public class QualityFile {@Schema(description = "文件唯一標識 id", example = "1")private Integer id;@Schema(description = "序號", example = "A00")private String orderNo;@Schema(description = "文件編號", example = "CZCDC/QM-2024-A0")private String fileNo;@Schema(description = "文件名稱", example = "質量手冊(封面)")private String fileName;@Schema(description = "版本號", example = "第9版")private String edition;@Schema(description = "修改記錄", example = "第9版第0次修改")private String modifyRecord;@Schema(description = "所屬小類", example = "3003")private String smallCategory;@Schema(description = "所屬類別", example = "第九版")private String detailCategory;@Schema(description = "發布部門", example = "質量管理科")private String issueDept;@Schema(description = "發布日期", example = "2025-08-16")@JsonFormat(pattern = "yyyy-MM-dd")private LocalDate issueDate;@Schema(description = "備注", example = " ")private String remark;@Schema(description = "文件路徑名稱", example = "CZCDC∕QM-2018-B2 4.2 人員vVv+DW=dw.doc")private String filePathname;@Schema(description = "是否空內容", example = "true")private Boolean isNullContent;
}
QualityFileDTO.java
package com.weiyu.pojo;import com.fasterxml.jackson.annotation.JsonFormat;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;import java.time.LocalDate;/*** 質量體系文件 DTO*/
@Schema(description = "質量體系文件 DTO")
@Data
@AllArgsConstructor
@NoArgsConstructor
public class QualityFileDTO {@Schema(description = "序號", example = "A00")private String orderNo;@Schema(description = "文件編號", example = "CZCDC/QM-2024-A0")private String fileNo;@Schema(description = "文件名稱", example = "質量手冊(封面)")private String fileName;@Schema(description = "版本號", example = "第9版")private String edition;@Schema(description = "修改記錄", example = "第9版第0次修改")private String modifyRecord;@Schema(description = "所屬小類", example = "3003")private String smallCategory;@Schema(description = "所屬類別", example = "第九版")private String detailCategory;@Schema(description = "發布部門", example = "質量管理科")private String issueDept;@Schema(description = "發布日期", example = "2025-08-16")@JsonFormat(pattern = "yyyy-MM-dd")private LocalDate issueDate;@Schema(description = "備注", example = " ")private String remark;
}
控制層?QualityFileController.java
package com.weiyu.controller;import com.alibaba.fastjson.JSON;
import com.weiyu.anno.Debounce;
import com.weiyu.pojo.QualityFile;
import com.weiyu.pojo.QualityFileDTO;
import com.weiyu.pojo.QualityFileQueryDTO;
import com.weiyu.pojo.Result;
import com.weiyu.service.QualityFileService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.core.io.Resource;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;import java.io.IOException;
import java.util.List;/*** 質量體系文件 Controller*/
@RestController
@RequestMapping("/resources/qualityFile")
@Slf4j
public class QualityFileController {@Autowiredprivate QualityFileService qualityFileService;/*** 新增質量體系文件,附帶上傳文件,使用 @PutMapping 接收請求,@ModelAttribute 接收參數* @ ModelAttribute是 Spring MVC 中處理復雜數據綁定和模型管理的核心注解,尤其適合表單操作和共享數據場景,能顯著減少樣板代碼* 將 HTTP 請求參數(如表單字段、查詢參數)自動綁定到 Java 對象的屬性上* 示例說明:* 如果查詢參數有fileNo為A1,表單字段也有fileNo為B2,那么qualityFile中的fileNo為B2,A1,即先獲取表單字段,再獲取查詢參數,中間使用逗號分隔* MultipartFile參數名稱說明:* 因為前端使用 formData.append("uploadFile", file) 用的參數名稱是 uploadFile* 后端這里使用 uploadFile 與前端一致,可以不使用 @RequestPart("uploadFile"),也可以使用* @param qualityFile 質量體系文件 {@link QualityFile}* @param uploadFile 上傳文件 {@link MultipartFile}*/@PutMapping("/addAttachUploadFile")public Result<?> addAttachUploadFile(@ModelAttribute QualityFile qualityFile,MultipartFile uploadFile) throws IOException {log.info("【質量體系文件】,新增附帶上傳文件,使用 @PutMapping 接收請求,@ModelAttribute 接收參數," +"/resources/qualityFile/addAttachUploadFile,qualityFile = {},uploadFile = {}", qualityFile, uploadFile);qualityFileService.addAttachUploadFile(qualityFile, uploadFile);return Result.success();}/*** 新增質量體系文件,附帶上傳文件,使用 @PatchMapping 接收請求,@ModelAttribute 接收參數* @ ModelAttribute是 Spring MVC 中處理復雜數據綁定和模型管理的核心注解,尤其適合表單操作和共享數據場景,能顯著減少樣板代碼* 將 HTTP 請求參數(如表單字段、查詢參數)自動綁定到 Java 對象的屬性上* 示例說明:* 如果查詢參數有fileNo為A1,表單字段也有fileNo為B2,那么qualityFile中的fileNo為B2,A1,即先獲取表單字段,再獲取查詢參數,中間使用逗號分隔* MultipartFile參數名稱說明:* 因為前端使用 formData.append("uploadFile", file) 用的參數名稱是 uploadFile* 后端這里使用 uploadFile 與前端一致,可以不使用 @RequestPart("uploadFile"),也可以使用* @param qualityFileDTO 質量體系文件 DTO {@link QualityFileDTO}* @param uploadFile 上傳文件 {@link MultipartFile}*/@PatchMapping("/addAttachUploadFile")public Result<?> addAttachUploadFile(@ModelAttribute QualityFileDTO qualityFileDTO,MultipartFile uploadFile) throws IOException {log.info("【質量體系文件】,新增附帶上傳文件,使用 @PatchMapping 接收請求,@ModelAttribute 接收參數," +"/resources/qualityFile/addAttachUploadFile,qualityFileDTO = {},uploadFile = {}", qualityFileDTO, uploadFile);QualityFile qualityFile = new QualityFile();qualityFile.setFileNo(qualityFileDTO.getFileNo());qualityFile.setFileName(qualityFileDTO.getFileName());qualityFile.setEdition(qualityFileDTO.getEdition());qualityFile.setOrderNo(qualityFileDTO.getOrderNo());qualityFile.setIssueDept(qualityFileDTO.getIssueDept());qualityFile.setIssueDate(qualityFileDTO.getIssueDate());qualityFile.setSmallCategory(qualityFileDTO.getSmallCategory());qualityFile.setDetailCategory(qualityFileDTO.getDetailCategory());qualityFile.setModifyRecord(qualityFileDTO.getModifyRecord());qualityFile.setRemark(qualityFileDTO.getRemark());qualityFileService.addAttachUploadFile(qualityFile, uploadFile);return Result.success();}/*** 新增質量體系文件,附帶上傳文件,使用 @PostMapping 接收請求,@RequestPart 接收參數* @ RequestPart是 Spring MVC 中處理 multipart 請求的靈活工具,尤其適合文件與結構化數據混合提交的場景,簡化了數據綁定與異常處理* MultipartFile參數名稱說明:* 因為前端使用 formData.append("uploadFile", file) 用的參數名稱是 uploadFile* 后端這里使用 uploadFile 與前端一致,可以使用 @RequestPart("uploadFile"),也可以不使用* String參數名稱說明:* 因為前端使用 formData.append("qualityFile", JSON.stringify(qualityFileObj.value)) 用的參數名稱是 qualityFile* 后端這里使用 qualityFileJsonString 與前端不一致,必須使用 @RequestPart("qualityFile") 映射參數名稱* @param qualityFileJsonString 質量體系文件json字符串* @param uploadFile 上傳文件 {@link MultipartFile}*/@PostMapping("/addAttachUploadFile")public Result<?> addAttachUploadFile(@RequestPart("qualityFile") String qualityFileJsonString,@RequestPart("uploadFile") MultipartFile uploadFile) throws IOException {log.info("【質量體系文件】,新增附帶上傳文件,使用 @PostMapping 接收請求,@RequestPart 接收參數," +"/resources/qualityFile/addAttachUploadFile,qualityFileJsonString = {},uploadFile = {}",qualityFileJsonString, uploadFile);// json字符串 轉換成 java對象(QualityFile)QualityFile qualityFile = JSON.parseObject(qualityFileJsonString, QualityFile.class);qualityFileService.addAttachUploadFile(qualityFile, uploadFile);return Result.success();}
}
服務層?QualityFileServiceImpl.java
package com.weiyu.service.impl;import com.weiyu.mapper.QualityFileMapper;
import com.weiyu.pojo.FileData;
import com.weiyu.pojo.QualityFile;
import com.weiyu.pojo.QualityFileQueryDTO;
import com.weiyu.service.QualityFileService;
import com.weiyu.utils.FileDownloadUtil;
import jakarta.validation.constraints.NotNull;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.core.io.Resource;
import org.springframework.http.ResponseEntity;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.multipart.MultipartFile;import java.io.IOException;
import java.util.ArrayList;
import java.util.List;/*** 質量體系文件 Service 接口實現*/
@Service
public class QualityFileServiceImpl implements QualityFileService {@Autowiredprivate QualityFileMapper qualityFileMapper;/*** 查詢質量體系文件列表** @param queryDTO 查詢 DTO* @return 質量體系文件列表*/@Overridepublic List<QualityFile> query(QualityFileQueryDTO queryDTO) {if (queryDTO == null) return new ArrayList<>();return qualityFileMapper.select(queryDTO);}/*** 新增質量體系文件** @param qualityFile 質量體系文件*/@Overridepublic void add(QualityFile qualityFile) {qualityFileMapper.insert(qualityFile);}/*** 上傳質量體系文件** @param fileNo 文件編號* @param uploadFile 上傳文件*/@Overridepublic void uploadFile(String fileNo, MultipartFile uploadFile) throws IOException {FileData fileData = new FileData();fileData.setFileName(uploadFile.getOriginalFilename());fileData.setFileContent(uploadFile.getBytes());// todo: 如果是大文件(超過10MB)保存到文件系統,數據庫只保存文件路徑;否則保存到數據庫// 保存文件到數據庫qualityFileMapper.saveFile(fileNo, fileData);}/*** 新增質量體系文件,附帶上傳文件** @param qualityFile 質量體系文件* @param uploadFile 上傳文件*/@Override@Transactionalpublic void addAttachUploadFile(QualityFile qualityFile, MultipartFile uploadFile) throws IOException {// 新增質量體系文件add(qualityFile);// 上傳質量體系文件uploadFile(qualityFile.getFileNo(), uploadFile);}
}
Mapper?QualityFileMapper.java
package com.weiyu.mapper;import com.weiyu.pojo.FileData;
import com.weiyu.pojo.QualityFile;
import com.weiyu.pojo.QualityFileQueryDTO;
import org.apache.ibatis.annotations.Mapper;import java.util.List;/*** 質量體系文件 Mapper*/
@Mapper
public interface QualityFileMapper {/*** 查詢質量體系文件列表* @param queryDTO 查詢 DTO* @return 質量體系文件列表*/List<QualityFile> select(QualityFileQueryDTO queryDTO);/*** 新增質量體系文件* @param qualityFile 質量體系文件*/void insert(QualityFile qualityFile);/*** 保存質量體系文件數據到數據庫* @param fileNo 文件編號* @param fileData 上傳文件*/void saveFile(String fileNo, FileData fileData);
}
數據庫sql操作?QualityFileMapper.xml
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapperPUBLIC "-//mybatis.org//DTD Mapper 3.0//EN""http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.weiyu.mapper.QualityFileMapper"><!--mssql--><!-- 查詢質量體系文件列表 --><select id="select" resultType="com.weiyu.pojo.QualityFile">selectCfm_OrderID as orderNo, Cfm_ID as fileNo, Cfm_Name as fileName, Cfm_Edition as edition,Cfm_ModifyRecord as modifyRecord, Cfm_SmallType as smallCategory, Cfm_SampleType as detailCategory,Cfm_Dept as issueDept, Cfm_IssueDate as issueDate, Cfm_Memo as remark,cfm_ContentFileName as filePathname, cfm_ContentIsNull as isNullContentfrom ControledFileMain<where>Cfm_BigType = '3'<if test="fileNo != null and fileNo != ''">and Cfm_ID like '%' + #{fileNo} + '%'</if><if test="fileName != null and fileName != ''">and Cfm_Name like '%' + #{fileName} + '%'</if></where>order by Cfm_SmallType, Cfm_ID</select><!-- 新增質量體系文件 --><insert id="insert">insert into ControledFileMain(Cfm_BigType, Cfm_OrderID, Cfm_ID, Cfm_Name, Cfm_Edition,Cfm_ModifyRecord, Cfm_SmallType, Cfm_SampleType,Cfm_Dept, Cfm_IssueDate, Cfm_Memo)values ('3', #{orderNo}, #{fileNo}, #{fileName}, #{edition},#{modifyRecord}, #{smallCategory}, #{detailCategory},#{issueDept}, #{issueDate}, #{remark})</insert><!-- 保存質量體系文件數據到數據庫 --><update id="saveFile">update ControledFileMain setcfm_ContentFileName = #{fileData.fileName}, cfm_Content = #{fileData.fileContent}, cfm_ContentIsNull = 0where Cfm_BigType = '3' and Cfm_ID = #{fileNo}</update>
</mapper>
5、數據庫表結構(sql server)
CREATE TABLE [dbo].[ControledFileMain]([Cfm_ID] [varchar](30) NOT NULL,[Cfm_Name] [varchar](200) NULL,[Cfm_BigType] [varchar](10) NOT NULL,[Cfm_SmallType] [varchar](10) NULL,[Cfm_Dept] [varchar](50) NULL,[Cfm_Memo] [varchar](100) NULL,[Cfm_ModifyRecord] [varchar](128) NULL,[Cfm_Edition] [varchar](50) NULL,[Cfm_IssueDate] [datetime] NULL,[Cfm_SampleType] [varchar](50) NULL,[Cfm_StandardType] [int] NULL,[Cfm_OrderID] [varchar](10) NULL,[Cfm_Holder] [varchar](50) NULL,[cfm_Content] [image] NULL,[cfm_ContentIsNull] [bit] NULL,[cfm_ContentFileName] [varchar](255) NULL,CONSTRAINT [PK_ControledFileMain] PRIMARY KEY CLUSTERED
([Cfm_ID] ASC
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY]
) ON [PRIMARY] TEXTIMAGE_ON [PRIMARY]GO