需要到达的效果
1、点击上传显示弹窗,并成功添加文件,且支持多文件多格式上传
2、点击确定按钮,文件成功保存至本地目录,并且将文件信息保存至数据库
- 由于我们并没有设置表单内容也没有做表单规则,点击下载文件可展开文件列表
3、点击下载文件,文件能下载至本地
文件上传代码代码实现
1、前端,由于我们使用的是elementUI,下面我们贴上代码
// 引入方法
import {
listTreatment,
getTreatment,
delTreatment,
addTreatment,
updateTreatment,
exportTreatment
} from "@/api/hospital/treatment";
// 上传参数
data() {
return {
// 非多个禁用
multiple: true,
// 文件下载列表
dataFileList: [],
// 表单参数
form: {},
// 表单校验
rules: {},
// 上传参数
upload: {
// 是否禁用上传
isUploading: false,
// 设置上传的请求头部
headers: {Authorization: "Bearer " + getToken()},
// 上传的地址
url: process.env.VUE_APP_BASE_API + "/system/treatment/upload",
// 上传的文件列表
fileList: []
},
};
},
<el-dialog :title="title" :visible.sync="open" width="900px" append-to-body>
<el-form ref="form" :model="form" :rules="rules" label-width="80px">
<el-form-item label="请选择方案" label-width="100px">
<el-upload
ref="upload"
action=""
:on-remove="handleRemove"
:on-change="fileChange"
:before-upload="beforeAvatarUpload"
:before-remove="beforeRemove"
:auto-upload="false"
multiple
:file-list="upload.fileList">
<el-button size="small" type="primary">点击上传</el-button>
<!-- <div slot="tip" class="el-upload__tip">只能上传jpg/png文件,且不超过500kb</div>-->
</el-upload>
</el-form-item>
</el-form>
<div slot="footer" class="dialog-footer">
<el-button type="primary" @click="submitForm">确 定</el-button>
<el-button @click="cancel">取 消</el-button>
</div>
</el-dialog>
- js代码,由于我们对都是对文件列表upload.fileList参数进行操作
/** 文件预上传格式限制 */
beforeAvatarUpload(file) {
// const isJPG = file.type === 'image/jpeg'
// const isPng = file.type === 'image/png'
// const isLt2M = file.size / 1024 / 1024 < 2
//
// if (!isJPG && !isPng) {
// this.$message.error('上传图片只能是 JPG或png 格式!')
// }
// if (!isLt2M) {
// this.$message.error('上传图片大小不能超过 2MB!')
// }
// return (isJPG || isPng) && isLt2M
},
/** 文件移除时 */
handleRemove(file, fileList) {
for (const i in this.picList) {
if (this.picList[i].key === file.uid) {
this.picList.splice(i, 1)
}
}
this.upload.fileList = fileList
},
// 文件改变时
fileChange(file, fileList) {
this.upload.fileList = fileList
},
// 文件移除之前
beforeRemove(file, fileList) {
return this.$confirm(`确定移除 ${file.name}?`);
},
/** 提交按钮 */
submitForm() {
this.$refs["form"].validate(valid => {
if (valid) {
if (this.form.tId != null) {
let formData = new FormData()
this.upload.fileList.forEach(file => {
formData.append('file', file.raw)
});
formData.append("tId", this.form.tId)
formData.append("snakebiteType", this.form.snakebiteType)
formData.append("programmeName", this.form.programmeName)
formData.append("programmeDescribe", this.form.programmeDescribe)
formData.append("orgName", this.form.orgName)
this.bingOrgCode(this.form.orgName)
formData.append("orgCode", this.form.orgCode)
updateTreatment(formData).then(response => {
this.msgSuccess("修改成功");
this.open = false;
this.getList();
});
} else {
let formData = new FormData()
this.upload.fileList.forEach(file => {
formData.append('file', file.raw)
})
formData.append("snakebiteType", this.form.snakebiteType)
formData.append("programmeName", this.form.programmeName)
formData.append("programmeDescribe", this.form.programmeDescribe)
formData.append("orgCode", this.form.orgCode)
formData.append("orgName", this.form.orgName)
addTreatment(formData).then(response => {
this.msgSuccess("新增成功");
this.open = false;
this.getList();
});
}
}
});
},
// 取消按钮
cancel() {
this.open = false;
this.reset();
},
/ 新增蛇伤治疗
export function addTreatment(data) {
return request({
url: '/hospital/treatment',
method: 'post',
data: data
})
}
2、后端,我们使用的springboot,下面我们贴上代码
- controller 控制层接收参数,这里给出实现类,接口也是一样的
@RestController
@RequestMapping("/hospital/treatment")
public class SnakebiteTreatmentController extends BaseController
{
@Autowired
private ISnakebiteTreatmentService snakebiteTreatmentService;
/**
* 新增蛇伤治疗,并上传文件
*/
//@PreAuthorize("@ss.hasPermi('hospital:treatment:add')")
@Log(title = "蛇伤治疗", businessType = BusinessType.INSERT)
@PostMapping
public AjaxResult add(@RequestParam(value = "file") MultipartFile[] file,SnakebiteTreatment snakebiteTreatment) throws Exception
{
return toAjax(snakebiteTreatmentService.insertSnakebiteTreatment(file, snakebiteTreatment));
}
}
这里使用 MultipartFile[] file 来存储多个文件,首先对MultipartFile的 file对象进行遍历查看是否有多个文件,使用for (MultipartFile newFile : file)生成newFile 对象
- 使用MultipartFile里的getOriginalFilename()方法来获取当前newFile的文件名称
String fileName = newFile.getOriginalFilename();
- 使用FileUploadUtils文件工具类里的getExtension(newFile)来获取文件类型
String fileType = FileUploadUtils.getExtension(newFile);
- 设置文件路径前缀,可以手动写死设置。我这里使用的是若依
String filePrefix = RuoYiConfig.getProfile();
- 使用FileUploadUtils文件工具类里的upload(前缀,文件对象)进行上传文件操作,并返回文件后缀
- 使用字符串分隔符进行分割后缀
String savePath = fileSuffix.substring(9);
@Service
public class SnakebiteTreatmentServiceImpl implements ISnakebiteTreatmentService {
@Autowired
private SnakebiteTreatmentMapper snakebiteTreatmentMapper;
@Autowired
private SnakebiteTreatmentFileServiceImpl snakebiteTreatmentFileService;
/**
* 新增蛇伤治疗,并上传文件
*
* @param snakebiteTreatment 蛇伤治疗
* @return 结果
*/
@Override
public int insertSnakebiteTreatment(MultipartFile[] file, SnakebiteTreatment snakebiteTreatment) throws Exception {
int code = snakebiteTreatmentMapper.insertSnakebiteTreatment(snakebiteTreatment);
Long tId = snakebiteTreatment.gettId();
//有上传文件就处理,没有就不处理
if (file != null && file.length > 0) {
if (tId != null) {
ArrayList<SnakebiteTreatmentFile> list = new ArrayList<>();
for (MultipartFile newFile : file) {
if (newFile.isEmpty()) {
return -1;
}
// 获取文件名称
String fileName = newFile.getOriginalFilename();
// 获取文件类型
String fileType = FileUploadUtils.getExtension(newFile);
// 获取文件路径前缀
String filePrefix = RuoYiConfig.getProfile();
// 获取文件路径后缀
String fileSuffix = FileUploadUtils.upload(filePrefix, newFile);
// 设置文件保存路径
String savePath = fileSuffix.substring(9);
// 将主表自增主键、文件名,文件路径,文件类型保存至文件表数据库中
SnakebiteTreatmentFile treatmentFile = new SnakebiteTreatmentFile();
treatmentFile.settId(tId);
treatmentFile.settFileType(fileType);
treatmentFile.settFileName(fileName);
treatmentFile.settFilePath(savePath);
list.add(treatmentFile);
}
snakebiteTreatmentFileService.insertSnakebiteTreatmentFile(list);
}
}
return code;
}
}
public int insertSnakebiteTreatmentFile(List<SnakebiteTreatmentFile> snakebiteTreatmentFile);
- 我们这里使用的是mybatis,下面贴上操作文件数据库表代码
<insert id="insertSnakebiteTreatmentFile" parameterType="SnakebiteTreatmentFile" useGeneratedKeys="true" keyProperty="tfId">
insert into snakebite_treatment_file (t_id,t_file_name,t_file_path,t_file_type) values
<foreach collection="list" item="item" index="index" separator=",">
(#{item.tId}, #{item.tFileName}, #{item.tFilePath},#{item.tFileType})
</foreach>
</insert>
到这里文件上传已经完成,下面贴上FileUploadUtils文件上传工具类代码
package com.zyy.common.utils.file;
import java.io.File;
import java.io.IOException;
import org.apache.commons.io.FilenameUtils;
import org.springframework.web.multipart.MultipartFile;
import com.zyy.common.config.RuoYiConfig;
import com.zyy.common.constant.Constants;
import com.zyy.common.exception.file.FileNameLengthLimitExceededException;
import com.zyy.common.exception.file.FileSizeLimitExceededException;
import com.zyy.common.exception.file.InvalidExtensionException;
import com.zyy.common.utils.DateUtils;
import com.zyy.common.utils.StringUtils;
import com.zyy.common.utils.uuid.IdUtils;
/**
* 文件上传工具类
*
* @author zyy
*/
public class FileUploadUtils {
/**
* 默认大小 50M
*/
public static final long DEFAULT_MAX_SIZE = 50 * 1024 * 1024;
/**
* 默认的文件名最大长度 100
*/
public static final int DEFAULT_FILE_NAME_LENGTH = 100;
/**
* 默认上传的地址
*/
private static String defaultBaseDir = RuoYiConfig.getProfile();
public static void setDefaultBaseDir(String defaultBaseDir) {
FileUploadUtils.defaultBaseDir = defaultBaseDir;
}
public static String getDefaultBaseDir() {
return defaultBaseDir;
}
/**
* 以默认配置进行文件上传
*
* @param file 上传的文件
* @return 文件名称
* @throws Exception
*/
public static final String upload(MultipartFile file) throws IOException {
try {
return upload(getDefaultBaseDir(), file, MimeTypeUtils.DEFAULT_ALLOWED_EXTENSION);
} catch (Exception e) {
throw new IOException(e.getMessage(), e);
}
}
/**
* 根据文件路径上传
*
* @param baseDir 相对应用的基目录
* @param file 上传的文件
* @return 文件名称
* @throws IOException
*/
public static final String upload(String baseDir, MultipartFile file) throws IOException {
try {
return upload(baseDir, file, MimeTypeUtils.DEFAULT_ALLOWED_EXTENSION);
} catch (Exception e) {
throw new IOException(e.getMessage(), e);
}
}
/**
* 文件上传
*
* @param baseDir 相对应用的基目录
* @param file 上传的文件
* @param allowedExtension 上传文件类型
* @return 返回上传成功的文件名
* @throws FileSizeLimitExceededException 如果超出最大大小
* @throws FileNameLengthLimitExceededException 文件名太长
* @throws IOException 比如读写文件出错时
* @throws InvalidExtensionException 文件校验异常
*/
public static final String upload(String baseDir, MultipartFile file, String[] allowedExtension)
throws FileSizeLimitExceededException, IOException, FileNameLengthLimitExceededException,
InvalidExtensionException {
int fileNamelength = file.getOriginalFilename().length();
if (fileNamelength > FileUploadUtils.DEFAULT_FILE_NAME_LENGTH) {
throw new FileNameLengthLimitExceededException(FileUploadUtils.DEFAULT_FILE_NAME_LENGTH);
}
assertAllowed(file, allowedExtension);
String fileName = extractFilename(file);
File desc = getAbsoluteFile(baseDir, fileName);
file.transferTo(desc);
String pathFileName = getPathFileName(baseDir, fileName);
return pathFileName;
}
/**
* 编码文件名
*/
public static final String extractFilename(MultipartFile file) {
String fileName = file.getOriginalFilename();
String extension = getExtension(file);
// fileName = DateUtils.datePath() + "/" + IdUtils.fastUUID() + "." + extension;
fileName = DateUtils.datePath() + "/" + fileName;
return fileName;
}
private static final File getAbsoluteFile(String uploadDir, String fileName) throws IOException {
File desc = new File(uploadDir + File.separator + fileName);
if (!desc.getParentFile().exists()) {
desc.getParentFile().mkdirs();
}
if (!desc.exists()) {
desc.createNewFile();
}
return desc;
}
private static final String getPathFileName(String uploadDir, String fileName) throws IOException {
int dirLastIndex = RuoYiConfig.getProfile().length() + 1;
String currentDir = StringUtils.substring(uploadDir, dirLastIndex);
String pathFileName = Constants.RESOURCE_PREFIX + "/" + currentDir + "/" + fileName;
return pathFileName;
}
/**
* 文件大小校验
*
* @param file 上传的文件
* @return
* @throws FileSizeLimitExceededException 如果超出最大大小
* @throws InvalidExtensionException
*/
public static final void assertAllowed(MultipartFile file, String[] allowedExtension)
throws FileSizeLimitExceededException, InvalidExtensionException {
long size = file.getSize();
if (DEFAULT_MAX_SIZE != -1 && size > DEFAULT_MAX_SIZE) {
throw new FileSizeLimitExceededException(DEFAULT_MAX_SIZE / 1024 / 1024);
}
String fileName = file.getOriginalFilename();
String extension = getExtension(file);
if (allowedExtension != null && !isAllowedExtension(extension, allowedExtension)) {
if (allowedExtension == MimeTypeUtils.IMAGE_EXTENSION) {
throw new InvalidExtensionException.InvalidImageExtensionException(allowedExtension, extension,
fileName);
} else if (allowedExtension == MimeTypeUtils.FLASH_EXTENSION) {
throw new InvalidExtensionException.InvalidFlashExtensionException(allowedExtension, extension,
fileName);
} else if (allowedExtension == MimeTypeUtils.MEDIA_EXTENSION) {
throw new InvalidExtensionException.InvalidMediaExtensionException(allowedExtension, extension,
fileName);
} else {
throw new InvalidExtensionException(allowedExtension, extension, fileName);
}
}
}
/**
* 判断MIME类型是否是允许的MIME类型
*
* @param extension
* @param allowedExtension
* @return
*/
public static final boolean isAllowedExtension(String extension, String[] allowedExtension) {
for (String str : allowedExtension) {
if (str.equalsIgnoreCase(extension)) {
return true;
}
}
return false;
}
/**
* 获取文件名的后缀
*
* @param file 表单文件
* @return 后缀名
*/
public static final String getExtension(MultipartFile file) {
String extension = FilenameUtils.getExtension(file.getOriginalFilename());
if (StringUtils.isEmpty(extension)) {
extension = MimeTypeUtils.getExtension(file.getContentType());
}
return extension;
}
}
-------------------------------------------------------------------------------------------
文件下载代码实现
1、前端,点击方案列表下载方案(文件)按钮
<el-dialog title="方案列表" :visible.sync="openDownload" width="900px" append-to-body>
<el-form ref="fileForm" label-width="80px">
<el-table :data="dataFileList">
<el-table-column label="序号" align="center" width="50px" type="index"/>
<el-table-column label="方案名称" align="center" prop="tFileName"/>
<el-table-column label="操作" align="center" class-name="small-padding fixed-width" width="220px">
<template slot-scope="scope">
<el-button
size="mini"
type="text"
icon="el-icon-download"
@click="download(scope.row)"
v-hasPermi="['hospital:treatment:download']"
>下载方案
</el-button>
<el-button
size="mini"
type="text"
icon="el-icon-delete"
@click="handleFileDelete(scope.row)"
v-hasPermi="['hospital:treatment:remove']"
>删除方案
</el-button>
</template>
</el-table-column>
</el-table>
</el-form>
<div slot="footer" class="dialog-footer">
<el-button @click="cancelDownload">取 消</el-button>
</div>
</el-dialog>
// 文件下载
download(row) {
// window.open(process.env.VUE_APP_BASE_API + "/hospital/file/downloadFile?tPath=" + tPath)
var name = row.tFileName;
var url = row.tFilePath;
const a = document.createElement('a')
a.setAttribute('download', name)
a.setAttribute('target', '_blank')
a.setAttribute('href', process.env.VUE_APP_BASE_API + "/hospital/file/downloadFile?tPath=" + url)
a.click()
},
1、后端
- controller 控制层接收文件路径
- 我们通过使用文件工具类FileUtils的downloadUtil(response, filePrefix + tPath, fileName)方法进行处理,并传入response,前缀与地址拼接,文件名
/**
* 下载文件
*/
@PreAuthorize("@ss.hasPermi('hospital:treatmentFile:download')")
@RequestMapping("/downloadFile")
public void downloadFile(HttpServletRequest request, HttpServletResponse response, @RequestParam("tPath") String tPath) throws IOException {
// 获取文件路径前缀
String filePrefix = RuoYiConfig.getProfile();
// 获取文件名
String fileName = tPath.substring(tPath.lastIndexOf("/") + 1);
// 文件下载
FileUtils.downloadUtil(response, filePrefix + tPath, fileName);
}
到这里文件下载也已经完成,下面贴上FileUtils文件工具类代码
package com.zyy.hospital.utils;
import org.springframework.web.multipart.MultipartFile;
import javax.imageio.ImageIO;
import javax.servlet.http.HttpServletResponse;
import java.awt.image.BufferedImage;
import java.io.*;
import java.net.URLEncoder;
import java.util.List;
import java.util.zip.ZipEntry;
import java.util.zip.ZipOutputStream;
/**
* 文件工具类
*/
public class FileUtils {
/**
* 上传文件工具
*
* @param UPLOAD_FILES_PATH 上传路径
* @param fileName 文件名称
* @param file 文件
*/
public static Boolean upLoadUtil(String UPLOAD_FILES_PATH, String fileName, MultipartFile file) throws IOException {
if (file.isEmpty()) {
return false;
} else {
File dest = new File(UPLOAD_FILES_PATH + "/" + fileName);
//判断文件父目录是否存在
if (!dest.getParentFile().exists()) {
dest.getParentFile().mkdirs();
}
file.transferTo(dest);
}
return true;
}
/**
* 下载文件工具
*
* @param response response对象
* @param realPath 文件路径
* @param fileName 文件名称
*/
public static void downloadUtil(final HttpServletResponse response, String realPath, String fileName) throws IOException {
File file = new File(realPath);
if (file.exists()) {
response.setHeader("content-type", "application/octet-stream");
response.setContentType("application/octet-stream");
// 下载文件能正常显示中文
try {
response.setHeader("Content-Disposition", "attachment;filename=" + URLEncoder.encode(fileName, "UTF-8"));
} catch (UnsupportedEncodingException e) {
e.printStackTrace();
}
// 实现文件下载
byte[] buffer = new byte[1024];
FileInputStream fis = null;
BufferedInputStream bis = null;
try {
fis = new FileInputStream(file);
bis = new BufferedInputStream(fis);
OutputStream os = response.getOutputStream();
int i = bis.read(buffer);
while (i != -1) {
os.write(buffer, 0, i);
i = bis.read(buffer);
}
} catch (Exception e) {
e.printStackTrace();
} finally {
assert bis != null;
bis.close();
fis.close();
}
}
}
/**
* 删除文件夹
*
* @param sPath 文件夹路径
*/
public static boolean DeleteFolder(String sPath) {
boolean flag = false;
File file = new File(sPath);
// 判断目录或文件是否存在
if (!file.exists()) { // 不存在返回 false
return flag;
} else {
// 判断是否为文件
if (file.isFile()) { // 为文件时调用删除文件方法
return deleteFile(sPath);
} else { // 为目录时调用删除目录方法
return deleteDirectory(sPath);
}
}
}
/**
* 删除单个文件
*
* @param sPath 被删除文件的文件名
* @return 单个文件删除成功返回true,否则返回false
*/
public static boolean deleteFile(String sPath) {
boolean flag = false;
File file = new File(sPath);
// 路径为文件且不为空则进行删除
if (file.isFile() && file.exists()) {
file.delete();
flag = true;
}
return flag;
}
/**
* 删除目录(文件夹)以及目录下的文件
*
* @param sPath 被删除目录的文件路径
* @return 目录删除成功返回true,否则返回false
*/
public static boolean deleteDirectory(String sPath) {
//如果sPath不以文件分隔符结尾,自动添加文件分隔符
if (!sPath.endsWith(File.separator)) {
sPath = sPath + File.separator;
}
File dirFile = new File(sPath);
//如果dir对应的文件不存在,或者不是一个目录,则退出
if (!dirFile.exists() || !dirFile.isDirectory()) {
return false;
}
boolean flag = true;
//删除文件夹下的所有文件(包括子目录)
File[] files = dirFile.listFiles();
for (int i = 0; i < files.length; i++) {
//删除子文件
if (files[i].isFile()) {
flag = deleteFile(files[i].getAbsolutePath());
if (!flag) {
break;
}
} //删除子目录
else {
flag = deleteDirectory(files[i].getAbsolutePath());
if (!flag) {
break;
}
}
}
if (!flag) {
return false;
}
//删除当前目录
if (dirFile.delete()) {
return true;
} else {
return false;
}
}
/**
* 转文件格式
*
* @param img 照片文件
*/
public static byte[] fileToByte(File img) throws Exception {
byte[] bytes = null;
ByteArrayOutputStream baos = new ByteArrayOutputStream();
try {
BufferedImage bi;
bi = ImageIO.read(img);
ImageIO.write(bi, "jpg", baos);
bytes = baos.toByteArray();
} catch (Exception e) {
// e.printStackTrace();
} finally {
// 关闭输出流
baos.close();
}
return bytes;
}
}