文件的上传和下载

文件上传

1. 文件上传的流程

文件上传的流程通常如下:

  1. 用户在浏览器中访问包含文件上传表单的页面。
  2. 用户选择要上传的文件,并点击上传按钮。
  3. 浏览器将选择的文件打包成一个HTTP请求,然后发送给服务器。
  4. 服务器接收到HTTP请求,并解析其中的文件数据。
  5. 服务器对文件进行处理,比如保存到文件系统、存储到数据库、或者进行其他逻辑处理。
  6. 服务器发送一个响应给客户端,告诉客户端文件上传是否成功。
  7. 客户端收到服务器的响应后,根据响应结果进行相应的处理,比如显示上传成功或失败的消息。

2.文件上传的代码实现

表单上传的属性

action、

  • action 属性的值通常是服务器端的一个URL,用于接收并处理表单数据。服务器端的脚本或程序会根据表单中的数据执行相应的操作,比如将数据存储到数据库中、发送电子邮件、进行身份验证等。

method

method是 HTML
元素的一个属性,用于指定表单数据的提交方法。常见的提交方法有GETPOST`。

  • 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.下载文件流程

文件下载的过程通常如下:

  1. 客户端发起请求:用户在浏览器中点击下载链接或按钮,或者在应用程序中触发文件下载操作。浏览器向服务器发送一个下载文件的请求。
  2. 服务器处理请求:服务器接收到客户端的下载请求后,根据请求的内容生成相应的文件内容。
  3. 服务器发送响应:服务器将文件内容作为响应发送给客户端。响应通常包含标准的HTTP头部信息,包括文件类型(Content-Type)、文件大小(Content-Length)等,以及实际的文件数据。
  4. 客户端接收响应:浏览器或应用程序接收到服务器发送的响应后,根据响应中的文件数据进行相应的处理。通常浏览器会弹出一个文件下载对话框,提示用户选择文件保存的位置,并提供一个保存按钮用于开始下载文件。
  5. 文件保存到本地:用户点击保存按钮后,浏览器将文件保存到指定的位置。如果文件已经存在,可能会提示用户覆盖文件或重命名文件。
  6. 下载完成:文件下载完成后,用户可以在本地设备中找到并使用下载的文件。

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);
        });
});

效果图

文件下载

文件在浏览器上展示

相关推荐
懒惰才能让科技进步18 分钟前
从零学习大模型(十二)-----基于梯度的重要性剪枝(Gradient-based Pruning)
人工智能·深度学习·学习·算法·chatgpt·transformer·剪枝
Ni-Guvara32 分钟前
函数对象笔记
c++·算法
AskHarries1 小时前
Java字节码增强库ByteBuddy
java·后端
泉崎1 小时前
11.7比赛总结
数据结构·算法
你好helloworld1 小时前
滑动窗口最大值
数据结构·算法·leetcode
佳佳_1 小时前
Spring Boot 应用启动时打印配置类信息
spring boot·后端
AI街潜水的八角2 小时前
基于C++的决策树C4.5机器学习算法(不调包)
c++·算法·决策树·机器学习
白榆maple2 小时前
(蓝桥杯C/C++)——基础算法(下)
算法
JSU_曾是此间年少2 小时前
数据结构——线性表与链表
数据结构·c++·算法
许野平2 小时前
Rust: 利用 chrono 库实现日期和字符串互相转换
开发语言·后端·rust·字符串·转换·日期·chrono