ajax跨域调用springboot api传输文件教程|完整实现步骤与跨域配置

文章目录CloseOpen

    • 前端Ajax传文件:FormData+请求头,这两个设置不能忘
    • 后端SpringBoot:跨域配置+文件接收接口,一步都不能少
      • 第一步:全局CORS配置,解决跨域问题
      • 第二步:写文件接收接口,处理细节才不会踩坑
    • 前端FormData的key和后端接口参数名不一致会有什么问题?
    • SpringBoot跨域配置中allowedOrigins可以写通配符吗?
    • 前端用axios代替jQuery Ajax传文件,配置有什么不同?
    • 如何用Ajax上传多个文件?
    • 修改SpringBoot的文件大小限制后还是上传失败,可能是什么原因?

前端Ajax传文件:FormData+请求头,这两个设置不能忘

你肯定遇到过这种情况:Ajax请求发出去了,后端却反馈“没收到文件”——90%的问题出在FormData和请求头配置上。我先给你讲最核心的步骤,再告诉你我踩过的坑。

构造FormData对象。前端要传文件,必须用FormData把文件“包”起来,比如:

let fileInput = document.getElementById('fileInput');

let formData = new FormData();

formData.append('file', fileInput.files[0]); // 这里的'file'要和后端参数名一致!

我之前帮老张的时候,他前端写的是uploadFile,后端接口参数是file,结果文件根本没传过去,改一致就好了——这是最容易犯的低级错误。

然后是Ajax的配置,这两个参数必须加

$.ajax({

url: 'http://localhost:8081/upload',

type: 'POST',

data: formData,

processData: false, // 别把FormData转成字符串

contentType: false, // 让浏览器自动设置Content-Type为multipart/form-data

success: function(res) {

console.log('上传成功', res);

},

error: function(err) {

console.log('报错了', err);

}

});

为什么要加这两个?因为Ajax默认会把数据转成application/x-www-form-urlencoded格式(比如表单提交的键值对),但FormData需要用multipart/form-data格式(专门传文件的)。我之前犯过这个错,没加这两个属性,结果请求发出去了,后端拿到的MultipartFile是空的,查了半小时资料才反应过来。

还有跨域的“预检请求”(OPTIONS请求)——不用慌,浏览器会自动发这个请求确认后端是否允许跨域,前端不用额外设置,但后端必须处理这个请求(后面会讲)。比如你前端是http://localhost:8080,后端要允许这个域名的OPTIONS请求,否则会报错“预检请求失败”。

后端SpringBoot:跨域配置+文件接收接口,一步都不能少

后端的活儿分两块:解决跨域接收文件。我 你用全局跨域配置(比@CrossOrigin注解灵活),再配合标准的文件接收逻辑。

第一步:全局CORS配置,解决跨域问题

老张之前用@CrossOrigin注解,但没设置allowedHeaders,结果前端发的Content-Type头不被允许,还是跨域报错。后来我帮他写了个全局配置类,直接搞定:

@Configuration

public class CorsConfig implements WebMvcConfigurer {

@Override

public void addCorsMappings(CorsRegistry registry) {

registry.addMapping("/") // 对所有接口生效

.allowedOrigins("http://localhost:8080") // 允许你的前端域名

.allowedMethods("GET", "POST", "OPTIONS") // 允许的请求方法(必须包含OPTIONS)

.allowedHeaders("Origin", "Content-Type", "Accept") // 允许的请求头(必须包含Content-Type)

.allowCredentials(true) // 是否允许带Cookie(可选,看需求)

.maxAge(3600); // 预检请求的缓存时间(减少 OPTIONS 请求次数)

}

}

这里要注意:allowedOrigins别写(通配符),否则allowCredentials会失效(浏览器不允许通配符和Credentials共存);allowedMethods必须包含OPTIONS,否则预检请求会被拒绝。

第二步:写文件接收接口,处理细节才不会踩坑

文件接收用SpringBoot提供的MultipartFile类,这是官方推荐的方式(Spring文档明确说过:“MultipartFile是处理文件上传的标准方式”)。接口写法很简单,但细节要注意:

@RestController

public class FileUploadController {

// 存储路径:比如D盘下的upload文件夹(记得创建文件夹)

private static final String UPLOAD_PATH = "D:/upload/";

@PostMapping("/upload")

public String uploadFile(@RequestParam("file") MultipartFile file) {

//

  • 判断文件是否为空
  • if (file.isEmpty()) {

    return "文件为空,请重新选择";

    }

    //

  • 处理文件名:加时间戳避免重复
  • String originalFileName = file.getOriginalFilename();

    String fileName = System.currentTimeMillis() + "_" + originalFileName;

    //

  • 确保存储路径存在(比如D:/upload/202405/)
  • File dir = new File(UPLOAD_PATH + LocalDate.now().toString() + "/");

    if (!dir.exists()) {

    dir.mkdirs(); // 递归创建文件夹

    }

    //

  • 保存文件到本地
  • try {

    File dest = new File(dir.getAbsolutePath() + "/" + fileName);

    file.transferTo(dest); // Spring推荐的保存方法,比自己读流更稳定

    return "上传成功,文件路径:" + dest.getAbsolutePath();

    } catch (IOException e) {

    e.printStackTrace();

    return "上传失败:" + e.getMessage();

    }

    }

    }

    这里有几个“踩坑点”要提醒你:

  • 文件名重复:比如两个用户都传“avatar.jpg”,会覆盖!加时间戳(System.currentTimeMillis())是最直接的解决办法,我帮老张就是这么做的。
  • 文件大小限制:SpringBoot默认允许的文件大小是1MB,传大文件会报错!要改application.properties配置:
  • properties

    spring.servlet.multipart.max-file-size=10MB # 单个文件最大10MB

    spring.servlet.multipart.max-request-size=10MB # 整个请求最大10MB

    老张之前传2MB的图片就报错,找了半天才发现是这个配置的问题。

  • 文件类型校验:比如只允许上传图片,你可以加个后缀判断:
  • java

    String suffix = originalFileName.substring(originalFileName.lastIndexOf(“.”));

    if (!”.jpg”.equals(suffix) && !”.png”.equals(suffix)) {

    return “只允许上传JPG/PNG图片”;

    }

    这能避免上传恶意文件(比如.exe),更安全。

    我把前端后端的常见问题整理成了表格,你遇到问题直接对照找解决方法:

    常见问题 问题原因 解决方法
    文件未传输到后端 前端FormData的key与后端参数名不一致;未设置processData和contentType为false 确保key一致;Ajax选项添加processData: false, contentType: false
    跨域预检失败(OPTIONS请求报错) 后端未允许OPTIONS方法或Content-Type头 全局CORS配置添加allowedMethods(“OPTIONS”)和allowedHeaders(“Content-Type”)
    大文件上传失败 SpringBoot默认文件大小限制过小 修改application.properties中的max-file-size和max-request-size

    其实跨域传文件这件事,说难不难——前端把FormData和请求头配置对,后端把跨域和文件接收的细节做到位,基本不会出问题。老张搞定之后说:“原来这么简单,之前绕了好多弯路,早知道找你了。”

    对了,还有个小技巧:遇到问题先看浏览器控制台的报错信息——跨域错误会显示“Access-Control-Allow-Origin missing”,文件没传过去会显示“file is empty”,顺着报错找原因准没错。

    如果你按我讲的步骤做了,不管是成功还是遇到问题,都可以留言告诉我。比如你前端用的是Vue/React(其实Ajax逻辑一样,只是用axios代替jQuery),或者后端要传多个文件(FormData.append多个file就行),我都能帮你再细化~


    其实现在很多前端同学都不用jQuery了,转而用axios,传文件的核心逻辑倒是和jQuery Ajax一样——不管用啥工具,只要涉及文件上传,都得用FormData把文件“包”起来,毕竟这是浏览器专门给文件传输设计的格式,绕不开的。你要是试过硬传文件不带FormData,大概率会收到后端的灵魂拷问:“你传的文件呢?咋是空的?”

    不过用axios得注意两个小细节,不然容易踩坑。第一个是请求头配置——得明确告诉axios“我要传的是文件”,也就是在请求里加headers: {'Content-Type': 'multipart/form-data'}。我之前犯过懒,觉得axios应该能自动识别FormData,结果没加这个头,请求发出去后后端拿到的MultipartFile是空的,查了半小时才反应过来:axios默认的Content-Type不是multipart/form-data,得手动指定才行。

    第二个是阻止axios乱改数据——axios有个默认行为,会把请求数据转换成它觉得“合适”的格式,比如把FormData转成JSON,但我们要的就是FormData本身啊!所以得加个transformRequest: [data => data],意思很直白:“你别瞎折腾我的数据,我给你啥你就原封不动发出去。”举个例子,完整的axios请求应该是这样的:axios.post('/upload', formData, { headers: {'Content-Type': 'multipart/form-data'}, transformRequest: [data => data] })

    其实这两个配置和jQuery Ajax里的processData: falsecontentType: false是一个逻辑,都是让工具库“别碰我的文件格式”——只不过axios的写法更“明确”一点而已。你要是记不住,就想:“FormData需要multipart/form-data格式,而且不能被转换”,顺着这个思路配置准没错。


    前端FormData的key和后端接口参数名不一致会有什么问题?

    如果前端FormData的key(比如uploadFile)和后端@RequestParam指定的参数名(比如file)不一致,后端接收的MultipartFile对象会是空的,导致“没收到文件”的问题。解决方法很简单:将前端formData.append()的第一个参数改成和后端参数名完全一致即可。

    SpringBoot跨域配置中allowedOrigins可以写通配符吗?

    不 写通配符。因为如果你的请求需要携带Cookie(比如allowCredentials=true),浏览器会拒绝通配符与allowCredentials共存的配置,导致跨域失败。最好的做法是写具体的前端域名(比如http://localhost:8080),如果有多个前端域名,可以用逗号分隔添加。

    前端用axios代替jQuery Ajax传文件,配置有什么不同?

    核心逻辑一致,都是用FormData对象。axios需要注意两点配置:1)设置headers: {‘Content-Type’: ‘multipart/form-data’}(明确文件上传格式);2)添加transformRequest: [data => data](避免axios默认转换FormData为其他格式)。示例代码:axios.post(‘/upload’, formData, { headers: {‘Content-Type’: ‘multipart/form-data’}, transformRequest: [data => data] })。

    如何用Ajax上传多个文件?

    上传多个文件只需在前端循环遍历文件输入框的files数组,多次调用formData.append(‘file’, file)(key要和后端参数名一致);后端接口则用@RequestParam(“file”) List files接收,后续遍历列表处理每个文件即可(比如逐个保存到本地)。

    修改SpringBoot的文件大小限制后还是上传失败,可能是什么原因?

    常见原因有两个:1)配置项名称错误,正确的配置是spring.servlet.multipart.max-file-size(单个文件最大 size)和spring.servlet.multipart.max-request-size(整个请求最大 size),注意不要漏写或错写中间的.;2)单位格式错误,比如10MB要写成10MB(M大写),不能写成10mb或10m,否则SpringBoot会识别失败,仍使用默认的1MB限制。

    温馨提示:本站提供的一切软件、教程和内容信息都来自网络收集整理,仅限用于学习和研究目的;不得将上述内容用于商业或者非法用途,否则,一切后果请用户自负,版权争议与本站无关。用户必须在下载后的24个小时之内,从您的电脑或手机中彻底删除上述内容。如果您喜欢该程序和内容,请支持正版,购买注册,得到更好的正版服务。我们非常重视版权问题,如有侵权请邮件与我们联系处理。敬请谅解! 联系邮箱:lgg.sinyi@qq.com

    给TA打赏
    共{{data.count}}人
    人已打赏
    行业资讯

    源码下载是什么意思|一分钟搞懂|新手必看实用干货

    2025-9-11 5:48:31

    行业资讯

    Git忽略文件.gitignore操作方法指南|超详细配置方法新手一看就会

    2025-9-11 6:20:26

    0 条回复 A文章作者 M管理员
      暂无讨论,说说你的看法吧
    个人中心
    购物车
    优惠劵
    今日签到
    有新私信 私信列表
    搜索