文件上传
1. 文件上传的流程
文件上传的流程通常如下:
- 用户在浏览器中访问包含文件上传表单的页面。
- 用户选择要上传的文件,并点击上传按钮。
- 浏览器将选择的文件打包成一个HTTP请求,然后发送给服务器。
- 服务器接收到HTTP请求,并解析其中的文件数据。
- 服务器对文件进行处理,比如保存到文件系统、存储到数据库、或者进行其他逻辑处理。
- 服务器发送一个响应给客户端,告诉客户端文件上传是否成功。
- 客户端收到服务器的响应后,根据响应结果进行相应的处理,比如显示上传成功或失败的消息。
2.文件上传的代码实现
表单上传的属性
action、
action
属性的值通常是服务器端的一个URL,用于接收并处理表单数据。服务器端的脚本或程序会根据表单中的数据执行相应的操作,比如将数据存储到数据库中、发送电子邮件、进行身份验证等。
method
method是 HTML
元素的一个属性,用于指定表单数据的提交方法。常见的提交方法有
GET和
POST`。
GET
: 表单数据会附加在URL的末尾,并作为查询字符串的一部分发送给服务器。这种提交方式通常用于获取数据,比如搜索表单等。GET
方法对提交的数据量有限制,通常不适用于包含大量数据或敏感信息的表单。POST
: 表单数据会作为请求的一部分发送给服务器,而不会在URL中显示。这种提交方式适用于包含大量数据或敏感信息的表单,比如用户登录、文件上传等。POST
方法没有数据量的限制,并且可以发送复杂的数据结构。
enctype
application/x-www-form-urlencoded
: 这是默认的表单编码类型。它将表单数据编码为 URL 查询字符串格式,适用于普通的表单数据提交,但不支持文件上传。multipart/form-data
: 这种编码类型适用于包含文件上传的表单。它会将表单数据编码为多个部分(即多部分 MIME 编码),每个部分都有自己的头部信息和内容,可以包含二进制文件数据。这种编码类型通常用于文件上传时。text/plain
: 这种编码类型将表单数据作为纯文本进行提交,不进行任何编码。这种编码类型较少使用,因为它无法支持文件上传,并且对于复杂的表单数据结构支持较差。- 设置之后,当用户选择文件并提交表单时,浏览器会将表单数据以多部分 MIME 编码的方式发送给服务器,包括文件数据。服务器可以根据这种编码方式来正确解析文件数据,并进行相应的处理。
target
_self
: 默认值。表示在当前窗口中加载响应页面。当用户提交表单后,响应页面会在当前窗口中打开或替换。_blank
: 表示在新窗口中打开响应页面。当用户提交表单后,响应页面会在新的浏览器窗口中打开。_parent
: 表示在父窗口中加载响应页面。通常用于在框架中使用表单时,指定响应页面加载在父框架中。_top
: 表示在顶层窗口中加载响应页面。通常用于在嵌套框架中使用表单时,指定响应页面加载在最顶层的框架中。
前端代码
ini
<form action="/downandupdate/update" method="post" enctype="multipart/form-data" id="downandload" target="frameName">
<input type="file" name="file">
<input type="submit" value="提交">
</form>
<iframe src="" frameborder="0" name="frameName"></iframe>
target
和 <iframe>
元素通常一起使用,用于在 HTML 页面中创建一个内联的框架,用于展示来自服务器的响应页面或内容
这样写可以保证页面不跳转
后端代码
scss
@RequestMapping("/downandupdate")
public class downloadandupdate {
// 获取服务器所在的项目目录
private String basePath = System.getProperty("user.dir") + "\src\main\resources\backend\content\";
@PostMapping("/update")
// MultipartFile用于接受文件的数据
public R<String> update(MultipartFile file, HttpSession session) {
// 获取上传文件的文件名
String fileName = basePath + file.getOriginalFilename();
File localFile = new File(fileName);
if (!localFile.exists()) {
localFile.mkdir();
}
try {
// 将上传的数据保存在指定的目录下
file.transferTo(localFile);
} catch (IOException e) {
throw new RuntimeException(e);
}
// 设置session,用于后面的下载数据
session.setAttribute("fileName",file.getOriginalFilename());
return null;
}
}
3.设置上传文件的大小限制
在文件上传过程中,需要注意安全性和性能问题。文件上传可能会受到恶意用户的攻击,比如上传恶意软件或超大文件,因此需要对上传的文件进行验证和过滤。此外,对于大文件的上传,可能会影响服务器的性能,因此可能需要对上传文件的大小进行限制,或者使用分块上传等技术来优化性能。
在application.yml配置文件中设置
yaml
spring:
servlet:
multipart:
# 限制文件上传的大小
max-file-size: 3MB
# 设置客户端发送给服务器的整个请求的大小
max-request-size: 3MB
文件下载
1.下载文件流程
文件下载的过程通常如下:
- 客户端发起请求:用户在浏览器中点击下载链接或按钮,或者在应用程序中触发文件下载操作。浏览器向服务器发送一个下载文件的请求。
- 服务器处理请求:服务器接收到客户端的下载请求后,根据请求的内容生成相应的文件内容。
- 服务器发送响应:服务器将文件内容作为响应发送给客户端。响应通常包含标准的HTTP头部信息,包括文件类型(Content-Type)、文件大小(Content-Length)等,以及实际的文件数据。
- 客户端接收响应:浏览器或应用程序接收到服务器发送的响应后,根据响应中的文件数据进行相应的处理。通常浏览器会弹出一个文件下载对话框,提示用户选择文件保存的位置,并提供一个保存按钮用于开始下载文件。
- 文件保存到本地:用户点击保存按钮后,浏览器将文件保存到指定的位置。如果文件已经存在,可能会提示用户覆盖文件或重命名文件。
- 下载完成:文件下载完成后,用户可以在本地设备中找到并使用下载的文件。
2.下载到本地
后端代码
scss
@GetMapping("/download")
public ResponseEntity<Resource> downloadFile(HttpSession session) {
String filePath = basePath + session.getAttribute("fileName"); // 文件在服务器中的路径
try {
File file = new File(filePath);
Path path = Paths.get(file.getAbsolutePath());
ByteArrayResource resource = new ByteArrayResource(Files.readAllBytes(path));
HttpHeaders headers = new HttpHeaders();
// 设置响应头和响应体数据类型
headers.add(HttpHeaders.CONTENT_DISPOSITION, "attachment; filename=" + session.getAttribute("fileName"));
headers.add(HttpHeaders.CONTENT_TYPE, MediaType.APPLICATION_OCTET_STREAM_VALUE);
// ResponseEntity 可以用于控制器方法中的返回值,用于构建控制器方法的 HTTP 响应。通过返回 ResponseEntity 对象,可以更加灵活地设置响应的状态码、头部信息和响应体内容
return ResponseEntity.ok()
.headers(headers)
.contentLength(file.length())
.contentType(MediaType.parseMediaType("application/octet-stream"))
.body(resource);
} catch (IOException e) {
e.printStackTrace();
return ResponseEntity.notFound().build();
}
}
前端代码
通过给按钮设置点击事件
bash
<button onclick="downToLocal" id="downandload1">下载到本地 </button>
ini
document.getElementById("downandload1").addEventListener("click",function () {
fetch('/downandupdate/download')
.then(response => {
if (!response.ok) {
throw new Error('Network response was not ok');
}
return response.blob();
})
// blob 是浏览器提供的一个API,用于处理二进制数据。它可以用来创建、读取、写入和操作二进制数据
.then(blob => {
const url = window.URL.createObjectURL(new Blob([blob]));
const a = document.createElement('a');
a.href = url;
a.download = 'example.txt'; // 指定文件名
document.body.appendChild(a);
a.click();
window.URL.revokeObjectURL(url);
})
.catch(error => console.error('Error downloading file:', error));
})
3.在页面上展示
这里是直接将数据读取传输到前端
后端代码
typescript
@GetMapping("/brower")
public String showFileContent(HttpSession session) {
String content = null;
try {
// 读取文件内容
content= new String(Files.readAllBytes(Paths.get(basePath + session.getAttribute("fileName")));
return content;
} catch (IOException e) {
e.printStackTrace();
}
return content;
}
前端代码
xml
<button onclick="downToLocal" id="downandload1">下载到本地 </button>
<h1>文件内容:</h1>
<!-- 在页面上显示文件内容 -->
<!--<pre> 标签用于定义预格式化的文本,其中的文本会保留所有空格和换行符,并以固定宽度的字体显示。<pre> 元素通常用于展示计算机代码或其他需要保留格式的文本内容-->
<pre id="fileContent"></pre>
javascript
document.getElementById("downbrower").addEventListener("click", function () {
axios.get('/downandupdate/brower')
.then(function (response) {
// 将文件内容填充到<pre>标签中
document.getElementById("fileContent").textContent = response.data;
})
.catch(function (error) {
console.error('文件内容获取失败:', error);
});
});
效果图
文件下载
文件在浏览器上展示