使用原生 JS 的前端 + koa2搭建一个拖拽文件上传的服务接口,用作学习练手以及自己使用的图床
- 初始时简单完成:
- 文件上传接口
v0.1.0 - 拖拽相关操作
v0.2.0 - 图床上的图片链接
v1.0.0 - laobubu提出的根据一个 url 拿到需打印文档的服务,现在可以在打印店里访问
https://i.setsuna.wang来打印
- 文件上传接口
- 额外的需求:
- 图片以外的缩略图处理,例如
.md .css .doc .ppt .pdfv1.1.0 - clipboard 支持
- 图片切割
image?width=200&height=200/webp - 后期前端页面切换为
vuetify+nuxt - 增加第三方的图床 API
- sm.ms
- 七牛云
- 针对三家图床API(包括自己)使用图标颜色来标注
宕机or正常服务中
- 对访客进行统计
直接赋值后运行会报错, 报错的原因是 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(){
}
})目前只能通过表单选择文件或者拖拽文件或者剪切板事件
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);
};name:文件名,该属性只读。size:文件大小,单位为字节,该属性只读。type:文件的 MIME 类型,如果分辨不出类型,则为空字符串,该属性只读。lastModified:文件的上次修改时间,格式为时间戳。lastModifiedDate:文件的上次修改时间,格式为 Date 对象实例。
readAsText(Blob|File, opt_encoding):返回文本字符串。默认情况下,文本编码格式是’UTF-8’,可以通过可选的格式参数,指定其他编码格式的文本。readAsDataURL
注意:
FileList这个对象不是很严谨,它的 length 和 item 等等都能被map或for..in访问到,因此只能使用for(var i = 0;i<FileList.�length;i++)来遍历
- 事件
onabort事件:读取中断或调用reader.abort()方法时触发。onerror事件:读取出错时触发。onload事件:读取成功后触发。onloadend事件:读取完成后触发,不管是否成功。触发顺序排在 onload 或 onerror 后面。onloadstart事件:读取将要开始时触发。onprogress事件:读取过程中周期性触发
- 点击文件选择并通过选择文件使得
#fileInput元素触发change事件 => 执行funGetFiles函数funGetFile函数中依次执行funDragHover- 如果此时
e.type是dragover就执行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回调, 通常什么也不做
- 从
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; }