阿里二面:GET 请求能传图片吗?

共 2706字,需浏览 6分钟

 ·

2022-01-01 14:56

不点蓝字关注,我们哪来故事?




 正文如下 

来源:juejin.im/post/6860253625030017031


从一道面试题说起:GET 请求能传图片吗?

# 前言

曾经遇到的面试题,觉得挺有意思,来说下我的答案及思考过程。

首先,我们要知道的是,图片一般有两种传输方式:base64 和 file对象。

# base64 图片

图片的base64编码想必大家都见过:


base64 的本质是字符串,而 GET 请求的参数在 url 里面,所以直接把图的 base64 数据放到 url 里面,就可以实现 GET 请求传图片。

input 输入框拿到的图是 file 对象,图片 file 对象转 base64 :
// img参数:file文件或者blobconst getBase64 = img => {  return new Promise((resolve,reject) => {    const reader = new FileReader();    reader.onload = e => {      resolve(e.target.result);    };    reader.onerror = e => reject(e);    reader.readAsDataURL(img);  })}

问题来了,GET 请求的 url 长度是有限制的,不同的浏览器长度限制不一样,最长的大概是 10k 左右,根据 base64 的编码原理,base64图片大小比原文件大小大 1/3,所以说 base64 只能传一些非常小的小图,大图的 base64 太长会被截断。但其实这个长度限制是浏览器给的,而不是 GET 请求本身,也就说,在服务端,GET 请求长度理论上无限长,也就是可以传任意大小的图片。微信搜索公众号:程序员开源社区,回复“资源”,获取更多精品学习资料。

# file 对象

我们来看看这个场景:


<form action="http://localhost:8080/" method="get"> <input type="file" name="logo"> <input type="submit">form>

选择图片,然后提交表单,能提交成功,但是接口收不到文件。请求的 url 会变成 http://localhost:8080/?logo=xxx.png,但是不会携带图片数据。正常情况,file 对象数据是放在POST请求的 body 里面,并且是 form-data 编码。那么 GET 请求能否有 body 体呢?答案是可以有。GET 和 POST 并没有本质上的区别,他们只是 HTTP 协议中两种请求方式,仅仅是报文格式不同(或者说规范不同)。做过底层开发的同事可能比较熟悉,之前我们C语言的同事和我讲,我们的 HTTP 请求,他们收到是这样子的:


举个栗子, 一个普通的 GET 请求,他们收到是这样的:

GET /test/?sex=man&name=zhangsan HTTP/1.1Host: http://localhost:8080Accept: application/json, text/plain, */*Accept-Encoding: gzip, deflateAccept-Language: zh-CN,zh;q=0.9Connection: Keep-Alive


POST 请求长这样:

POST /add HTTP/1.1Host: http://localhost:8080Content-Type: application/x-www-form-urlencodedContent-Length: 40Connection: Keep-Alive
sex=man&name=Professional


同样,DELETE、PUT、PATCH 请求,也都是这样的报文。底层解析这个报文的时候,并不关心是什么请求,所以说 GET请求也可以有body 体,也可以传 form-data 数据。有兴趣的可以拿 postman(我用的版本是 v7.30.1) 试一下,看看 GET 请求传图片,接口能不能收到图片文件:


GET 请求能不能带 body 这个事是由 HTTP 协议来定义的。

所谓协议就是大家共同遵守的一套规则,你不遵守某一规则有时候确实不会有大问题,但是其行为表现是什么就不得而知了。协议带来规范化,规范化带来高效。事实是 HTTP 1.1 的 RFC 文档里没有禁止 GET 请求带 body ,但是也没有定义 GET 请求 body 的语义。

参见: tools.ietf.org。
A payload within a GET request message has no defined semantics; sending a payload body on a GET request might cause some existing implementations to reject the request.


# 总结

作为面试题的话,本题大概有两个考点:

1、二进制图片序列化 base64;

2、特定场景的 url 长度限制。

3、部分 http 协议知识。

或者说,真要 get 传图片作为方案的话,需要打通上面两个关键技术问题。面试现场也可以再加一些Blob、TypedArray、图片压缩方案之类的。

PS:如果觉得我的分享不错,欢迎大家随手点赞、在看。

 关注公众号:Java后端编程,回复下面关键字 


要Java学习完整路线,回复  路线 

缺Java入门视频,回复 视频 

要Java面试经验,回复  面试 

缺Java项目,回复: 项目 

进Java粉丝群: 加群 


PS:如果觉得我的分享不错,欢迎大家随手点赞、在看。

(完)




加我"微信获取一份 最新Java面试题资料

请备注:666不然不通过~


最近好文


1、Kafka 3.0重磅发布,弃用 Java 8 的支持!

2、你只会用 ! = null 判空?嘿嘿!

3、这次,Swagger-ui遇到对手了!

4、一个基于Spring Boot+Vue+Redis的物联网智能家居系统

5、本机号码一键登录原理与应用



最近面试BAT,整理一份面试资料Java面试BAT通关手册,覆盖了Java核心技术、JVM、Java并发、SSM、微服务、数据库、数据结构等等。
获取方式:关注公众号并回复 java 领取,更多内容陆续奉上。
明天见(。・ω・。)ノ
浏览 6
点赞
评论
收藏
分享

手机扫一扫分享

分享
举报
评论
图片
表情
推荐
点赞
评论
收藏
分享

手机扫一扫分享

分享
举报