后端之路——文件本地上传

一、基础原理

文件上传是一个很基础的知识点,尤其是本地上传,在现实开发基本都是云上传,但是作为一个基础要简单了解一下

首先前端我就不多讲解了,网页开发里用<form>表单可以上传文件,只需要加上这三属性: 【action="接口路径"】   【method="post"】   【enctype="multipart/form-data"】就可以上传文件了,这里我不打算讲细,因为这主要是讲后端,有兴趣的自己额外研究一下

代码在这,自己直接复制粘贴就行:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>文件上传</title>
    <style>
        .submit{
            width: 100px;
            height: 30px;
            margin-top: 20px;
            margin-left: 120px;
        }
        input{
            height: 30px;
            margin-bottom: 20px;
        }
        form{
            width: 20%;
            border: 1px solid black;
            padding: 20px;
            margin: auto;
            margin-top: 250px;
            display: flex;
            flex-direction: column;
        }
    </style>

</head>
<body>
    <form action="/upload" method="post" enctype="multipart/form-data">
        姓名:<input type="text" name="userName">
        年龄:<input type="text" name="age">
        头像:<input type="file" name="image">
        <input type="submit" value="提交" class="submit">
    </form>
</body>
</html>

提示:

这里为了方便我就直接在【spring boot工程】里写了前端页面,如果要在spring boot工程写前端html页面,必须在【resources】的【static】目录下设置

而且注意,你的html文件的文件名是啥,你到时【接上后端服务之后】访问的前端页面的网址路径就是啥:

在接入后端之前,我们在html文件右上角浏览器临时运行一下就行,后期接上了后端的接口之后再【运行整个后端项目】,然后访问【后端的网址+html文件名】来运行页面

然后打开浏览器的【检查】,右边除了我们常用的Console控制台,还有一个Network网络,谷歌是【Network】,别的可能是中文【网络】

谷歌浏览器Edge浏览器

点到当我们点击【submit提交按钮】时,就会触发一个【请求】,点一下就能展开,就能看到【请求的详情】:

谷歌浏览器

Edge浏览器

然后找到【请求头】(Request Headers),勾选【原始】(Raw)就能看到原请求头代码信息

可以看到【Content-Type】这块有两信息:第一个是表单上传的内容形式,第二个是多个信息上传时,信息之间的分隔符

那么我们具体的信息在哪,可以点到【负载】(Payload)看到我们传过去的信息

上面就是在浏览器查看文件上传的一些基本原理

二、然后讲一下后端怎么获取到上传的资源

注意,前端用<form>的形式发送请求的时候,后端的【请求注解】对应【form的action属性】和【form的method请求方式】、后端的【请求方法的参数名】要对应【form的每个输入框的name属性】

—— 然后后端接收文件参数的数据类型得是【MultipartFile】

当然要是参数名跟form的name属性名不也一样也可以,加一个【@RequestParam(" ")】注解就可以

那么现在在controller层加一个【controller类】,就叫:UpLoadController吧

代码如下:

//写你们自己的路径
//package com.czm.tliaswebmanagement.controller;
//import com.czm.tliaswebmanagement.pojo.Result;

import lombok.extern.slf4j.Slf4j;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.multipart.MultipartFile;

@Slf4j
@RestController
public class UpLoadController {
    @PostMapping("/upload")
    public Result uplaod(String userName, Integer age, MultipartFile image){
        log.info("上传过来的参数{}  {}  {}",userName, age, image);
        return Result.success();
    }
}

接着在运行整个后端项目之前,在你的log.info输出日志的部分打个断点

然后点击【调试】,不要点【运行】,【调试】的话日志才能捕捉到前端发来的请求

然后到前端页面发送一下请求,就会跳到后端看到信息

然后点开“文件”的【location】,这个路径就是我们本地文件的地址

把路径复制到电脑文件夹跳转,就能看到文件了,这里三个文件是对应userName、age、image三个数据

不过这里的原理是:每次上传的时候,后端虽然能接收到文件,但只会生成【临时文件】,再运行完之后就会删除临时文件

只要去掉断点,在重新放行让程序运行完,再回到那个文件夹就会发现那三个文件被清空了

那就需要【文件上传的本地储存

三、后端获取文件后本地储存

因为黑马讲得太细了,而且现实开发里本来本地储存就很少用,那我这里就简短高效讲了

其实上传文件的原理就是:前端把文件变为二进制编码数据,通过后端传送给服务器,然后服务器保存下来这个文件。

那么现在我们本地储存的话,就可以理解本机电脑就是一个服务器了,我们就可以指定将文件保存到哪个位置

代码很简单,逻辑就是1、【获取文件名】,2、调用【文件.transferTo()】方法来指定文件存储路径,然后存储,3、给transferTo()里传入一个【File对象】,参数就是结尾是【文件名】的【绝对路径】字符串

(简单了解不要记,我后面会放源代码在下面,以后直接复制粘贴即可)

写的时候如果报错,那就鼠标悬停,点一下那个提示的帮助方法,就会在方法头那加一个【throws IOException抛出异常】就OK了

但是如果要传递多个文件,如果存在相同文件名的文件,上一个就会被覆盖,比如原来上传了一个【1.png】的文件,后面又上传一个叫【1.png】的文件,就会把上一张覆盖了,所以我们要保证每个文件名要【不同】【唯一】,那么就调用【UUID.randomUUID.toString()】方法获得随机的唯一的乱码字符串,来作为文件名

完整代码:(这就是完整的本地文件存储的代码,以后用到直接来这【复制】就行)

//写你们自己的路径
//package com.czm.tliaswebmanagement.controller;
//import com.czm.tliaswebmanagement.pojo.Result;

import lombok.extern.slf4j.Slf4j;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.multipart.MultipartFile;

import java.io.File;
import java.io.IOException;
import java.util.UUID;

@Slf4j
@RestController
public class UpLoadController {
    @PostMapping("/upload")
    public Result uplaod(String userName, Integer age, MultipartFile image) throws IOException {
        log.info("上传过来的参数{}  {}  {}",userName, age, image);

        /*---------------------------------【本地存储】----------------------------------*/
        //获取本地文件名(比如:1.jpg、 xxx.txt、 qids.png...)
        String originalFileName = image.getOriginalFilename();


        //获取原文件名的后缀名【.jpg】、【.png】、【.html】...
        int index = originalFileName.lastIndexOf(".");
        String extname = originalFileName.substring(index);
        //然后生成一个新的文件名
        String newFileName = UUID.randomUUID().toString() + extname;


        //调用【文件的transferTo】方法,往里面传入一个【File对象】,就可以指定文件【存储的具体路径】
        //当然【存储的具体路径】包括了【前面的绝对路径】+【后面的文件名】
        //下面例子就是把“F:\images\”和“asjhwuhwndm.jpg”拼成“F:\images\asjhwuhwndm.jpg”
        image.transferTo(new File("F:\\images\\" + newFileName));
        /*----------------------------------------------------------------------------*/

        return Result.success();
    }
}

最后一步,去【application.properties】文件,把下面两个代码配置上去,因为文件保存默认限制了单个文件1M以内,多个文件上传也有大小限制,这两个配置你就可以根据自己需要上传大文件了

#配置单个文件最大上传大小
spring.servlet.multipart.max-file-size = 10MB
#配置单个请求最大上传大小(一次请求可以上传多个文件)
spring.servlet.multipart.max-request-size = 100MB

四、发请求试一下

注意发请求这里写接口时,参数换成body的【form-data】,然后类型选【file】

发送请求的时候就点那个【Upload】按钮,上传你的本地文件,这里我传来三次不同的图片,我就不一一演示了

点开文件夹,成功

缺点就是文件本地会爆,所以了解即可,可能会用到,但不多,大部分还是【云存储】

下一篇讲:阿里云OSS云存储文件

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/772583.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

【HarmonyOS NEXT】鸿蒙如何动态添加组件(NodeController)

NodeController用于实现自定义节点的创建、显示、更新等操作的管理&#xff0c;并负责将自定义节点挂载到NodeContainer上。 说明 本模块首批接口从API version 11开始支持 当前不支持在预览器中使用NodeController。 导入模块 import { NodeController } from "ohos…

面试官:JVM调优,主要针对是哪一个区域?JVM内存结构是怎样的?

作为一个Java程序员&#xff0c;在日常的开发中&#xff0c;不必像C/C程序员那样&#xff0c;为每一个内存的分配而操心&#xff0c;JVM会替我们进行自动的内存分配和回收&#xff0c;方便我们开发。但是一旦发生内存泄漏或者内存溢出&#xff0c;如果对Java内存结构不清楚&…

【情绪ABC理论】你为什么生气?清理一下情绪垃圾吧!

心理学有一个著名的情绪ABC理论&#xff0c;认为人的情绪并不是由事件本身引起的&#xff0c;而是由对事件的看法所导致&#xff0c;情绪的困扰某种程度与我们的不合理信念有关。在无法改变事物本身时&#xff0c;转变自己的认识有助于保持阳光心情。 什么是ABC法则&#xff1…

2024最全前端面试系列(计算机网络)(非科班出身最薄弱的环节)

2020最全前端面试系列&#xff08;CSS&#xff09; 2020最全前端面试系列&#xff08;VUE&#xff09; 2020最全前端面试系列&#xff08;浏览器原理&#xff09; 2020最全前端面试系列&#xff08;数据结构&#xff09; 常见状态码 | | 类别 | 原因短语 | | — | — | —…

申请SSL证书 SSL是如何保护网站安全的

随着互联网的不断发展&#xff0c;网络安全问题日益凸显&#xff0c;特别是在数据传输和存储方面。为了保护网站和用户的数据安全&#xff0c;SSL&#xff08;安全套接层&#xff09;技术应运而生&#xff0c;成为了保护网站安全的重要工具。本文将详细介绍SSL如何保护网站安全…

2024-07-04 base SAS programming学习笔记8(HTML)

当使用ODS来进行结果或数据集输出的时候&#xff0c;可以同时设置多个ODS 命令&#xff0c;同时输出到多个不同的文件。使用_ALL_ 表示关闭所有的ODS输出窗口&#xff0c;比如&#xff1a; ods html file(body)"html-file-pathname"; ods html file"pdf-file-pa…

React、JSX简介、渲染列表、基础和复杂的条件渲染

目录 一、简介 1、搭建环境 2、回到项目&#xff08;VScode&#xff09; 3、项目核心渲染路径 4、网站资料&#xff08;启动项目的方法&#xff09; 二、JSX 三、实现渲染列表 四、实现条件渲染 五、实现复杂条件渲染 一、简介 1、搭建环境 npx creat-react-app reac…

【 VIPKID-注册安全分析报告】

前言 由于网站注册入口容易被黑客攻击&#xff0c;存在如下安全问题&#xff1a; 暴力破解密码&#xff0c;造成用户信息泄露短信盗刷的安全问题&#xff0c;影响业务及导致用户投诉带来经济损失&#xff0c;尤其是后付费客户&#xff0c;风险巨大&#xff0c;造成亏损无底洞 …

Soildwoker学习(特征学习4)

本节学习内容&#xff1a; 1、异性孔向导 2、螺纹孔的选择 M6 六角圆柱头螺钉 M6 螺纹孔 3、线性阵列 4、基准轴 5、镜像 特征镜像 实体镜像

Swagger php注解常用语法梳理

Swagger php注解常用语法梳理 快速编写你的 RESTFUL API 接口文档工具&#xff0c;通过注释定义接口和模型&#xff0c;可以和代码文件放置一起&#xff0c;也可以单独文件存放。 Swagger 优势 通过代码注解定义文档&#xff0c;更容易保持代码文档的一致性模型复用&#xff0…

Spring Boot中使用SpringEvent组件

Spring的事件机制是基于观察者模式的实现&#xff0c;主要由以下三个部分组成&#xff1a; 事件&#xff08;Event&#xff09;&#xff1a;事件是应用中发生的重要事情&#xff0c;通常是一个继承自ApplicationEvent的类。 事件发布器&#xff08;Publisher&#xff09;&…

ubuntu使用官方deb文件安装指定版本cuda失败,总是装成最新版

之前安装过最新版的cuda&#xff0c;之后想换用旧版&#xff0c;但是按照官网的说明&#xff0c;sudo apt-get -y install cuda后总是装成最新版的。 解决方法&#xff1a; 最后一步使用sudo apt-get -y install cuda-x-x&#xff0c;直接指定你要安装的cuda的版本号。

python作业一

1. #A. num int(input("请输入要打印的层数:")) for n in range(1, num1):s ""for i in range(1, n1):s f"{i}" " "print(s)#B. num int(input("请输入要打印的层数:")) for i in range(num1, 0, -1):s" "f…

springcloud+vue项目,controller层接口返回json数据,前端可以接收到数据,但浏览器“F12-->网络-->响应“显示为空的问题处理

1.显示为空的场景 SharetekR(access_tokeneyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJsb2dpblR5cGUiOiJsb2dpbiIsImxvZ2luSWQiOiJQQzoxODA1ODA4ODc1MjUwMTIyNzUyIiwicm5TdHIiOiJrZEoxV05CV3NBSUdYb05TbktSU3kzOGNuSnk3c3FRTSIsInVzZXJJZCI6MTgwNTgwODg3NTI1MDEyMjc1MiwidXNlck5h…

分布式数据库HBase:从零开始了解列式存储

在接触过大量的传统关系型数据库后你可能会有一些新的问题: 无法整理成表格的海量数据该如何储存? 在数据非常稀疏的情况下也必须将数据存储成关系型数据库吗? 除了关系型数据库我们是否还有别的选择以应对Web2.0时代的海量数据? 如果你也曾经想到过这些问题, 那么HBase将是…

25届最近5年华北电力大学自动化考研院校分析

华北电力大学&#xff08;北京保定&#xff09; 目录 一、学校学院专业简介 二、考试科目指定教材 三、近5年考研分数情况 四、近5年招生录取情况 五、最新一年分数段图表 六、初试大纲复试大纲 七、学费&奖学金&就业方向 一、学校学院专业简介 二、考试科目指…

【C语言】刷题笔记 Day2

【笔记】 【1】局部变量不初始化&#xff0c;默认放的随机值。 1 int n0; 2 scanf("%d",&n); //13.141 【2】这里虽然输入的是一个浮点数&#xff0c;但是只取整数部分。 【3】3.156e7 表示的是3.156*10的7次方。 【4】多组输入&#xff0c;保存和不保存…

关于Wav2Lip配置实现

模型介绍 Wav2Lip是一种先进的深度学习模型&#xff0c;旨在将音频波形直接转换为面部动画&#xff0c;尤其关注于唇部动作的生成与同步。这一技术的核心在于其能够利用输入的语音信号&#xff0c;生成与之高度匹配的嘴唇动作&#xff0c;从而实现逼真的语音驱动数字人物动画效…

docker初始化运行mysql容器时自动导入数据库存储过程问题

问题&#xff1a;用navicat导出的数据库脚本&#xff0c;在docker初始化运行mysql容器时&#xff0c;导入到存储过程时出错。 ERROR 1064 (42000) at line 2452: You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for t…