写点什么

面试官:GET 能上传图片吗?

作者:喵叔
  • 2021 年 11 月 27 日
  • 本文字数:1101 字

    阅读完需:约 4 分钟

这个问题是我以前带过的实习生在面试的时候遇到的一道面试题,当我听到这个问题的时候我觉得挺有意思,下面我来解答一下这个问题吧。我们都知道图片有两种传输方式 base64 和 file 对象。base64 的本质是字符串,GET 请求的参数在 URL 中,因此直接把图的 base64 数据放到 URL 里是可以实现 GET 请求上传图片的。下面的代码就是将 file 对象转 base64 后上传的代码:


//img参数类型为图片文件或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 会被截断。


TIP:GET 长度限制是浏览器设定的,不是 GET 请求本身设定的,理论上 GET 请求长度是无限长的,是可以传任意大小的图片。


下面来看这个场景:


<form action="http://127.0.0.1:2022/" method="get">    <input type="file" name="img">    <input type="submit"></form>
复制代码


运行代码,选择图片并提交表单,虽然能提交成功,但接口收不到任何 文件。请求 URL 变成了http://127.0.0.1:8080/?img=xxx.jpg,而且未携带图片数据。正常来说 file 对象数据是放在 POST 请求的 body 里,并且使用 form-data 编码。那么我们可以想像 GET 请求是否有 body 呢?答案是有的。GET 和 POST 没有本质上的区别,只是 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
复制代码


底层解析报文时并不关心是什么请求,因此 GET 请求也有 body,可以传 form-data 数据。GET 请求能不能带 body 是 HTTP 协议来定义的。协议是共同遵守的规则,它带来规范和高效。在 HTTP 1.1 的 RFC 文档里并没有禁止 GET 请求携带 body,但也没有定义 GET 请求 body 的语义。这道面试题主要是考察二进制图片转换成 base64、特定场景的 URL 长度的限制以及 HTTP 知识。

用户头像

喵叔

关注

还未添加个人签名 2020.01.14 加入

还未添加个人简介

评论

发布
暂无评论
面试官:GET能上传图片吗?