基于springboot和vue的文本文件上传下载在线编辑功能,前端页面比较简陋,主要是记录一下文件的上传下载逻辑
一、Maven依赖
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.7.0</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<!--借用thymeleaf整合vue-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-thymeleaf</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-devtools</artifactId>
<scope>runtime</scope>
<optional>true</optional>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<optional>true</optional>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<scope>test</scope>
</dependency>
</dependencies>
二、配置文件
# 应用端口
server:
port: 8080
spring:
thymeleaf:
cache: false
# 文件上传下载路径
upload:
# windows下的默认路径
windowsFilePath: F:/my/uploadFile/
# linux下的默认路径
linuxFilePath: /tmp/uploadFile/
三、后端接口
- 业务接口
package com.carson.springbootfile.controller;
import com.carson.springbootfile.entity.FileVo;
import com.carson.springbootfile.entity.RequestResult;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;
import javax.servlet.http.HttpServletResponse;
import java.io.*;
import java.util.Locale;
/**
* @author: carson
* @date: 20:18 2022/6/19
* @description: 上传与下载文件接口
*/
@Controller
public class uploadController {
//windows下的默认路径
@Value("${upload.windowsFilePath}")
private String wUpFilePath;
//linux下的默认路径
@Value("${upload.linuxFilePath}")
private String lUpFilePath;
/**
* 上传文件
* @param file
* @return
* @throws IOException
*/
@PostMapping("/upload")
@ResponseBody
public RequestResult upload(@RequestParam("file") MultipartFile file) throws IOException {
RequestResult requestResult = new RequestResult();
String upFilePath = getUpFilePath();
if(upFilePath==null||"".endsWith(upFilePath)){
requestResult.setRequestMsg("添加失败,路径为空");
requestResult.setRequestObject(false);
requestResult.setRequestSuccess(false);
return requestResult;
}
File file1 = new File(upFilePath);
if(!file1.exists()){
//不存在则创建文件路径
file1.mkdirs();
}
File localFile = new File(upFilePath + file.getOriginalFilename());
//文件写入磁盘
file.transferTo(localFile);
//封装返回结果
requestResult.setRequestMsg("添加成功");
requestResult.setRequestObject(true);
requestResult.setRequestSuccess(true);
return requestResult;
}
/**
* 获取文件路径
* @param fileDir
* @return
* @throws IOException
*/
@GetMapping("/getFilePath")
@ResponseBody
public RequestResult getFilePath(@RequestParam("fileDir")String fileDir) throws IOException {
RequestResult requestResult = new RequestResult();
File file = new File(fileDir);
File[] files = file.listFiles();
requestResult.setRequestMsg("查询成功");
requestResult.setRequestObject(files);
requestResult.setRequestSuccess(true);
return requestResult;
}
/**
* @author: carson
* @date: 21:45 2022/6/20
* @description: 下载文件
* @param fileName
* @param response
* @return: void
*/
@GetMapping("/downloadFile")
public void downloadFile(@RequestParam("fileName")String fileName,HttpServletResponse response) throws Exception {
String upFilePath = getUpFilePath();
File file = new File(upFilePath + fileName);
//设置编码格式,防止下载的文件内乱码
response.setCharacterEncoding("UTF-8");
//获取路径文件对象
String realFileName = file.getName();
//设置响应头类型,这里可以根据文件类型设置,text/plain、application/vnd.ms-excel等
response.setHeader("content-type", "application/octet-stream;charset=UTF-8");
response.setContentType("application/octet-stream;charset=UTF-8");
//如果不设置响应头大小,可能报错:“Excel 已完成文件级验证和修复。此工作簿的某些部分可能已被修复或丢弃”
response.addHeader("Content-Length", String.valueOf(file.length()));
try{
//Content-Disposition的作用:告知浏览器以何种方式显示响应返回的文件,用浏览器打开还是以附件的形式下载到本地保存
//attachment表示以附件方式下载 inline表示在线打开 "Content-Disposition: inline; filename=文件名.mp3"
// filename表示文件的默认名称,因为网络传输只支持URL编码的相关支付,因此需要将文件名URL编码后进行传输,前端收到后需要反编码才能获取到真正的名称
response.setHeader("Content-Disposition", "inline;filename=" + java.net.URLEncoder.encode(realFileName.trim(), "UTF-8"));
} catch (
UnsupportedEncodingException e1) {
e1.printStackTrace();
}
//初始化文件流字节缓存
byte[] buff = new byte[1024];
BufferedInputStream bis = null;
try {
//开始写入
OutputStream os = response.getOutputStream();
//写入完成,创建文件流
bis = new BufferedInputStream(new FileInputStream(file));
// bis.read(data):将字符读入数组。在某个输入可用、发生I/O错误或者已到达流的末尾前,此方法一直阻塞。
// 读取的字符数,如果已到达流的末尾,则返回 -1
int i = bis.read(buff);
while (i != -1) {
os.write(buff, 0, buff.length);
os.flush();
i = bis.read(buff);
}
}catch (Exception e){
e.printStackTrace();
}finally {
if (bis != null) {
try {
bis.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
/**
* 读取文件内容
* @param fileName
* @return
*/
@GetMapping("/readFile")
@ResponseBody
public RequestResult readFile(@RequestParam("fileName")String fileName){
String upFilePath = getUpFilePath();
RequestResult requestResult = new RequestResult();
File file = new File(upFilePath + fileName);
StringBuilder result = new StringBuilder();
String content = "";//文件内容
BufferedReader br = null;
try {
//写入完成,创建文件流
br = new BufferedReader(new FileReader(file));
//使用readLine方法,一次读一行
while((content = br.readLine())!=null){
result.append(System.lineSeparator()+content);
}
}catch (Exception e){
e.printStackTrace();
}finally {
if (br != null) {
try {
br.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
//封装返回结果
requestResult.setRequestSuccess(true);
requestResult.setRequestObject(result.toString());
requestResult.setRequestMsg("读取成功");
return requestResult;
}
/**
* 写入文件
* @param vo
* @return
*/
@PostMapping("/writeToFile")
@ResponseBody
public RequestResult writeToFile(FileVo vo){
RequestResult requestResult = new RequestResult();
String upFilePath = getUpFilePath();
//获取文件名
String fileName = vo.getFileName();
//获取文件内容
String fileContent = vo.getFileContent();
File file = new File(upFilePath + fileName);
//删除旧文件
if(file.exists())file.delete();
//创建新文件
try {
file.createNewFile();
file = new File(upFilePath + fileName);
} catch (IOException e) {
throw new RuntimeException(e);
}
try {
//写入内容
FileWriter fileWriter = new FileWriter(file, true);
fileWriter.write(fileContent);
fileWriter.flush();
fileWriter.close();
//封装返回结果
requestResult.setRequestMsg("写入成功");
requestResult.setRequestObject(upFilePath+fileName);
requestResult.setRequestSuccess(true);
} catch (IOException e) {
throw new RuntimeException(e);
}
return requestResult;
}
}
- 页面跳转接口
package com.carson.springbootfile.controller.page;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.GetMapping;
/**
* @author: carson
* @date: 21:18 2022/6/20
* @description: 页面跳转
*/
@Controller
public class pageUploadController {
@GetMapping("/index")
public String toIndexPage(){
//跳转到src/main/resources/templates/index.html
return "index";
}
}
四、前端页面
index.html
- 引入依赖
<!-- element-ui样式 -->
<link rel="stylesheet" href="https://unpkg.com/element-ui/lib/theme-chalk/index.css">
<!--引入vue-->
<script src="https://cdn.jsdelivr.net/npm/vue@2.6.14/dist/vue.js"></script>
<!--引入element-ui-->
<script src="https://unpkg.com/element-ui/lib/index.js"></script>
<!--引入axios-->
<script src="https://cdn.jsdelivr.net/npm/axios/dist/axios.min.js"></script>
- 完整前端代码
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<!-- element-ui样式 -->
<link rel="stylesheet" href="https://unpkg.com/element-ui/lib/theme-chalk/index.css">
<title>上传文件</title>
</head>
<!--引入vue-->
<script src="https://cdn.jsdelivr.net/npm/vue@2.6.14/dist/vue.js"></script>
<!--引入element-ui-->
<script src="https://unpkg.com/element-ui/lib/index.js"></script>
<!--引入axios-->
<script src="https://cdn.jsdelivr.net/npm/axios/dist/axios.min.js"></script>
<body>
<div id="app">
<el-row>
<el-upload
class="upload-demo"
drag
action="http://localhost:8080/upload"
:file-list="fileList"
:on-success="handleSuccessUpload"
multiple>
<i class="el-icon-upload"></i>
<div class="el-upload__text">将文件拖到此处,或<em>点击上传</em></div>
<!-- <div class="el-upload__tip" slot="tip">只能上传jpg/png文件,且不超过500kb</div>-->
</el-upload>
</el-row>
<el-row>
<el-col :span="5">
<el-select v-model="fileName" placeholder="请选择文件" clearable>
<el-option
v-for="item in loadFileList"
:key="item.value"
:label="item.label"
:value="item.value">
</el-option>
</el-select>
</el-col>
<el-col :span="2">
<el-button @click="downloadFile">下载</el-button>
</el-col>
<el-col :span="2">
<el-button @click="readFile">读取</el-button>
</el-col>
</el-row>
<el-row>
<el-input
type="textarea"
autosize
placeholder="请输入内容"
v-model="textarea"
clearable>
</el-input>
<el-button @click="saveToFile">保存</el-button>
</el-row>
</div>
</body>
<script>
new Vue({
el: '#app',
data() {
return {
fileList:[],
loadFileList:[],
fileName:'',
textarea:''
}
},
created(){
var that = this
that.getLoadFileList()
},
methods: {
handleSuccessUpload(){
this.getLoadFileList()
},
//下载文件
downloadFile(){
var that = this
axios({
method:"GET",
url:"/downloadFile",
params:{
fileName: that.fileName
},
headers: {
//和后端设置的一样
'Content-Type': 'application/octet-stream;charset=UTF-8'
},
responseType: 'blob'
}).then(res => {
var url = window.URL.createObjectURL(new Blob([res.data]));
var link = document.createElement('a');
link.href = url;
link.setAttribute('download', that.fileName);
document.body.appendChild(link);
link.click();
})
},
//读取文件内容
readFile(){
var that = this
that.textarea = ''
axios({
method:"GET",
url:"/readFile",
params:{
fileName: that.fileName
}
}).then(res =>{
if(res.data.requestSuccess){
that.textarea = res.data.requestObject
}
}).catch(err=>{
console.log(err)
})
},
//保存文件
saveToFile(){
var that = this
axios({
method:"POST",
url:"/writeToFile",
params:{
fileContent: that.textarea,
fileName: that.fileName
}
}).then(res =>{
if(res.data.requestSuccess){
that.$message.success('保存成功')
that.getLoadFileList()
}
})
},
//获取文件列表
getLoadFileList(){
var that = this
that.loadFileList = []
axios({
method:'get',
url: '/getFilesInPath'
}).then(res=>{
if(res.data.requestSuccess){
that.loadFileList = res.data.requestObject;
}
})
}
}
})
</script>
</html>