Skip to content

使用简单的前端代码 + koa2搭建一个拖拽文件上传的服务接口

Notifications You must be signed in to change notification settings

lxx2013/upload-setsuna-wang

Repository files navigation

upload-setsuna-wang

使用原生 JS 的前端 + koa2搭建一个拖拽文件上传的服务接口,用作学习练手以及自己使用的图床

接口设计 可参考 sm.ms

计划

  • 初始时简单完成:
    • 文件上传接口 v0.1.0
    • 拖拽相关操作 v0.2.0
    • 图床上的图片链接 v1.0.0
    • laobubu提出的根据一个 url 拿到需打印文档的服务,现在可以在打印店里访问https://i.setsuna.wang来打印
  • 额外的需求:
  • 图片以外的缩略图处理,例如.md .css .doc .ppt .pdf v1.1.0
  • clipboard 支持
  • 图片切割 image?width=200&height=200/webp
  • 后期前端页面切换为vuetify+nuxt
  • 增加第三方的图床 API
    • sm.ms
    • 七牛云
    • 针对三家图床API(包括自己)使用图标颜色来标注 宕机 or 正常服务中
  • 对访客进行统计

总结

0. 绑定document.querySelector$

直接赋值后运行会报错, 报错的原因是 querySelectorAll 所需的执行上下文必需是 document,而我们赋值到 $ 调用后上下文变成了全局 window ,正确的应该是

var $  = document.querySelector.bind(document);
var $$ = document.querySelectorAll.bind(document);

需要注意的地方是,这些方法返回的要么是单个 Node 节点,要么是 NodeList 而 NodeLis 是类数组的对象,但并不是真正的数组,所以拿到之后不能直接使用 map,forEach 等方法。正确方法:

Array.prototype.map.call(document.querySelectorAll('button'),function(element,index){
    element.onclick = function(){
    }
})

1.FileList 对象获取

目前只能通过表单选择文件或者拖拽文件或者剪切板事件

document.querySelector('input').onchange = function() {
  console.log(this.files);
};
//或者拖拽事件
var ipt = document.querySelector('textarea');
ipt.ondragover = function () { return false; };
ipt.ondrop = function(e) {
  e.stopPropagation();
  e.preventDefault();
  e = e || window.event;
  var files = e.dataTransfer.files;
  console.log(files);
};

2. FileList中的 File 对象属性

  • name:文件名,该属性只读。
  • size:文件大小,单位为字节,该属性只读。
  • type:文件的 MIME 类型,如果分辨不出类型,则为空字符串,该属性只读。
  • lastModified:文件的上次修改时间,格式为时间戳。
  • lastModifiedDate:文件的上次修改时间,格式为 Date 对象实例。

3. FileReader 对象

  • readAsText(Blob|File, opt_encoding):返回文本字符串。默认情况下,文本编码格式是’UTF-8’,可以通过可选的格式参数,指定其他编码格式的文本。
  • readAsDataURL

注意:FileList这个对象不是很严谨,它的 length 和 item 等等都能被mapfor..in访问到,因此只能使用 for(var i = 0;i<FileList.�length;i++)来遍历

  • 事件
    • onabort事件:读取中断或调用reader.abort()方法时触发。
    • onerror事件:读取出错时触发。
    • onload事件:读取成功后触发。
    • onloadend事件:读取完成后触发,不管是否成功。触发顺序排在 onload 或 onerror 后面。
    • onloadstart事件:读取将要开始时触发。
    • onprogress事件:读取过程中周期性触发

4. lxxFile.js 执行流程

  • 点击文件选择并通过选择文件使得#fileInput元素触发change事件 => 执行 funGetFiles 函数
    • funGetFile函数中依次执行
      • funDragHover
        • 如果此时e.typedragover就执行onDragOver函数
        • 否则执行onDragLeave函数
      • fileFilter中读取file并使用new FileReader()对应的readAsDataURL(file)来把 base64编码的图像放入 DOM 中 ,其中把 onload 事件回调封装为了 Promise
        readFile: function (file) {
          return new Promise((resolve, reject) => {
            var reader = new FileReader()
            reader.onload = e => {
              resolve(e.target.result)
            }
            reader.onerror = e => {
              reject('readFile error!')
            }
            reader.readAsDataURL(file)
          })
        },
        调用的时候使用await this.readFile(files[i])即可
  • 点击确认上传 => 执行 funUploadFile 函数
    • fileFilter中取出文件并创建 XMLHttpRequest()来以 POST 形式发送new FormData()
    • xhr.readyState == 4 && xhr.status ==200执行onSuccess(file,xhr.responseText)回调
    • xhr.status != 200执行onFailure(file,xhr.responseText)回调
    • fileFilter.length为0时执行onComplete回调, 通常什么也不做

5. 拖拽相关

  • DataTransfer对象可通过e.Datransfer访问
  • 相关事件有dragstart | dragenter | dragleave | dragover | drop | dragend
  • 标准属性有
    • 常用:dropEffect 常用来设置鼠标的脚标样式 有none|copy|link|move四个可选值

    注:有人说该属性仅在dragover事件中设置才有效.经测试在dragleave事件中设置该属性时, Firefox 62.0.3支持/Chrome 69.0不支持. 另外,建议使用dragover事件而非dragenter事件,因为dragenter内设置的dropEffect无法在后续的拖动过程中显示.且enter+drop的组合会遇到drop不生效的问题, hover+drop则正常

    • 常用:files 用来获取被拖拽的文件
    • 不常用: effectAlowed | items(只读) | types(只读)
  • 标准方法:详细见鑫空间
  • 在 div 上绑定ondrop事件等等可能会被子元素(如图片)等触发, 解决方法是在有drag 操作时添加一个 drag 的 className,然后添加 css . 这样可以不影响 hover 伪元素
    .drag *{
      pointer-events: none;
    }

参考文档

About

使用简单的前端代码 + koa2搭建一个拖拽文件上传的服务接口

Resources

Stars

Watchers

Forks

Packages

No packages published