今年第三季度工作上完成了一个比较有意思的项目,类似于外包的性质,主要任务就是提供一大堆API,其中一个API是上传附件,完成开发后,对方的程序员问我,这个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(Multipurpose Internet Mail Extensions),它并不是HTTP协议的一部分,就像我们每个人都是独一无二的,有自己的属性,互联网上每个资源也有属性,比如有些资源是图片,有些是视频,有些是HTML页面,MIME规定了每种资源的类型,这个类型不是随便定义的,由IANA负责登记和维护。

说的有点难理解,比如你看到一个URL地址,http://localhost/image.png,我们其实并不是通过.png后缀判断资源类型的,而是通过MIME来获知该资源类型的,这个图片的MIME可能就是image/png(至于客户端如何知晓资源的MIME类型,后面会讲),现在是不是有了点感性的认识了。

MIME类型结构如下:

type/subtype

type相当于某些类型的集合,而subtype相当于子类型。以image/png为例,image表示图片类型集合,png表示某种类型图片。

让我们看几个比较重要的MIME类型:

text/plain
text/html
application/octet-stream
multipart/form-data

其实本篇文章的主角就是multipart/form-data,再等一等,先别着急,再一次说说MIME,从它的英文全称来看,它和mail有关系,是由mail应用定义而来的,一封邮件由多种资源组成,为了将不同类型的资源组成在邮件中,MIME产生了。随着互联网Web的发展,MIME的作用越来越多,扩展也越来越多,MIME概念也逐步移到了Web。

Content Type

现在我们定义了每种资源的MIME类型,那么客户端如何知晓每种资源的MIME类型呢?这时候就要使用Content-Type HTTP Header 头了,比如我们请求一个资源,Web服务器在发送资源的时候,发送了“content-type:image/png” Header 头,这样客户端就知道该资源是一个png图片了。

如果客户端发送了一个 “Content-Type: multipart/form-data;”,代表客户端要上传一个附件。

也就是说 Content-Type 后面的值就是一个 MIME 类型,聪明的同学也猜到了,上传附件和 multipart/form-data MIME 类型有关,确实是!

multipart/form-data

multipart/form-data 这个MIME类型并不是标准的MIME类型,而是因为Web的需要扩展而来的,我们在开发网页的时候为了上传一个文件,会输入以下的HTML标签:

<form action="upload.php" method="post" enctype="multipart/form-data">Select image to upload:<input type="file" name="fileToUpload" id="fileToUpload"><input type="submit" value="Upload Image" name="submit">
</form>

关于HTML表单上传可以参考 https://www.w3.org/TR/html5/s... 或 RFC 1867(Form-based File Upload in HTML,该RFC已经废弃了)。

那么multipart/form-data表示什么呢?multipart互联网上的混合资源,就是资源由多种元素组成,form-data表示可以使用HTML Forms 和 POST 方法上传文件,具体的定义可以参考RFC 7578。

multipart/form-data结构

说了那么多,从HTTP协议的角度,最后看下文件上传的HTTP消息体,使用Postman也容易看出,如下:

POST /api.php HTTP/1.1
Host: localhst
Cache-Control: no-cache
Content-Type: multipart/form-data; boundary=----FormBoundary------FormBoundary
Content-Disposition: form-data; name="file"; filename="file.png"
Content-Type: image/png<图片二进制内容>
------FormBoundary
Content-Disposition: form-data; name="param1"value1
------FormBoundary
Content-Disposition: form-data; name="param2"value2
------FormBoundary--

消息体什么意思呢,如果你自行想使用代码实现文件上传,要根据定义自行封装HTTP消息,接下去我们简单描述一下。

Content-Type: multipart/form-data; boundary=——FormBoundary 表示要上传附件,其中boundary表示分隔符,如果要上传多个表单项,就要使用boundary分割,每个表单项由———FormBoundary开始,以———FormBoundary结尾。每一个表单项又由Content-Type和Content-Disposition组成。

------FormBoundary
Content-Disposition: form-data; name="param1"value1
------FormBoundary

表示普通的一个表单元素,最重要的是理解 Content-Disposition HTTP 消息头,其中第一个参数总是固定不变的form-data,name表示表单元素属性名,回车换行符后面的内容就是元素的值。

接下去重点描述和文件有关的:

------FormBoundary
Content-Disposition: form-data; name="file"; filename="file.png"
Content-Type: image/png

<图片二进制内容>
------FormBoundary
其中多了一个filename参数,表示文件名,Content-Type 告诉服务器这是一个图片,内容就是图片的二进制数据。

其实Content-Disposition这个HTTP header头用途也很广泛,在本文就不重点描述了。

其实要自行封装文件上传,最好的办法就是用自己熟悉的开发语言实现一下,这样印象才更深刻,希望这篇文章对你有用。

网页上传文件的原理详解相关推荐

  1. Jeesite4本地及服务器上传文件、图片详解

    大家过年好,你们的老朋友小Q又回来了,最近一段时间忙于公司项目开发,又加上过年比较忙,所以没能留出时间更新内容,大家是不是有点着急了?公司最近在使用jeesite4开发项目,我呢,对这个框架一点也不熟 ...

  2. java文件流 m.jb51.net_FasfDFS整合Java实现文件上传下载功能实例详解

    今天使用Java代码实现文件的上传和下载.对此作者提供了Java API支持,下载fastdfs-client-java将源码添加到项目中.或者在Maven项目pom.xml文件中添加依赖 org.c ...

  3. JS - 文件上传组件WebUploader使用详解1(带进度的文件上传

    一.基本介绍 1,什么是 WebUploader? WebUploader 是由百度公司团队开发的一个以 HTML5 为主,FLASH 为辅的现代文件上传组件. 官网地址:http://fex.bai ...

  4. php设置上传文件大小限制_php修改上传文件大小限制实例详解

    php修改上传文件大小限制实例详解 php在默认情况下,只允许上传一定大小的文件,当上传文件大小超过这个值时,将会出错.本文章将向大家讲解php.ini中如何修改上传文件大小限制.需要修改的设置有三个 ...

  5. HTML5 多图片上传(前端+后台详解)

    HTML5 多图片上传(前端+后台详解) 1.参考jquery插件库 2.修改代码 3.添加的后台代码 4.删除的后台代码 1.参考jquery插件库 手机端实现多图片上传 2.修改代码 我发现他这里 ...

  6. html页面在ie上出现404怎么解决,ie浏览器网页上有错误解决方法详解

    ie浏览器网页上有错误解决方法详解 最近网友反馈我的浏览器左下角总显示"网页上有错误",我已经修复过IE了,可是不管用.然后在浏览器上看不到网上的视频和图片的播放.在QQ空间上输入 ...

  7. 转 虫师的selenium借助AutoIt识别上传(下载)详解

    selenium借助AutoIt识别上传(下载)详解 2014-12-27 11:26 by 虫师, 755 阅读, 1 评论, 收藏,  编辑 AutoIt目前最新是v3版本,这是一个使用类似BAS ...

  8. 【Postman知识分享】Postman测试下载文件和上传文件(图文详解)

    [辰兮要努力]:hello你好我是辰兮,很高兴你能来阅读,昵称是希望自己能不断精进,向着优秀程序员前行! 博客来源于项目以及编程中遇到的问题总结,偶尔会有读书分享,我会陆续更新Java前端.后台.数据 ...

  9. html web上传文件原理,Web上传文件的原理及实现

    本文为原创,如需转载,请注明作者和出处,谢谢! 现在有很多Web程序都有上传功能,实现上传功能的组件或框架也很多,如基于java的Commons FileUpload.还有Struts1.x和Stru ...

  10. Java网络编程实现文件上传和下载案例详解

    客户端: 文件上传案例的客户端:读取本地文件,上传到服务器,读取服务器回写的数据 明确: 数据源:c:\1.jpg 目的地:服务器 实现步骤: 1.创建一个本地字节输入流FileInputStream ...

最新文章

  1. LinkedList 源码分析
  2. 【转载】程序员有哪些电脑技能让外行感到神奇?
  3. HDUOJ1864最大报销额(01背包)
  4. 《Linux内核设计与实现》读书笔记(十七)- 设备与模块
  5. git 重新关联远程仓库地址
  6. LiDAR点云数据处理(TLS/MLS/ALS)
  7. Unity物体运动时画出轨迹
  8. UE4 图表插件使用文档
  9. matlab自带滤波器,matlab自带滤波器函数小结(图像处理)
  10. 卧槽!还有这种事!马斯克的SpaceX-API 竟然开源了!登顶GitHub热榜!
  11. pycharm清华镜像源使用
  12. 织梦dedecms 内容管理系统模板标签代码参考
  13. linux 网络慢 dns,Linux DNS客户端解析域名慢解决
  14. 5.2 PMBOK--收集需求
  15. java实现姓名转拼音并处理多音字
  16. 苹果cmsV10程序无法搜索影片的处理教程
  17. GIF录制器之-ScreentoGif--非常好用
  18. 002 计算bonus
  19. 等级保护测评工作重点难点_重点保护
  20. 常用相似性、相关性度量指标

热门文章

  1. 小红书运营中常提到的KOC是什么?带你了解KOC和KOL之间的区别
  2. DNS污染的解决方法
  3. VM虚拟机安装WindowsXp_SP3全过程
  4. poj 1287 Networking(最小生成树)
  5. VScode comment translate 无法使用问题
  6. Craft CMS简介
  7. 德鲁克的时间管理法—《可以量化的…
  8. Android批量打包-如何一秒内打完几百个apk渠道包
  9. 深度学习(deep learning)发展史
  10. java 跳跃表_你真的了解跳跃表吗