1、vue前端部分
前端部分采用element组件
官网上传下载的地址地址
主要的element代码如下,下面我一一的讲解一下
<el-form-item>
<el-upload
drag
:action="url"
ref="upload"
:before-upload="beforeUploadHandle"
:on-success="successHandle"
:on-change="handleChange"
multiple
:file-list="fileList"
:limit="1"
:on-exceed="handleExceed"
style="text-align: center"
:auto-upload="false"
>
<el-button size="small" type="primary">点击上传</el-button>
</el-upload>
</el-form-item>
drag:支持拖拽的效果
:action=“url” :绑定的URL,上传的url,默认的的post方式上传,这个我也找了半天才明白过来
ref=“upload” :可以理解成上传组件的ID,绑定的是upload
:before-upload=“beforeUploadHandle”:在上传之前绑定的方法,一般里面做一下判断,比如判断文件属性
:on-success=“successHandle” :上传成功时候调用的方法
:on-change="handleChange"上传文件组件,状态改变时候调用的方法
multiple :是否支持多文件上传
:file-list :上传的组件列表,在下面显示
:limit=“1”:限制上传的数量
:on-exceed=“handleExceed” 文件超出个数限制时的钩子,当文件超出limit限制的值,会调用这个函数
:auto-upload=“false” 这个是很关键的,element上传组件,这个是默认true。也就是说,点击上传后,直接就上传了,这个设置为false与则不会自动上传
this.
r
e
f
s
.
u
p
l
o
a
d
.
s
u
b
m
i
t
(
)
;
文件提交
t
h
i
s
.
refs.upload.submit(); 文件提交 this.
refs.upload.submit();文件提交this.refs.upload.clearFiles 清除上传记录
2、Vue上传前端方法部分
data里面
这个里面设置 document 是拿取到文件的名称,并赋值,uid是elementUI根据时间随机生成的UId,我也拿取来作为参数存储下来,给后端生成文件夹使用,并存储到数据库
data() {
return {
url: "",
num: 0,
successNum: 0,
fileList: [],
document: "",
uid: "",
}}
方法部分
initUrl这个可以作为初始化,create(){}里面初始化上传地址使用,我这里url是带token值传参的
handleExceed()超出绑定的 limit 限制时候调用
beforeUploadHandle()在上传前面,判断文件上传的类型
handleChange()当添加了文件的时候调用,我这里在文件路径后面加入了uid
successHandle()上传成功时候调用
initUrl(id) {
this.url = this.$http.adornUrl(
`/sys/oss/upload3?token=${this.$cookie.get("token")}` +
`&uid=` +
this.uid
);
},
handleExceed(files, fileList) {
this.$message.warning(`当前限制选择 1 个文件,本次上传数量超过限制`);
this.fileList = [];
},
// 上传之前
beforeUploadHandle(file) {
// if (
// file.type !== "image/jpg" &&
// file.type !== "image/jpeg" &&
// file.type !== "image/png" &&
// file.type !== "image/gif"
// ) {
// this.$message.error("只支持jpg、png、gif格式的图片!");
// return false;
// }
this.num++;
},
upclick() {
this.visible = true;
},
// 上传成功
successHandle(response, file, fileList) {
this.fileList = fileList;
console.log(response);
console.log(file);
console.log(fileList);
this.successNum++;
if (response && response.code === 0) {
if (this.num === this.successNum) {
this.$confirm("操作成功, 是否继续操作?", "提示", {
confirmButtonText: "确定",
cancelButtonText: "取消",
type: "warning",
}).catch(() => {
this.visible = false;
});
}
} else {
this.$message.error(response.msg);
}
},
// 弹窗关闭时
closeHandle() {
this.fileList = [];
this.$emit("refreshDataList");
},
handleChange(file, fileList) {
this.document = file.name;
this.uid = file.uid;
console.log(file.name);
console.log(file.uid);
this.url =
this.$http.adornUrl(`/sys/oss/upload3?`) +
`token=${this.$cookie.get("token")}` +
`&uid=` +
file.uid;
console.log(this.url);
},
文件提交的方法,因为配置的 :auto-upload=“false” ,所以需要手动提交传入文件,传输完文件之后,this.$refs.upload.clearFiles();将文件清空处理
if (this.fileList != null) {
console.log(this.url);
this.$refs.upload.submit();
this.$nextTick(() => {
this.$refs.upload.clearFiles();
});
}
3、Springboot后端上传文件接口
解释几点
1、File.separator:系统的分隔符 /
2、HttpServletRequest req 可以拿到URL?uid=***,这种url的参数
String sid = req.getParameter(“uid”);我把这个随机的uid作为参数拿到并作为文件夹的,这样文件就出现不会被覆盖的问题
3、当然这个MultipartFile[]是支持多文件上传的
4、Streams.copy(multipartFiles[i].getInputStream(), new FileOutputStream(storagePath),拿到输入流和路径,开始上传
@Autowired
UnitService unitService;
private static final Logger logger = LoggerFactory.getLogger(UnitController.class);
//在文件操作中,不用/或者\最好,推荐使用File.separator
private final static String fileDir = "files";
private final static String rootPath = System.getProperty("user.home") + File.separator + fileDir + File.separator;
@PostMapping("/upload3")
@RequiresPermissions("sys:oss:all")
public R upload2(@RequestParam("file") MultipartFile[] multipartFiles, HttpServletRequest req) {
String sid = req.getParameter("uid");
String uid = sid;
String path=rootPath;
if(uid!=null){
path=path+uid+File.separator;
System.out.println(uid);
}
System.out.println(uid);
File fileDir = new File(path);
if (!fileDir.exists() && !fileDir.isDirectory()) {
fileDir.mkdirs();
}
try {
if (multipartFiles != null && multipartFiles.length > 0) {
for (int i = 0; i < multipartFiles.length; i++) {
System.out.println(multipartFiles[i].getResource());
try {
//以原来的名称命名,覆盖掉旧的
String storagePath = path + multipartFiles[i].getOriginalFilename();
logger.info("上传的文件:" + multipartFiles[i].getName() + "," + multipartFiles[i].getContentType() + "," + multipartFiles[i].getOriginalFilename()
+ ",保存的路径为:" + storagePath);
Streams.copy(multipartFiles[i].getInputStream(), new FileOutputStream(storagePath), true);
//或者下面的
// Path path = Paths.get(storagePath);
//Files.write(path,multipartFiles[i].getBytes());
} catch (IOException e) {
}
}
}
} catch (Exception e) {
return R.error(e.getMessage());
}
return R.ok("上传成功!");
}
4、Vue前端下载文件
下载的样式
<el-button
type="text"
icon="el-icon-download"
class="blue"
@click="handleDownload(scope.$index, scope.row)"
>下载</el-button
>
</template>
下载的方法
主要是配置一个elemIF.src =url这样,我同样是带token值的,下载默认get方式下载
async handleDownload(index, row) {
console.log(row)
console.log(row.document)
this.loadingOverLay = this.$loading({
lock: true,
text: "文件生成中",
spinner: "el-icon-loading",
background: "rgba(0,0,0,0.7)",
});
var elemIF = document.createElement("iframe");
elemIF.src =
this.$http.adornUrl(
`/sys/oss/download?`
) +`token=${this.$cookie.get("token")}`+`&id=`+row.id;
elemIF.style.display = "none";
document.body.appendChild(elemIF);
this.loadingOverLay.close();
},
5、SpringBoot下载接口(可以通用)
download的方法是下载方法,
setFileDownloadHeader方法是处理乱码问题的方法
我是通过ID查询到数据查询到文件的名称和路径,返回下载的
@RequiresPermissions("sys:oss:all")
@GetMapping(value = "/download")
public void download(HttpServletRequest req, HttpServletResponse resp) {
System.out.println(req);
String sid = req.getParameter("id");
int id = Integer.parseInt(sid);
UnitEntity documentById = unitService.findDocumentById(id);
String location=documentById.getFileaddress();
String fileName=documentById.getDocument();
BufferedInputStream bis = null;
BufferedOutputStream bos = null;
OutputStream fos = null;
try {
bis = new BufferedInputStream(new FileInputStream(location));
fos = resp.getOutputStream();
bos = new BufferedOutputStream(fos);
setFileDownloadHeader(req, resp, fileName);
int byteRead = 0;
byte[] buffer = new byte[8192];
while ((byteRead = bis.read(buffer, 0, 8192)) != -1) {
bos.write(buffer, 0, byteRead);
}
} catch (Exception e) {
e.printStackTrace();
} finally {
try {
bos.flush();
bis.close();
fos.close();
bos.close();
} catch (Exception e) {
e.printStackTrace();
}
}
}
public static void setFileDownloadHeader(HttpServletRequest request,
HttpServletResponse response, String fileName) {
try {
String encodedFileName = null;
String agent = request.getHeader("USER-AGENT");
if (null != agent && -1 != agent.indexOf("MSIE")) {
encodedFileName = URLEncoder.encode(fileName, "UTF-8");
} else if (null != agent && -1 != agent.indexOf("Mozilla")) {
encodedFileName = new String(fileName.getBytes("UTF-8"),
"iso-8859-1");
} else {
encodedFileName = URLEncoder.encode(fileName, "UTF-8");
}
response.setHeader("Content-Disposition", "attachment; filename=\""
+ encodedFileName + "\"");
} catch (Exception e) {
e.printStackTrace();
}
}
6、在线展示PDF和图片后台
前端只需要调用一个网址就能查看图片和PDF
代码逻辑如下,
(1)、前端查看接口XXXX:8080/showPicture?id=***
(2)后端通过req.getParameter(“id”);拿到Id在数据库中查到PDF的绝对地址,
(3)、通过showPdf渲染就能在线查看pdf了
@RequiresPermissions("generator:area:update")
@GetMapping("/showPicture")
public R showPicture(HttpServletResponse response, HttpServletRequest req){
try {
String sid = req.getParameter("id");
int id = Integer.parseInt(sid);
AreaFileEntity byId = areaFileService.getById(id);
String location = byId.getFileaddress();
showPdf(response,location);
return R.ok();
}catch (Exception e) {
e.printStackTrace();
return R.error("传输失败");
}
}
public static void showPdf(HttpServletResponse response, String fileName) throws IOException {
// response.setContentType("application/pdf");
response.addHeader("Access-Control-Allow-Origin", "*");
FileInputStream in = new FileInputStream(new File(fileName));
OutputStream out = response.getOutputStream();
byte[] b = new byte[1024];
while ((in.read(b))!=-1) {
out.write(b);
}
out.flush();
in.close();
out.close();
}
7、文件上传,采用FormData封装数据接口
前端:(点击上传后,直接调用接口,上传图片)
<el-upload
class="avatar-uploader"
accept="image/*"
action=""
:show-file-list="false"
:http-request="uploadMainImg"
>
<img
v-if="formData.imageUrl"
:src="formData.imageUrl"
class="avatar"
/>
<i v-else class="el-icon-plus avatar-uploader-icon"></i>
</el-upload>
前端样式
.avatar-uploader .el-upload {
border: 1px dashed #d9d9d9;
border-radius: 6px;
cursor: pointer;
position: relative;
overflow: hidden;
}
.avatar-uploader .el-upload:hover {
border-color: #409eff;
}
.avatar-uploader-icon {
font-size: 28px;
color: #8c939d;
width: 178px;
height: 178px;
line-height: 178px;
text-align: center;
}
.avatar {
width: 178px;
height: 178px;
display: block;
}
前端上传方法
//上传图片
uploadMainImg(file) {
const data = new FormData();
data.append("file", file.file);
data.append("uid", file.file.uid);
console.log(file.file)
commonApi
.uploadImg(data)
.then((response) => {
// 以防图片多次上传,上传成功后,把原来的图片删除
this.deleteImg();
this.formData.imageUrl = response.data;
})
.catch((error) => {
this.$message({
type: "error",
message: "上传失败",
});
});
},
前端接口
// 上传图片
uploadImg(data = {}) {
return request({
url: `/article/file/upload`,
method: 'post',
data // data: data 简写
})
},
## 后端
后端接口
@PostMapping("/upload")
public Result upLoad(@RequestParam(value="file") MultipartFile file,@RequestParam(value="uid")String uid) {
Result result1 = AliyunUtil.upLoadLocal(file);
System.out.println("uid等于"+uid);
return result1;
}
后端上传工具
private final static String fileDir = "workFiles";
private final static String rootPath = System.getProperty("user.home") + File.separator + fileDir + File.separator;
public static Result upLoadLocal(MultipartFile multipartFiles){
File fileDir = new File(rootPath);
if (!fileDir.exists() && !fileDir.isDirectory()) {
fileDir.mkdirs();
}
try {
if (multipartFiles != null ) {
try {
//以原来的名称命名,覆盖掉旧的
String storagePath = rootPath + multipartFiles.getOriginalFilename();
System.out.println("上传的文件:" + multipartFiles.getName() + "," + multipartFiles.getContentType() + "," + multipartFiles.getOriginalFilename()
+ ",保存的路径为:" + storagePath);
Streams.copy(multipartFiles.getInputStream(), new FileOutputStream(storagePath), true);
return Result.ok(storagePath);
} catch (IOException e) {
return Result.ok("失败!");
}
}
} catch (Exception e) {
return Result.error(e.getMessage());
}
return Result.ok("失败!");
}
minIo文件分片上传并显示文件上传进度
1、