闲话图片上传
陆陆续续做了不少需要上传图片的项目,场景各种各样,从前后端数据交互来看,有直接从浏览器里发ajax到后端,也有用Node做中间层,在Node端转发到后端。从用户使用方式来看,有在移动端H5页面获取客户端图片,也有在PC端直接上传图片。所以打算做一个总结,梳理不同场景的实现思路以及遇到的问题。
H5页面使用Ajax直接发送到后端
整体思路如下图所示
在H5页面调用JsBridge方法,获取图片的Base64编码,将base64编码转换成Blob二进制文件(图中没有标注出来),接下来在浏览器端构造FormData数据,最后使用Ajax发送到后端,后端返回图片的URL。
在实际项目中,base64编码可以赋值给img
标签的src
属性,用于预览图片(例子可查看FileReader对象 - MDN)。在发送给后端之前,将其转换成Blob二进制文件,代码如下:
1 | /** |
PC页面使用Ajax直接发送到后端
PC和H5页面唯一一个不同点在于获取图片数据的方式不同。H5通过JsBridge方法直接获取图片的Base64编码,而PC端需要我们自己去读取。
通过input:file
标签获取File对象,使用FileReader对象的readAsDataURL方法 - MDN读取File得到Base64编码,将Base64编码转换成Blob二进制文件,最后构造FormData数据。
通过上面两种场景,我们基本能总结出上传图片的思路。
如果觉得不好理解的话,建议先去MDN了解下各个数据类型(File, Blob)的含义,以及和JavaScript中原生数据类型的区别。
Node层转发
出于尝鲜的心理,在最近的一个项目中,我使用了Node层转发的方式来处理图片。沿用前面总结的思路,我们需要获取到图片内容,构造FromData数据,
Node层怎么获取到图片内容呢?,Node层怎么构造FormData数据呢?
我们使用了formidable来接收浏览器端发送的FormData数据,formidable非常好的一点是将文件内容和其他参数分开了,方便我们获取
request有一个 advanced 用法是在使用post方法上传数据时,能构造FormData数据,
完整代码:
1 | var form = new formidable.IncomingForm(); |
当然在Node层构造FormData还有其他方式,比如:form-data。
有一个需要注意的地方,在Node层,是没法像浏览器端那样将Base64编码转换成Blob二进制文件的方法的,我们获取二进制文件内容的方式,是通过createReadStream
创建一个读取的数据流。
ok,总结来看,不管是在浏览器端还是在Node层,我们的最终目的都是要获取图片的二进制文件,然后构造FormData数据,只是在不同环境中,获取二进制文件的方式不同。
希望对大家有帮助 ~