文件上传这件小事

起源

我之前一直做的是单图上传,或者单图上传加预览的模式,实现起来都不是那么麻烦,下面都会提到。

而今天给自己挖了个坑,批量上传多张图片,类似这样:

选择上传文件.png

然后我还特想装13,想研究下原理。

从头说这件事

文件上传,html的基础表单组件就提供了该功能的实现,使用非常简单的表单提交就能做。然而可能一些pm觉得图片能实时预览是非常好的用户体验,这时候可以用js来构建form表单异步上传。再往后推,就要求既能批量上传,又能实时预览。说白了感觉用户体验什么的借口感觉都是在挖坑给我们写代码的。

cp1 表单上传

代码优先发言:

<form action="index.php" method="post" enctype="multipart/form-data">
  <input type="file" name="file">
  <input type="submit" value="提交">
</form>

效果图发言:

表单文件上传效果.png

这个体验确实不好,只有文件名,没有文件的内容预览。

后端代码贴个servlet3的

先把servlet加上 <code>@MultipartConfig(maxFileSize=1024x1024x10)</code> 注解,然后逻辑代码如下:

Part part=request.getPart("file");
if (null!=part&&part.getSize()>0) {
  InputStream inputStream=part.getInputStream();
  ByteArrayOutputStream outputStream=new ByteArrayOutputStream();
  byte[] buffer = new byte[1024*100];
  int len=0;
  while ((len=inputStream.read(buffer,0,buffer.length))>0) {
    outputStream.write(buffer,0,len);
  }
  byte[] fileByte=outputStream.toByteArray();
}

拿到byte数组后面的操作代码我就不贴了,有的存本地文件,有的上传到文件服务器,这个因项目架构而定,反正servlet3的后端逻辑差不多就是这样,至于使用其他框架的自行查询对照实现。

cp2 异步上传预览

效果图优先发言:

上传表情并预览.png

这里我使用 jquery 的 fileupload 实现的,当然也有很多极简爱好者自己实现,原理也很简单。

前端代码,跟上面结构一致

<form action="index.php" method="post" enctype="multipart/form-data">
  <input id="selectFile" type="file" name="file">
  <input type="submit" value="提交">
</form>

js代码

$("#selectFile").fileupload({
  dataType: "json",
  url: "/upload/singleFile",
  type: "POST",
  done: function(e, data) {
    $("#selectFile").before('<img src="'+data.result.result+'"/>');
  }
});

这里文件选择好后直接上传到后台,上传完成后插入一个img标签做预览效果。文件的上传和表单的提交是分开的!表单提交的时候只提交文件的编号或者地址,不包含任何文件。

使用框架的好处就是简单方便,缺点是不了解原理,高级特性没办法用。

异步上传文件的原理是,构造一个iframe进行上传,上传完成后获取iframe的内容,作为服务器的返回结果,前端拿到返回的结果后,构造img展示预览图。(这里本来要配代码,无奈之前收藏的书签丢失了,不过不重要,后面有更简单的方式)

cp3 批量上传并预览

虽然前面提到的 jquery 的 fileupload 插件能实现,但是作为一名极简主义者,自然是要自!己!开!发!

前端代码,input加入multiple属性

<form action="index.php" method="post" enctype="multipart/form-data">
  <input id="selectFile" type="file" name="file" multiple="multiple">
  <input type="submit" value="提交">
</form>

js代码:

因为坑挖的奇葩,需要在图片上传之前做一些前置操作,拿到选择图片的信息:

var files=$("#selectFile")[0].files;
for (var i = 0; i < files.length; i++) {
  var file=files[i];
  console.log(file);
}

看下打印出来的信息

lastModified:1471099234297
lastModifiedDate:Sat Aug 13 2016 22:40:34 GMT+0800 (中国标准时间)
name:"6.png"
size:26476
type:"image/png"
webkitRelativePath:""

不错,图片类型,大小,图片名都显示出来了,要做前置操作的在这里做抓紧做。

那么我们拿到文件的dom了怎么上传?当是我是懵逼的,因为文件上传,包括插件,单位都是 input ,这是input 里面的东西,怎么上传?

后来找到了一种方法,XMLHttpRequest,构造请求提交表单。构!造!请!求!这不是类似java的HttpClient吗?万能的工具!

核心代码:

var xhr = new XMLHttpRequest();
xhr.open('POST', "index.php", true);
var formData = new FormData();
formData.append('file', file);  // file 为上面拿到的file对象
xhr.onreadystatechange = function(response) {  // 文件上传完毕通知函数
  console.log(xhr.responseText);
}
xhr.send(formData);

具体的实现参照前面cp2就能实现,这里篇幅有限,不多阐述。

结语

有时候js的原理确实该看看,反正又不难,半天的时间就能搞定。

愿每位码农都能在天梯上披襟斩棘,一统逼界,千秋万载。

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 218,858评论 6 508
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 93,372评论 3 395
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 165,282评论 0 356
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 58,842评论 1 295
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 67,857评论 6 392
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 51,679评论 1 305
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 40,406评论 3 418
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 39,311评论 0 276
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 45,767评论 1 315
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,945评论 3 336
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 40,090评论 1 350
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 35,785评论 5 346
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 41,420评论 3 331
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,988评论 0 22
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 33,101评论 1 271
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 48,298评论 3 372
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 45,033评论 2 355

推荐阅读更多精彩内容