前端上传预览文件以和下载,node后端存储文件以和返回前端文件流下载
-
上传文件
-
<div class="inputBox" style="background-color: rgb(63, 137, 212);">
-
上传文件
-
multiple:接收多个文件上传
-
<input multiple="multiple" type="file" id="img" />
-
</div>
input自带的上传文件样式不好看,并且各个浏览器的默认样式不一致,我们需要修改
在外面添加一个盒子,然后将内部的 input 隐藏,修改外部盒子的样式就可以了,但是input隐藏后触发不了事件怎么办呢?这里我们可以使用模拟事件
img就是内部input元素,这样就可以触发选择文件的事件了。
-
inputBox.addEventListener('click', function () {
-
// 这里使用模拟事件
-
let evt = document.createEvent('MouseEvents')
-
// 初始化事件 三个参数分别为事件类型,是否冒泡,是否阻止默认事件
-
evt.initEvent('click', false, false)
-
img.dispatchEvent(evt) //触发事件
-
}, false)
接下来的功能是选择的文件预览
监听input选择的change事件,因为可能上传多个文件,这里循环处理,使用formdata上传文件,创建formdata实例,后面做判断,我这里只写了图片文件的预览,但是上传的话如果没有在input的属性中规定上传的文件类型,是什么文件都可以的。
在else中执行渲染操作,具体就是将图片转化为base64格式然后创建元素插入并渲染。
render.result就是拿到的base64字符串,这样的话文件的预览就实现了。
-
img.addEventListener('change', function () {
-
//this.files就是拿到的文件
-
console.log(this.files)
-
formdata = new FormData()
-
for (var i = 0; i < this.files.length; i ) {
-
if (this.files[i].type.includes('mp4')) {
-
formdata.append(`mp4${i}`, this.files[i]); //插入formdata
-
$span = $(`<span>不支持该类型的预览</span>`)
-
$(".imgbox").append($span);
-
} else {
-
let render = new FileReader()// 创建读取文件类
-
render.readAsDataURL(this.files[i]);// 读取对应的文件
-
formdata.append(`img${i}`, this.files[i]); //插入formdata
-
render.onload = () => {
-
// 图片预览
-
$img = $(`<img style="width: 200px;height:200px;vertical-align: top;" src="https://blog.csdn.net/weixin_54968142/article/details/${render.result}" alt="">`)
-
$(".imgbox").append($img);
-
}
-
}
-
}
-
})
上传
这里有两个实现,一个jquery还有一个axios,推荐使用axios,因为他将上传文件的操作独立出来了,可以更方便的实现进度条效果。
-
$("#btn").click(function (e) {
-
formdata.append('name', '1111')
-
if (!$('#img')[0].value) {
-
alert('上传的文件不能为空')
-
return false
-
}
-
// axios实现
-
axios({
-
method: 'post',
-
url: 'http://localhost:3000/users', //这里写node的接口
-
data: formdata,
-
headers: {
-
//这里必须要写请求头,不然node识别不了
-
'Content-Type': 'multipart/form-data'
-
},
-
onUploadProgress: function (progressEvent) {
-
console.log(progressEvent)
-
// 进度条
-
$(".speed").show()
-
let percentCompleted = Math.round((progressEvent.loaded * 100) / progressEvent.total)
-
$(".content").css("width", percentCompleted "%")
-
if (percentCompleted == 100) {
-
setTimeout(() => {
-
$(".speed").hide()
-
}, 500)
-
}
-
}
-
}).then(res => {
-
//成功后清空最上面声明的formdata
-
formdata = new FormData()
-
}).catch(err => {
-
console.log(err)
-
})
-
// jquery实现
-
// $.ajax({
-
// url: "http://localhost:3000/users/?age=1",
-
// type: "POST",
-
// data: formdata,
-
// processData: false, // 表示不需要对数据进行处理
-
// cache: false,// 不需要对数据进行缓存
-
// contentType: false,// 不需要设置请求头
-
// xhr: function () {
-
// var xhr = new XMLHttpRequest();
-
// //使用XMLHttpRequest.upload监听上传过程,注册progress事件,打印回调函数中的event事件
-
// xhr.upload.addEventListener('progress', function (e) {
-
// //loaded代表上传了多少total代表总数为多少
-
// var progressRate = (e.loaded / e.total) * 100 '%';
-
// //进度条
-
// $('.speed').css('display', 'block');
-
// $('.content').css('width', progressRate);
-
// if (progressRate == '100%') {
-
// setTimeout(() => {
-
// $('.speed').css('display', 'none');
-
// }, 500)
-
// }
-
// })
-
// return xhr
-
// },
-
// success: (res) => {
-
// // 清空上一次的文件(也就是新创建一个)
-
// formdata = new FormData()
-
// $('#img')[0].value = ''
-
// $(".imgbox").empty()
-
// },
-
// error: (err) => {
-
// console.log(err)
-
// }
-
// })
-
})
nodejs部分,这里主要是基于express,首先起服务就不说了
解决跨域,在App.js中添加,注意添加的位置
-
app.all('*', function (req, res, next) { //处理跨域
-
res.header("Access-Control-Allow-Origin", "*");
-
res.header("Access-Control-Allow-Headers", "X-Requested-With,Content-Type");
-
res.header("Access-Control-Allow-Methods", "PUT,POST,GET,DELETE,OPTIONS");
-
res.header("X-Powered-By", ' 3.2.1')
-
res.header("Content-Type", "application/json;charset=utf-8");
-
next();
-
});
node路由
这里我们需要安装一个模块formidable,使用yarn add formidable -s安装,npm安装也可以,推荐使用yarn,他会锁定当前项目依赖的版本,这样别人在下载依赖的时候就不会出现依赖版本问题。
下面可以实现基本的功能,也可以自己做判断分辨文件的类型啊,存储在不同的文件夹等等
-
// 解析带文件上传的表单需要
-
const formidable = require("formidable")
-
-
router.post('/', function (req, res, next) {
-
console.log(req.body)
-
var form = new formidable.IncomingForm()
-
// console.log(path.resolve(__dirname, '../'))
-
//path.resolve(__dirname, '../')代表当前目录的上一级__dirname表示当前的根目录
-
form.uploadDir = `${path.resolve(__dirname, '../')}/public/images` // 上传目录
-
form.keepExtensions = true //上传文件保持原来的扩展名
-
form.parse(req, function (err, fields, files) {
-
console.log(files) //上传的文件参数
-
console.log(fields) //上传的除了文件以外的参数
-
if (err) {
-
res.send(err)
-
}
-
let response = {
-
msg: `成功上传至${form.uploadDir}`
-
}
-
res.send(response)
-
})
-
});
从服务端下载文件
服务端部分,这里我们读取文件后直接返回文件的blob编码,我们在前端响应的时候将相应类型设置为buffer就可以接收到了,我这里还判断了前端需要下载什么类型的文件,目前是有视频和图片。
-
router.get('/download', async function (req, res, next) {
-
let { type } = req.query
-
let video = []
-
let images = []
-
let file = ''
-
const filesName = fs.readdirSync(path.resolve(__dirname, '../public/images'))
-
function filelist() {//读取文件列表
-
filesName.forEach(item => {
-
if (item.includes('mp4')) {
-
video.push(item)
-
} else {
-
images.push(item)
-
}
-
})
-
}
-
filelist()
-
function read(url) { //读取文件
-
filelist()
-
return new Promise((resolve, rejects) => {
-
//fs读取文件如果不添加第二个参数data是buffer类型的数据,如果添加的话就是字符串
-
fs.readFile(`${path.resolve(__dirname, '../')}/public/images/${url}`, function (err, data) {
-
resolve(data)
-
rejects(err)
-
})
-
})
-
}
-
if (type === 'mp4') {
-
if (video.length === 0) {
-
res.send({
-
msg: '视频不存在',
-
})
-
} else {
-
file = video[0]
-
let data = await read(file)
-
//如果要前端下载的话这个响应头必须设置
-
res.setHeader('Content-Type', 'application/octet-stream')
-
res.send(data)
-
}
-
} else {
-
if (images.length === 0) {
-
res.send({
-
msg: '图片不存在',
-
})
-
} else {
-
file = images[0]
-
let data = await read(file)
-
//如果要前端下载的话这个响应头必须设置
-
res.setHeader('Content-Type', 'application/octet-stream')
-
res.send(data)
-
}
-
}
-
});
前端
-
function download(type) {
-
axios.get(`http://localhost:3000/users/download?type=${type}`, {
-
responseType: 'blob',
-
// responseType: 'arraybuffer' //这两种格式都可以,都是二进制流,但是如果使用这个,就不能判断type值了
-
}).then(res => {
-
console.log(res)
-
if (res.data.type.includes('application/json')) {
-
// blob转json
-
var reader = new FileReader();
-
reader.readAsText(res.data,'utf-8');
-
reader.onload = function (event) {
-
content = JSON.parse(reader.result);
-
alert(content.msg)
-
};
-
} else {
-
let url = window.URL.createObjectURL(new Blob([res.data]))
-
let link = document.createElement('a')
-
link.style.display = 'none'
-
link.href = url
-
link.setAttribute('download', '资源.' type)
-
document.body.appendChild(link)
-
link.click()
-
document.body.removeChild(link) //下载完成移除元素
-
window.URL.revokeObjectURL(url) //释放掉blob对象
-
}
-
})
-
}
这篇好文章是转载于:学新通技术网
- 版权申明: 本站部分内容来自互联网,仅供学习及演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系,请提供相关证据及您的身份证明,我们将在收到邮件后48小时内删除。
- 本站站名: 学新通技术网
- 本文地址: /boutique/detail/tanhggafbk
-
photoshop保存的图片太大微信发不了怎么办
PHP中文网 06-15 -
Android 11 保存文件到外部存储,并分享文件
Luke 10-12 -
《学习通》视频自动暂停处理方法
HelloWorld317 07-05 -
word里面弄一个表格后上面的标题会跑到下面怎么办
PHP中文网 06-20 -
photoshop扩展功能面板显示灰色怎么办
PHP中文网 06-14 -
微信公众号没有声音提示怎么办
PHP中文网 03-31 -
excel下划线不显示怎么办
PHP中文网 06-23 -
excel打印预览压线压字怎么办
PHP中文网 06-22 -
怎样阻止微信小程序自动打开
PHP中文网 06-13 -
TikTok加速器哪个好免费的TK加速器推荐
TK小达人 10-01