文档章节

实现拖拽上传功能, 学到的技术点总结

Cander0815
 Cander0815
发布于 2017/08/01 19:31
字数 2308
阅读 23
收藏 2

完成托拽上传功能学到的技术点

一、拖拽获取到文件 a). 原理调用原生js提供的 drop系列的事件

  1. dragentetr 当被鼠标拖动的对象进入其容器范围内时触发此事件
  2. dragleave 当被鼠标拖动的对象离开其容器范围内时触发此事件
  3. drop 当被鼠标拖动的对象在容器范围内时被放下时触发此事件
  4. dragover 当某被拖动的对象在另一对象容器范围内拖动时触发此事件 使用时需要给body绑定以上四个事件, 取消浏览器的默认行为(打开文件);
function clearDefault (event) {
    var e = event || window.event
    e.preventDefault()
  }
  document.addEventListener('dragentetr', clearDefault)
  document.addEventListener('dragleave', clearDefault)
  document.addEventListener('drop', clearDefault)
  document.addEventListener('dragover', clearDefault)

b). 在dom上指定一个区域作为我们要拖入文件的区域。一般是一个div;

<div id="dropBox"></div>

为改div绑定上事件,

  1. dragenter 进入事件, 提示用户可以放开鼠标
  2. dragleave 离开区域时, 提示文字恢复为将文件拖至此区域
  3. drop 文件进入此区域时, 可以通过e.dataTransfer.files 这个数组访问到进入次区域的所有文件, 是一个索引数组;可以访问到文件的一些信息
var div = document.querySelector('#dropBox')
  div.addEventListener('dragenter', function (event) {
    var e = event || window.event
    e.preventDefault()
    this.innerHTML = '请释放鼠标'
    this.style.borderColor = 'green'
  })
  div.addEventListener('dragleave', function (event) {
    var e = event || window.event
    e.preventDefault()
    this.style.borderColor = 'red'
    this.innerHTML = '请将文件拖在此区域'
  })
  div.addEventListener('drop', function (event) {
    var e = event || window.event
    e.preventDefault()
    var files = e.dataTransfer.files // 这个是一个索引数组 => [file1, file2]
    // 每个file拥有以下信息 注意: 它们都是只读的
    var file = {
      lastModified: 1500618905073,   // =>这个代表是最后修改时间 格式是时间戳
      lastModifiedDate: 'Fri Jul 21 2017 14:35:05 GMT+0800 (中国标准时间)',  // =>同样也是最后修改的时间 格式是Date形式
      name: '测试文档.docx', // =>文件的名字
      size: 969331,  // =>文件的大小 单位是B 如有需要的话, 需要换算为别的单位
      type: 'application/vnd.openxmlformats-officedocument.wordprocessingml.document', // =>文件的类型
      webkitRelativePath: ''// => MDN上面说 它返回 File 相关的 path 或 URL。
    }
    // 这里我们只是单文件上传, 只取files中第一个文件
    file = files[0]
    // 获取文件的路径采用的是另外一个方法 window.URL.createObjectURL(file) 它的作用是创建一个可以被浏览器识别的路径 是一个网络地址形式的路径信息
    var filePath = window.URL.createObjectURL(file)
    // 根据上面说的我们在控制台打印文件的信息
    console.log('文件名: ' + file.name)
    console.log('大小: ' + bytesToSize(file.size))
    console.log('类型: ' + file.type)
    console.log('路径: ' + filePath)
    /*
     *到这里已经获取到了文件, 可以使用ajax
     *上传到服务器, 也可以使用H5的
     *FileReader
     *读取它的内容
     */
  })
  /*
   *在网上找的换算字节的函数
   *参数: bytes number 待转换的数字
   *输出: 合理的计算后并输出单位 B KB MB...
   */
  function bytesToSize (bytes) {
    if (bytes === 0) return '0 B'
    var k = 1000 // or 1024
    var sizes = ['B', 'KB', 'MB', 'GB', 'TB', 'PB', 'EB', 'ZB', 'YB']
    var i = Math.floor(Math.log(bytes) / Math.log(k))
    return (bytes / Math.pow(k, i)).toPrecision(3) + ' ' + sizes[i]
  }

二、XMLHttpRequest Level 2 XMLHttpRequest Level 2 我喜欢叫它ajax2代 它与第一代相比增加了很多实用的东西这里不做详细说明

  1. 跨域访问, 在后端加上跨域响应头 响应头代码: Access-Control-Allow-Origin: "你自己的域名" ps这篇文章不再做详细的说明
  2. 可以获取服务器端的二进制数据。范例代码: xhr.responseType = 'blob' ; ps这个我也不是很理解, 暂时做为记录
  3. 可以获取数据传输的进度信息。待会下面会详细说明这个。
  4. timeout 属性, 等待一定时间以后,请求未结束, 会触发ontimeout 事件, 认为此次请求超时, 失败。
  5. FormData 属性 自己在js中创建form形式的数据, 而不用像以前那样在html中创建一个不显示的form。待会下面会详细说明这个。 还有很多别的功能, 我会慢慢的补充...
// 创建一个ajax对象
  var xhr = new XMLHttpRequest()
  xhr.open('GET', 'test.do')
  xhr.send()

获取数据传输进度信息 上传于下载调用的是不用对象的onprogress事件 上传触发的是xhr.upload对象的 onprogress事件 下载触发的是xhr对象的onprogress事件

xhr.onprogress = updateProgress
  xhr.upload.onprogress = updateProgress
  function updateProgress (event) {
    if (event.lengthComputable) {
      // event.loaded  已经发送 / 下载的数据量
      // event.total 文件的总数据量
      var completedPercent = event.loaded / event.total
      console.log(completedPercent)
    }
  }
/*
   * 还有一些对应的事件, 这里只提一下
   * load事件:传输成功完成。
   * abort事件:传输被用户取消。
   * error事件:传输中出现错误。
   * loadstart事件:传输开始。
   * loadEnd事件:传输结束,但是不知道成功还是失败。
   */

timeout 请求超时的相关设置

xhr.timeout = 5000 // 单位ms
  xhr.ontimeout = function () { // 请求发起后的5s内为完成 就会结束请求并触发该事件
    console.log('请求错误')
  }

三、FormData 说明 在以前我们的开发中, 获取一个form的input的值时 采用自己定义一个json 键为与后端定义好的name, 值为用jquery选择器找到对应的input,用val()方法获取值。 现在有了FormData以后我们不需要用jquery去获取一个input的val()值, 像下面这样: 在html中写一个form表单

<form id="submit" action="http://test">
  <input type="text" name="username">
  <input type="text" name="pwd">
  <input type="submit" value="提交">
</form>

在js中我们这样写

var submit = document.querySelector('#submit') // 获取到id是submit的表单
  submit.onsubmit = function () {
    var data = new FormData(submit) // 初始化一个formdata对象
    /*
     * 这里我们已经获取到了id为submit中所有input的值
     * 此时我们console.log(data)的话在控制台只能看到一个空对象。
     * 这里我们用ajax发起请求的时候,在chrome的控制台的network选项卡中可以看到它内部的东西
     */
    // 如果需要在data中临时加一个值的时候可以这样的形式加入
    // data.append('name', 'value')
    data.append('enail', '345565@qq.com')
  }

现在就可以上传我在上边拖拽拿到的文件了

function ajaxPushFile (file) {
    // 这里的file就是上面我们获取到的file
    if (!file) {
      return false
    }
    var data = new FormData() // 初始化一个formdata对象 这里没有from元素就不传值
    data.append('files', file) // 将文件加入formdata中
    var xhr = new XMLHttpRequest() // 初始化ajax
    xhr.open('POST', 'http://test')
    xhr.timeout = 10000 // 设置超时
    xhr.responseType = 'text' // 设置响应返回的数据格式
    xhr.onreadystatechange = function (e) {
      if (this.readyState === 4 && this.status === 200) {
        // 获取返回的值
      }
    }
    xhr.ontimeout = function () { // 超时的回调
      alert('上传失败')
    }
    xhr.upload.onprogress = updateProgress // 获取上传进度
    function updateProgress (event) {
      if (event.lengthComputable) {
        // event.loaded  已经发送 / 下载的数据量
        // event.total 文件的总数据量
        var completedPercent = event.loaded / event.total
        console.log(completedPercent)
      }
    }

    xhr.send(data)
  }

到此 拖拽功能完成 这个功能用到了拖拽事件 与 ajax2 与 FormData 技术点

页面全部代码:

<!doctype html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <title>Document</title>
</head>
<style>
* {
    margin: 0;
    padding: 0;
}

#drop {
    width: 500px;
    height: 400px;
    border: 10px dotted red;
}
</style>

<body>
    <div id="drop">
        请将文件拖拽到这里
    </div>
</body>
<script>
function clearDefault(event) {
    var e = event || window.event
    e.preventDefault()
}
document.addEventListener('dragentetr', clearDefault)
document.addEventListener('dragleave', clearDefault)
document.addEventListener('drop', clearDefault)
document.addEventListener('dragover', clearDefault)
var div = document.querySelector('#drop')
div.addEventListener('dragenter', function(event) {
    var e = event || window.event
    e.preventDefault()
    this.innerHTML = '请释放鼠标'
    this.style.borderColor = 'green'
})
div.addEventListener('dragleave', function(event) {
    var e = event || window.event
    e.preventDefault()
    this.style.borderColor = 'red'
    this.innerHTML = '请将文件拖在此区域'
})
div.addEventListener('drop', function(event) {
        var e = event || window.event
        e.preventDefault()
        var files = e.dataTransfer.files // 这个是一个索引数组 => [file1, file2]
            // 每个file拥有以下信息 注意: 它们都是只读的
        var file = {
                lastModified: 1500618905073, // =>这个代表是最后修改时间 格式是时间戳
                lastModifiedDate: 'Fri Jul 21 2017 14:35:05 GMT+0800 (中国标准时间)', // =>同样也是最后修改的时间 格式是Date形式
                name: '测试文档.docx', // =>文件的名字
                size: 969331, // =>文件的大小 单位是B 如有需要的话, 需要换算为别的单位
                type: 'application/vnd.openxmlformats-officedocument.wordprocessingml.document', // =>文件的类型
                webkitRelativePath: '' // => MDN上面说 它返回 File 相关的 path 或 URL。
            }
            // 这里我们只是单文件上传, 只取files中第一个文件
        file = files[0]
            // 获取文件的路径采用的是另外一个方法 window.URL.createObjectURL(file) 它的作用是创建一个可以被浏览器识别的路径 是一个网络地址形式的路径信息
        var filePath = window.URL.createObjectURL(file)
            // 根据上面说的我们在控制台打印文件的信息
        console.log('文件名: ' + file.name)
        console.log('大小: ' + bytesToSize(file.size))
        console.log('类型: ' + file.type)
        console.log('路径: ' + filePath)
            /*
             *到这里已经获取到了文件, 可以使用ajax
             *上传到服务器, 也可以使用H5的
             *FileReader
             *读取它的内容
             */
    })
    /*
     *在网上找的换算字节的函数
     *参数: bytes number 待转换的数字
     *输出: 合理的计算后并输出单位 B KB MB...
     */
function bytesToSize(bytes) {
    if (bytes === 0) return '0 B'
    var k = 1000 // or 1024
    var sizes = ['B', 'KB', 'MB', 'GB', 'TB', 'PB', 'EB', 'ZB', 'YB']
    var i = Math.floor(Math.log(bytes) / Math.log(k))
    return (bytes / Math.pow(k, i)).toPrecision(3) + ' ' + sizes[i]
}
function ajaxPushFile (file) {
    // 这里的file就是上面我们获取到的file
    if (!file) {
      return false
    }
    var data = new FormData() // 初始化一个formdata对象 这里没有from元素就不传值
    data.append('files', file) // 将文件加入formdata中
    var xhr = new XMLHttpRequest() // 初始化ajax
    xhr.open('POST', 'http://test')
    xhr.timeout = 10000 // 设置超时
    xhr.responseType = 'text' // 设置响应返回的数据格式
    xhr.onreadystatechange = function (e) {
      if (this.readyState === 4 && this.status === 200) {
        // 获取返回的值
      }
    }
    xhr.ontimeout = function () { // 超时的回调
      alert('上传失败')
    }
    xhr.upload.onprogress = updateProgress // 获取上传进度
    function updateProgress (event) {
      if (event.lengthComputable) {
        // event.loaded  已经发送 / 下载的数据量
        // event.total 文件的总数据量
        var completedPercent = event.loaded / event.total
        console.log(completedPercent)
        div.innerHTML = '已完成: ' + (completedPercent * 100) + '%'
      }
    }
    xhr.send(data)
  }
</script>

</html>

© 著作权归作者所有

Cander0815

Cander0815

粉丝 3
博文 16
码字总数 9543
作品 0
深圳
前端工程师
私信 提问
Flutter知识点: Drag

效果GIF 需求 7个可拖拽的色块 1个固定的随机颜色色块 同色块则计分 实现需要的Widget Draggable :一个可以被拖拽到DragTarget的widget DragTarget:一个用来接收被拖拽的Draggable的widge...

老实巴交的读书人
2018/07/06
0
0
Vue + Canvas项目总结

演示地址 演示地址 PC端的项目啦,需要在电脑上看哦,而且最好用Chrome打开 引言 这是今年三月份帮学长做的一个项目,陪我度过了两个月的春招生活,整个项目做下来也是学到了很多东西,下面就...

雪碧亦作酒
2018/07/24
0
0
详解javascript拖拽(二)拖拽的应用及示例

上一篇介绍了拖拽的基础知识,这节我们谈谈拖拽的一些应用 HTML5不仅仅定义了拖拽的事件类型,还在事件对象中规范了一个重量级的对象:dataTransfer,借助它,我们可以实现数据传输、拖拽图案...

AndyLaw
2018/12/25
0
0
使用 JavaScript File API 实现文件上传

File API 是 Mozilla 向 W3C 提出的一个草案,旨在用标准 JavaScript API 实现本地文件的读取。File API 将极大地方便 Web 端的文件上传等操作,并有望成为未来的 HTML 5 规范的一部分。本文...

红薯
2011/01/24
2.5K
6
7款基于JavaScript和AJAX的文件上传插件

本文整理了7款基于JavaScript和AJAX的文件上传插件,这些插件基本上都能实现以下功能: 多文件上传 拖拽操作 实时上传进度 自定义上传限制 希望能为你的开发工作带来帮助。 1. jQuery File U...

EDIAGD
2013/09/23
0
0

没有更多内容

加载失败,请刷新页面

加载更多

解决vim打开之后乱码的问题

在Windows中的文档,传输到Linux系统中(使用rz命令),出现乱码 root@localhost ~]# rpm -qf `which iconv` glibc-common-2.17-105.el7.x86_64 [root@localhost ~]# rpm -ihv /mnt/Packages......

寰宇01
39分钟前
2
0
aldi 2017年1月记录

../../tools/CBLAS/lib/cblas_LINUX.a ../../tools/lapack-3.4.2/liblapacke.a \../../tools/lapack-3.4.2/librefblas.a -lgfortran \../../tools/lapack-3.4.2/liblapack.a \../../......

MtrS
40分钟前
2
0
Choerodon如何进行日志收集与告警

作者:董文启 应用程序日志是由软件应用程序记录的事件文件, 它一般包含错误,信息事件和警告。一个良好的日志系统有助于快速发现问题,定位问题,同时也为业务分析起到一定的作用。 传统E...

Choerodon
52分钟前
3
0
js二维码生成插件“jquery.qrcode.min.js”

<!doctype html> <html> <head> <meta charset="utf-8" /> <title>生成二维码</title> <script type='text/javascript' src='http://cdn.staticfile.org/jquery/2.1.1/jquery.min.js'></scri......

泉天下
55分钟前
1
0
Spring AOP之同一个对象方法内部自调用导致事务失效问题

对于像我这种喜欢滥用AOP的程序员,遇到坑也是习惯了,不仅仅是事务,其实只要脱离了Spring容器管理的所有对象,对于SpringAOP的注解都会失效,因为他们不是Spring容器的代理类,SpringAOP,就切入不...

xiaomin0322
今天
2
0

没有更多内容

加载失败,请刷新页面

加载更多

返回顶部
顶部