Upload 上传(图片/文件),回显(图片),下载(文件)
1.前���技术:V3 + Ant Design Vue
2.后端技术:Java
图片上传/回显:
文件上传回显:
表结构:单文件/图片上传为A表对文件C表 (A表field字段 对应 C表id字段)
如图:A表中的 vehicle_driving_license 和 driver_license 存的是C表中的id字段
表结构:多文件/图片上传为A表对文件B表 中的Biz字段,B表中的file_id字段对应C表中的id字段,(B表的 Biz 字段和 file_id 字段是一对多的存在关系)
如图:A表中的 house_type_file_id 和 house_type_balcony_close_file_id 、house_type_balcony_bisect_file_id、house_type_shearwall_file_id 存的是B表中的Biz_id字段,B表中的 field_id 字段对应 C表中的 id 字段,(B表中的Biz_id字段 与 field_id 字段是一对多的关系)
上传:(上传功能不分单个多个)java后台代码(controller):
@OperationLog @ApiOperation("上传文件") @PostMapping("/upload") public ApiResult upload(@RequestParam MultipartFile file, HttpServletRequest request) { FileInfo result = null; try { String dir = getUploadDir(); File upload = FileServerUtil.upload(file, dir, config.getUploadUuidName()); String path = upload.getAbsolutePath().replace("\", "/").substring(dir.length() - 1); String requestURL = StrUtil.removeSuffix(request.getRequestURL(), "/upload"); requestURL = "/api/file-info/file/"; String requestURL2 = "/api/file-info"; /*if(requestURL.contains("10.1.140.88")){ requestURL = "https://10.1.140.88/api/file"; } if(requestURL.contains("djshemei.com")){ requestURL = "https://10.1.140.88/api/file"; }*/ String originalName = file.getOriginalFilename(); result = new FileInfo(); result.setId(SnowFlakeGenerator.nextId()); String contentType = FileServerUtil.getContentType(upload); result.setFileType(contentType); result.setFileName(StrUtil.isBlank(originalName) ? upload.getName() : originalName); result.setFilePath(path); result.setUrlPath(requestURL+result.getId()); result.setUrl(requestURL2 + "/" + path); //这个用户应该是这个找登录用户 User loginUser = getLoginUser(); result.setCreUserId(Long.valueOf(loginUser.getUserId())); result.setCreUserName(loginUser.getUsername()); result.setCreateTime(LocalDateTime.now()); fileInfoService.save(result); return success(result); } catch (Exception e) { e.printStackTrace(); return fail("上传失败", result).setError(e.toString()); } }
前端:api代码:
/** * 上传文件 */ export async function uploadFile(file, opt) { const formData = new FormData(); formData.append('file', file); const res = await request.post('/community/file-info/upload', formData, opt); if (res.data.code === 0 && res.data.data) { return res.data.data; } return Promise.reject(new Error(res.data.message)); }
在页面引入使用
使用方法:
const onUpload1 = ({ file }) => { uploadFile(file) .then((data) => { console.log(data, 'data'); form1.vehicleDrivingLicenseFieldId1 = data.id; }) .catch((e) => { item.status = 'exception'; message.error(e.message); }); };
数据结构:
// 图片 const form1 = reactive({ vehicleDrivingLicenseField: [], vehicleDrivingLicenseFieldId1: '', driverLicenseField: [], driverLicenseFieldId2: '' });
图片回显:java代码 (controller)
@ApiOperation("查询文件") @GetMapping("/queryFile/{id}") public ApiResult getFileInfoByRoomCar (@PathVariable("id") Long id, HttpServletRequest request ) { List roomCarServiceList = roomCarService.list(new QueryWrapper().eq("car_id", id)); if(roomCarServiceList.size() == 0){ return success(new ArrayList()); }else{ List fileIdList = fileInfoService.list(new QueryWrapper().in("id", roomCarServiceList.stream().map(RoomCar::getVehicleDrivingLicense).collect(Collectors.toList()))); if (fileIdList.size() > 0) { String requestURL = StrUtil.removeSuffix(request.getRequestURL(), "/room-car/queryFile/"+id); for (FileInfo record : fileIdList) { if (StrUtil.isNotBlank(record.getFilePath())) { record.setDownloadUrl(requestURL + "/file-info/" + record.getFilePath()); record.setUrl(requestURL + "/file-info/" + record.getFilePath()); } } } List fileIdList1 = fileInfoService.list(new QueryWrapper().in("id", roomCarServiceList.stream().map(RoomCar::getDriverLicense).collect(Collectors.toList()))); if (fileIdList1.size() > 0) { String requestURL = StrUtil.removeSuffix(request.getRequestURL(), "/room-car/queryFile/"+id); for (FileInfo record : fileIdList1) { if (StrUtil.isNotBlank(record.getFilePath())) { record.setDownloadUrl(requestURL + "/file-info/" + record.getFilePath()); record.setUrl(requestURL + "/file-info/" + record.getFilePath()); } } } HashMap data = new HashMap(); data.put("vehicleDrivingLicenseField", fileIdList); data.put("driverLicenseField", fileIdList1); return success(data); } }
前端api:
export async function queryItem(id) { const res = await request.get('/community/decoration-manage/queryFile/' + id); if (res.data.code === 0) { return res.data; } return Promise.reject(new Error(res.data.message)); }
页面引入使用:
watch( () => props.visible, (visible) => { if (visible) { if (props.data) { assignObject(form, { ...props.data }); isUpdate.value = true; showFile.value = true; changeRoomType(props.data.roomTypeId); // driverLicense // vehicleDrivingLicense queryItem(props.data.carId) .then((res) => { form1.vehicleDrivingLicenseField = res.data.vehicleDrivingLicenseField; form1.driverLicenseField = res.data.driverLicenseField; }) .catch((e) => { message.error(e.message); }); loadingData(); } else { showFile.value = false; isUpdate.value = false; loadingData(); } } else { form1.vehicleDrivingLicenseField = []; form1.driverLicenseField = []; resetFields(); } } );
多文件上传跟单文件上传一样的,不一样的是显示的方式:
多文件回显后端 Java代码(controller):
@ApiOperation("查询文件") @GetMapping("/queryFile/{id}") public ApiResult getFileInfoByRegionalHouseTypeId(@PathVariable("id") Long id, HttpServletRequest request ) { BaseRegionalHouseType mainRec = baseRegionalHouseTypeService.getByIdRel(id); List house_type_file = new ArrayList(); List house_type_balcony_close_file = new ArrayList(); List house_type_balcony_bisect_file = new ArrayList(); List house_type_shearwall_file = new ArrayList(); Long bizId; bizId = mainRec.getHouseTypeFileId(); if (bizId != null) { house_type_file = fileInfoService.getfileinfobybiz(bizId); String requestURL = StrUtil.removeSuffix(request.getRequestURL(), "/base-regional-house-type/queryFile/"+id); for (FileInfo record : house_type_file) { if (StrUtil.isNotBlank(record.getFilePath())) { record.setDownloadUrl(requestURL + "/file-info/download/" + record.getFilePath()); } } } bizId = mainRec.getHouseTypeBalconyCloseFileId(); if (bizId != null) { house_type_balcony_close_file = fileInfoService.getfileinfobybiz(bizId); String requestURL = StrUtil.removeSuffix(request.getRequestURL(), "/base-regional-house-type/queryFile/"+id); for (FileInfo record : house_type_balcony_close_file) { if (StrUtil.isNotBlank(record.getFilePath())) { record.setDownloadUrl(requestURL + "/file-info/download/" + record.getFilePath()); } } } bizId = mainRec.getHouseTypeBalconyBisectFileId(); if (bizId != null) { house_type_balcony_bisect_file = fileInfoService.getfileinfobybiz(bizId); String requestURL = StrUtil.removeSuffix(request.getRequestURL(), "/base-regional-house-type/queryFile/"+id); for (FileInfo record : house_type_balcony_bisect_file) { if (StrUtil.isNotBlank(record.getFilePath())) { record.setDownloadUrl(requestURL + "/file-info/download/" + record.getFilePath()); } } } bizId = mainRec.getHouseTypeShearwallFileId(); if (bizId != null) { house_type_shearwall_file = fileInfoService.getfileinfobybiz(bizId); String requestURL = StrUtil.removeSuffix(request.getRequestURL(), "/base-regional-house-type/queryFile/"+id); for (FileInfo record : house_type_shearwall_file) { if (StrUtil.isNotBlank(record.getFilePath())) { record.setDownloadUrl(requestURL + "/file-info/download/" + record.getFilePath()); } } } HashMap data = new HashMap(); data.put("house_type_file", house_type_file); data.put("house_type_balcony_close_file", house_type_balcony_close_file); data.put("house_type_balcony_bisect_file", house_type_balcony_bisect_file); data.put("house_type_shearwall_file", house_type_shearwall_file); return success(data); }
前端api:
export async function queryHouse(id) { const res = await request.get('/community/base-regional-house-type/queryFile/' + id); if (res.data.code === 0) { return res.data; } return Promise.reject(new Error(res.data.message)); }
页面使用:
文件上传 户型图 封闭阳台方案 封闭阳台剖面图 剪力墙标识图 上传 下载 删除
import { ref, watch, onMounted } from 'vue'; import { getfileinfobybiz, uploadFile, removeFile } from '@/api/system/file-info'; import useFormData from '@/utils/use-form-data'; import { Form, message } from 'ant-design-vue/es'; import { messageLoading } from 'ele-admin-pro/es'; import { saveHouse, queryHouse } from '@/api/baseRegionalPark/base-regional-house-type'; import { CloudUploadOutlined, FileTextOutlined } from '@ant-design/icons-vue'; // import FileUpload from './file-upload.vue'; const emit = defineEmits(['done', 'update:visible']); const useForm = Form.useForm; const props = defineProps({ data: Object, visible: Boolean }); // 表单 const { form, resetFields, assignFields } = useFormData({ regionalHouseTypeId: '', // 户型图id houseTypeFileId: '', // 封闭阳台方案id houseTypeBalconyCloseFileId: '', // 封闭阳台剖面图id houseTypeBalconyBisectFileId: '', // 剪力墙标识图id houseTypeShearwallFileId: '', house_type_file: [], house_type_balcony_close_file: [], house_type_balcony_bisect_file: [], house_type_shearwall_file: [] }); // 按钮颜色 const btn = ref(0); // 确定数据 const datas = ref({ regionalHouseTypeId: '', house_type_file: [], house_type_balcony_close_file: [], house_type_balcony_bisect_file: [], house_type_shearwall_file: [], downloadUrl:"", // 户型图id houseTypeFileId: '', // 封闭阳台方案id houseTypeBalconyCloseFileId: '', // 封闭阳台剖面图id houseTypeBalconyBisectFileId: '', // 剪力墙标识图id houseTypeShearwallFileId: '', }); const typeclick = (type) => { switch (type) { case 0: btn.value = 0; datasource.value = datas.value.house_type_file; break; case 1: btn.value = 1; datasource.value = datas.value.house_type_balcony_close_file; break; case 2: btn.value = 2; datasource.value = datas.value.house_type_balcony_bisect_file; break; case 3: btn.value = 3; datasource.value = datas.value.house_type_shearwall_file; break; } }; const findPicIds = ref([]); // 表格实例 const tableRef = ref(null); // 导入请求状态 const loading = ref(false); const isAdmin = ref(false); // 保存按钮 const save = () => { saveHouse(datas.value).then((res) => { if (res.code == 0) { message.success('保存成功'); emit('done'); emit('update:visible', false); } else { message.error(res.msg); } }); }; // 表格列配置 const columns = ref([ { title: '序号', key: 'index', width: 48, align: 'center', fixed: 'left', hideInSetting: true, customRender: ({ index }) => index + (tableRef.value?.tableIndex ?? 0) }, { title: '文件名', dataIndex: 'fileName' }, { title: '文件类型', dataIndex: 'fileType' }, { title: '创建人', dataIndex: 'creUserName' }, { title: '创建时间', dataIndex: 'createTime' }, { title: '操作', key: 'action', width: 160, align: 'center', hideInSetting: true } ]); //上传文件 const onUploadCardf = (d) => { uploadFile(d.file, { onUploadProgress: (e) => { if (e.lengthComputable) { d.progress = (e.loaded / e.total) * 100; } } }) .then((data) => { d.status = 'done'; if (btn.value == 0) { datas.value.house_type_file.push(data); } else if (btn.value == 1) { datas.value.house_type_balcony_close_file.push(data); } else if (btn.value == 2) { datas.value.house_type_balcony_bisect_file.push(data); } else if (btn.value == 3) { datas.value.house_type_shearwall_file.push(data); } message.success('上传成功'); }) .catch((e) => { message.error(e.message); }); }; // /* 删除单个 */ const remove = (row, index) => { const hide = message.loading('请求中..', 0); removeFile(row.id) .then((msg) => { var arr = []; if(btn.value ==0 ){ arr = datas.value.house_type_file.filter((d) => d.id != row.id); datas.value.house_type_file = arr; } if(btn.value ==1 ){ arr = datas.value.house_type_balcony_close_file.filter((d) => d.id != row.id); datas.value.house_type_balcony_close_file = arr; } if(btn.value ==2 ){ arr = datas.value.house_type_balcony_bisect_file.filter((d) => d.id != row.id); datas.value.house_type_balcony_bisect_file = arr; } if(btn.value ==3 ){ arr = datas.value.house_type_shearwall_file.filter((d) => d.id != row.id); datas.value.house_type_shearwall_file = arr; } typeclick(btn.value); hide(); message.success(msg); }) .catch((e) => { hide(); message.error(e.message); }); }; // // 表格数据源 const datasource = ref([]); /* 更新visible */ const updateVisible = (value) => { emit('update:visible', value); }; watch( () => props.visible, (visible) => { if (visible) { if (!props.data) { alert('数据为空,请确保传递正确数据'); return; } console.log(props.data); datas.value.regionalHouseTypeId = props.data.regionalHouseTypeId; queryHouse(datas.value.regionalHouseTypeId).then((res) => { datas.value.house_type_file = res.data.house_type_file; datas.value.house_type_balcony_close_file = res.data.house_type_balcony_close_file; datas.value.house_type_balcony_bisect_file = res.data.house_type_balcony_bisect_file; datas.value.house_type_shearwall_file = res.data.house_type_shearwall_file; // 默认选中第一个 typeclick(0); }); } } ); // .ele-body { // height: 100%; // } .btnColor { background-color: #f4fbf8; color: #1677ff; } .content { display: flex; .loudong { width: 280px; margin-right: 15px; padding: 15px; // height: 80vh; background: #fff; overflow: auto; box-sizing: border-box; } .search { width: 100%; padding: 20px 10px 0px 20px; background: #f6f5f5; margin-bottom: 5px; } .content-right { flex: 1; } }
还有一个小细节,java存储文件id的字段一定不要忽略修改的时候传来的null
用注解:
@TableField(updateStrategy = FieldStrategy.IGNORED)
就ok啦,暂时先做个笔记,后面有空再慢慢写注解
The End