今年第三季度完成了一个有趣的项目,类似外包的性质。主要任务是提供很多API,其中之一就是上传附件。开发完成后,对方A程序员问我这个API怎么调用,我当时就懵了,因为我自己没有想过这个问题。一般情况下,我只是使用Curl命令行或者Postman来测试API。对于文件上传,我使用Curl来测试,例如:#使用@来引用一个文件$curl-F"param=value"-F"file=@/path/file.png"http://localhost/api.php如果使用Postman测试,如下图:注意form-data和File标签。是不是看起来很简单,现在换个角度,你想以代码的形式上传文件API,怎么办?这也很简单。很多开发语言都有很多现成的库。比如PHP通过Curl库上传文件就非常容易了。再想一想,如果你不使用这些库,你怎么上传文件呢?可能很多人会比较难,所以本文简单说一下文件上传的原理。其实就是按照HTTP协议的定义,封装了一个HTTP报文体。MIME首先要说的是MIME(MultipurposeInternetMailExtensions),它并不是HTTP协议的一部分,就像我们每个人都是独一无二的,有自己的属性一样。Internet上的每个资源也都有属性。比如有的资源是图片,有的是视频,有的是HTML页面,MIME指定了每一种资源的类型。这个类型不是随便定义的,是由IANA注册维护的。有点难懂。比如你看到一个URL地址,http://localhost/image.png,我们不是通过.png后缀来判断资源类型,而是通过MIME来学习资源类型。这个图片的MIME可能是image/png(至于client是怎么知道资源的MIME类型的,后面会讲到),大家现在有没有感性的认识呢?MIME类型结构如下:type/subtypetype相当于某些类型的集合,subtype相当于一个子类型。以image/png为例,image代表图片类型的集合,png代表某一类图片。再来看几个比较重要的MIME类型:text/plaintext/htmlapplication/octet-streammultipart/form-data其实本文的主角是multipart/form-data,等一下,别着急,说说再次,MIME,从它的英文全称来看,与邮件有关,由邮件应用程序定义。一封电子邮件由多个资源组成。为了在电子邮件中组合不同类型的资源,创建了MIME。随着InternetWeb的发展,MIME的功能越来越多,扩展也越来越多,MIME的概念也逐渐走向了Web。ContentType既然我们定义了每个资源的MIME类型,那么客户端如何知道每个资源的MIME类型呢?这个时候就用到了Content-TypeHTTPHeader。比如我们请求一个资源,web服务器在发送资源的时候会发送“content-type:image/png”Header,这样客户端就知道这个资源是一个png图片。如果客户端发送“Content-Type:multipart/form-data;”,则表示客户端要上传附件。也就是说Content-Type后面的值是一个MIME类型。聪明的同学也猜到了,上传附件与multipart/form-dataMIME类型有关,确实如此!multipart/form-datamultipart/form-data这种MIME类型并不是标准的MIME类型,而是因为Web的需要而扩展的。当我们开发网页时,为了上传文件,我们会输入如下HTML标签:
