html原生上传,一个基于HTML5及原生JS的文件上传组件--JohnUploader

587444d3b349

运行效果图

一、组件介绍

基本特点

基于HTML5的FileReader和FormData

可以完成多文件选择,并预览

完成文件的异步上传

原生XHR对象,适配多浏览器

代码

class JohnUploader{

url;

fileField;

vollay;

/**

*

* @param url 文件上传的地址

* @param fileField 一个"文件域"对象

* @param vollay 一个HTMLElement对象,做为img的容器

*/

constructor(url,fileField,vollay){

this.url=url

this.fileField=fileField

this.vollay=vollay

}

/**

* @param nf 一个新的"文件域对象"

* 由于"文件域"是不能够改变内容,所以需要改变这个属性

*/

setFileField(nf){

this.fileField=nf

}

/**

* 本函数的触发时机--文件域的改变事件

* 作用:在画廊中显示选中的图片

*/

selectionShow() {

this.vollay.innerHTML="";

let files = this.fileField.files;

for (let i = 0; i < files.length; i++) {

let file = files[i]

if(!file.isRemoved) {

let reader = new FileReader()

reader.readAsDataURL(file)

reader.onload = event=> {

let img = document.createElement('img')

img.src = reader.result

//点击图片删除(以后改成点击图片上的"删除logo")

img.onclick = event=> {

//为文件加入删除标记

file.isRemoved=true

//重新刷新画廊,从而不显示有删除标记的文件

this.selectionShow()

}

this.vollay.appendChild(img)

}

}

}

};

/**

* //根据给定的表单域,完成文件上传

* @param callback 文件上传完毕的回调函数,callback中的参数为:xhr.reponseText

*/

uploadFile(callback) {

let formData=new FormData();

let files = this.fileField.files;

if(files.length==0||files===null){

alert("没有选择上传文件!")

return;

}

for (let i = 0; i < files.length; i++) {

let file=files[i]

//如果文件没有加删除标记

if(!file.isRemoved)

formData.append('avatar',files[i],files[i].name);

}

let xhr=new XMLHttpRequest();

xhr.open("POST",this.url)

xhr.onreadystatechange=function(){

if(xhr.readyState==4){

callback(xhr.responseText)

}

}

xhr.send(formData)

}

}

二、组件使用演示

HTML部分

Title

img {

height: 100px;

margin: 5px;border: darkgreen 3px solid;padding: 2px;

}

这个文件域是被隐藏掉了

选择要上传的图片

上传画廊中的图片


已经上传的文件

//底部的测试代码

js测试代码

window.οnlοad=function(){

//抓取后台的图片列表

function fetchAllPhotos(url,callback){

let xhr=new XMLHttpRequest();

xhr.open("GET",url)

xhr.onreadystatechange=function(){

if(xhr.readyState==4){

let photos=JSON.parse(xhr.responseText)

callback(photos)

}

}

xhr.send(null)

}

/**

* 将抓取到的图片列表,在targetLocation中显示出来

* @param photos

* @param targetLocation

*/

function fetchAllPhotosCallback(photos,targetLocation){

targetLocation.innerHTML=''

photos.forEach(photo=>{

let img=document.createElement('img')

img.src='images/'+photo

targetLocation.appendChild(img)

})

}

let vollay = document.querySelector("#vollay")

let avatar = document.querySelector('[name="avatar"]')

let photoWall=document.querySelector('#photo-wall')

//这是主角JohnUploader

let uploader=new JohnUploader('upload',avatar,vollay)

//用来处理文件域清空的特殊情况,将来使用该克隆体,再进行克隆,替换掉avatar

let avtarClone=avatar.cloneNode(true)

//用于将"画廊复位"和将"文件域"进行复位

function reset(){

vollay.innerHTML = ''

let avatarClone2=avtarClone.cloneNode(true)

uploader.setFileField(avatarClone2)

avatar.after(avatarClone2)

avatar.remove()

avatar=avatarClone2

avatar.onchange = function(){

uploader.selectionShow()

}

}

//文件域的变化事件

avatar.onchange = function(){

uploader.selectionShow()

}

//抓取并显示后台的所有图片到照片墙

fetchAllPhotos('files',photos=>fetchAllPhotosCallback(photos,photoWall))

//使用button来完成"文件域"的选择文件功能

document.querySelector('#select-file').οnclick=()=>avatar.click()

//文件上传按钮的事件处理

document.querySelector('#upload-file').οnclick=()=> {

let innerAvatar=avatar

uploader.uploadFile(txt => {

//抓取并显示后台的所有图片到照片墙

fetchAllPhotos('files', photos => {

fetchAllPhotosCallback(photos, photoWall)

reset()

})

})

}

}

三、服务器部分Express+multer

项目依赖:

express

multer

项目结构

587444d3b349

项目结构

代码

//app.js

const fs=require('fs')

const express=require('express')

const http=require('http')

//文件上传中间件(指定上传的临时文件夹是/uploads)

const multer=require('multer')

var storage = multer.memoryStorage()

//磁盘临时文件的方案

// let upload = multer({ dest: 'uploads/' })

//内存缓存方案

let upload = multer({ storage: storage })

let app=express();

const FILE_PATH="public/images/"

//HttpServer服务的中间件(public目录下的index.html为首页)

app.use(express.static('public'))

//文件上传的处理(avatar是上传时的filedName)

app.post('/upload', upload.array('avatar',10), function (req, res, next) {

//req.body是普通表单域

//req.files或req.file,是文件域

let msg={

body:req.body,

files:req.files

}

//磁盘临时文件方案,将临时文件上传到/public/images中

// let output=fs.createWriteStream(FILE_PATH+req.file.originalname)

// let input=fs.createReadStream(req.file.path)

// input.pipe(output)

//内存缓存方案

req.files.forEach((file,index)=>{

fs.writeFile(FILE_PATH+file.originalname,file.buffer,function () {

console.log(file.originalname+"....完成"+index)

//最后一个文件处理完毕,直接显示数据

if (index==req.files.length-1){

res.json(msg)

}

})

})

})

//接收前端的请求,返回上传图片的列表

app.get("/files",function (req,res) {

fs.readdir('public/images',function (err,dir) {

res.json(dir)

})

})

//启动Express服务器

let server=http.createServer(app);

server.listen(8000,function () {

console.log("start server at port 8000")

})

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值