H5拖放+FormDate接口+NodeJS,完整异步文件上传(一)

  前段时间面试过程中,频繁遇到H5异步文件上传的相关问题。还遇到过一个"通过H5拖放功能实现文件异步上传"的问题,大概知道H5有新增拖拽功能可以接收文件,如何异步上传文件就母鸡了(摊手)。面试结束后,特意去看了相关知识点,了解到H5拖放+FormDate接口可以实现异步上传。为了测试文件上传是否成功,还去看了Node.js如何接收异步文件上传。所以,这会是一个H5拖放+FormDate接口+Node.js实现文件异步上传的完整Demo。
  先简单介绍一下这几个知识点,贴上详细介绍的链接,有兴趣的同学可以点进去多了解一些。

HTML5 拖放

  拖放(Drag 和 drop)是 HTML5 标准的组成部分。拖放是一种常见的特性,即抓取对象以后拖到另一个位置。抓取的对象可以是页面中DOM元素(需要设置draggable="true")或者系统文件。监听放置元素的drop事件,通过DataTransfer对象可以获得拖拽事件的状态及数据。详情可查阅MDN的HTML5 拖放 API文档

FormDate 接口

  XMLHttpRequest Level 2添加了一个新的接口FormData。利用FormData对象,我们可以通过JavaScript用一些键值对来模拟一系列表单控件,我们还可以使用XMLHttpRequest的send()方法来异步的提交这个"表单"。比起普通的ajax,使用FormData的最大优点就是我们可以异步上传一个二进制文件。详情可查阅MDN的FormData接口文档

后端文件接收&保存

  后端使用Node.js+Express+Multer实现文件上传。Express基于 Node.js平台,快速、开放、极简的web开发框架。Multer 是一个 node.js 中间件,用于处理 multipart/form-data 类型的表单数据,它主要用于上传文件。

小二,上代码

新建drop.html,插入以下代码

HTML代码: 先添加一个放置的div,并且监听ondrop和ondragover事件。

<div class="drop-area"  ondrop="drop_hander(event)" ondragover = "dragover_hander(event)"></div>

样式代码: 加个边框,设置一下大小。

.drop-area{
    margin:auto;
    width: 500px;
    height: 500px;
    border:1px pink dashed;
}

JavaScript代码: 监听拖放事件,获取文件,创建XHR实例并发送请求

/* 拖动到放置区域时 */
function dragover_hander (event) {
    /* 必须同时阻止dragover和drop的默认事件
       否则会响应浏览器默认行为
       浏览器能显示的文件会直接显示,例如html文件、图片文件
       浏览器不能显示的文件会出现文件下载弹窗
    */
    event.preventDefault(); 
}

/*拖放完成事件*/
function drop_hander (event) {

    event.preventDefault(); //阻止默认事件

    var files = event.dataTransfer.files; //通过dataTransfer对象获取文件对象数组
    var formData = new FormData(); //声明一个FormData实例

    for(var i = 0, len = files.length; i < len; i++) {
        //使用append方法添加文件到file键
        formData.append('file',  files[i]);
    }

    var request = new XMLHttpRequest(); //创建XHR实例
    request.open('POST', '/process_post'); //初始化请求
    request.send(formData);//发送请求
}

新建formupload.js,写服务端代码:使用express创建服务,使用multer中间保存文件。 这里需要安装express和multer依赖包。这里默认你已经有简单了解Node.js,会使用npm安装依赖包。如果还没接触过,可以看看菜鸟教程的Node.js 教程,看完前四节就行。

const express = require('express'); //引入express模块
const app = express(); //创建一个express应用
const multer = require('multer'); // 引入multer模块

/*
 新建一个multer中间件,设置文件保存路径
 路径必须存在,否则会报错
*/
const upload = multer({ dest: 'uploads/' }); 

/* 请求/drop.html,返回文件 */
app.get('/drop.html', function (req, res) {
   res.sendFile( __dirname + "/" + "drop.html" );
})

/* 
创建提交接口
使用中间件处理
upload.array('file')表示上传一个名为file文件数组
 */
app.post('/process_post', upload.array('file'), function (req, res,next) {
 
  if (!req.files) { // 末上传文件的返回
    res.json({ ok: false });
    return;
  }
  //有上传文件,返回文件列表
  res.json(req.files) 
  return;
})

//启动服务,监听8081端口
var server = app.listen(8081, function () {
 
  var host = server.address().address
  var port = server.address().port
 
  console.log("应用实例,访问地址为 http://%s:%s", host, port)
 
})

到这里代码就结束了,下面是目录结构。完整代码可以查看项目github地址注意:uploads文件夹一定要存在,否则服务会报错

h5-drop-upload
|- /uploads
|- drop.html
|- formupload
|- package.json

打开命令行,在h5-drop-upload目录下执行:

node formupload.js

如果没报错,会输出:

应用实例,访问地址为 http://:::8081

打开浏览器,输入:127.0.0.1:8081/drap.html。然后拖动文件到粉红色的框中,查看upload文件夹,你上传的文件就会这里(为了避免命名冲突,Multer 会修改上传的文件名)。到了这里还没报错,就表示整个“H5拖放+FormDate接口+Node.js”文件上传的Demo已经跑通了,可以结自己鼓掌了。

鼓掌

结束语

  我们已经简单实现文件异步上传功能,但离实际使用场景还有差距。实际使用中,肯定不能拖放完成就马上上传,至少应该显示一个文件列表,用户可以增删文件,最后确认再开始上传。更进一步,最好可以给个进度条,显示文件上传进度。接下来,让我们继续完善,敬请期待下篇。

  如果你已经看这里,麻烦顺便点个赞咯。。。。

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

推荐阅读更多精彩内容