• 首页 首页 icon
  • 工具库 工具库 icon
    • IP查询 IP查询 icon
  • 内容库 内容库 icon
    • 快讯库 快讯库 icon
    • 精品库 精品库 icon
    • 问答库 问答库 icon
  • 更多 更多 icon
    • 服务条款 服务条款 icon

前端上传预览文件以和下载,node后端存储文件以和返回前端文件流下载

武飞扬头像
达拉~
帮助1

  1.  
    上传文件
  2.  
    <div class="inputBox" style="background-color: rgb(63, 137, 212);">
  3.  
    上传文件
  4.  
    multiple:接收多个文件上传
  5.  
    <input multiple="multiple" type="file" id="img" />
  6.  
    </div>

input自带的上传文件样式不好看,并且各个浏览器的默认样式不一致,我们需要修改

在外面添加一个盒子,然后将内部的 input 隐藏,修改外部盒子的样式就可以了,但是input隐藏后触发不了事件怎么办呢?这里我们可以使用模拟事件

img就是内部input元素,这样就可以触发选择文件的事件了。

  1.  
    inputBox.addEventListener('click', function () {
  2.  
    // 这里使用模拟事件
  3.  
    let evt = document.createEvent('MouseEvents')
  4.  
    // 初始化事件 三个参数分别为事件类型,是否冒泡,是否阻止默认事件
  5.  
    evt.initEvent('click', false, false)
  6.  
    img.dispatchEvent(evt) //触发事件
  7.  
    }, false)

接下来的功能是选择的文件预览

监听input选择的change事件,因为可能上传多个文件,这里循环处理,使用formdata上传文件,创建formdata实例,后面做判断,我这里只写了图片文件的预览,但是上传的话如果没有在input的属性中规定上传的文件类型,是什么文件都可以的。

在else中执行渲染操作,具体就是将图片转化为base64格式然后创建元素插入并渲染。

render.result就是拿到的base64字符串,这样的话文件的预览就实现了。

  1.  
    img.addEventListener('change', function () {
  2.  
    //this.files就是拿到的文件
  3.  
    console.log(this.files)
  4.  
    formdata = new FormData()
  5.  
    for (var i = 0; i < this.files.length; i ) {
  6.  
    if (this.files[i].type.includes('mp4')) {
  7.  
    formdata.append(`mp4${i}`, this.files[i]); //插入formdata
  8.  
    $span = $(`<span>不支持该类型的预览</span>`)
  9.  
    $(".imgbox").append($span);
  10.  
    } else {
  11.  
    let render = new FileReader()// 创建读取文件类
  12.  
    render.readAsDataURL(this.files[i]);// 读取对应的文件
  13.  
    formdata.append(`img${i}`, this.files[i]); //插入formdata
  14.  
    render.onload = () => {
  15.  
    // 图片预览
  16.  
    $img = $(`<img style="width: 200px;height:200px;vertical-align: top;" src="https://blog.csdn.net/weixin_54968142/article/details/${render.result}" alt="">`)
  17.  
    $(".imgbox").append($img);
  18.  
    }
  19.  
    }
  20.  
    }
  21.  
    })
学新通

上传

这里有两个实现,一个jquery还有一个axios,推荐使用axios,因为他将上传文件的操作独立出来了,可以更方便的实现进度条效果。

  1.  
    $("#btn").click(function (e) {
  2.  
    formdata.append('name', '1111')
  3.  
    if (!$('#img')[0].value) {
  4.  
    alert('上传的文件不能为空')
  5.  
    return false
  6.  
    }
  7.  
    // axios实现
  8.  
    axios({
  9.  
    method: 'post',
  10.  
    url: 'http://localhost:3000/users', //这里写node的接口
  11.  
    data: formdata,
  12.  
    headers: {
  13.  
    //这里必须要写请求头,不然node识别不了
  14.  
    'Content-Type': 'multipart/form-data'
  15.  
    },
  16.  
    onUploadProgress: function (progressEvent) {
  17.  
    console.log(progressEvent)
  18.  
    // 进度条
  19.  
    $(".speed").show()
  20.  
    let percentCompleted = Math.round((progressEvent.loaded * 100) / progressEvent.total)
  21.  
    $(".content").css("width", percentCompleted "%")
  22.  
    if (percentCompleted == 100) {
  23.  
    setTimeout(() => {
  24.  
    $(".speed").hide()
  25.  
    }, 500)
  26.  
    }
  27.  
    }
  28.  
    }).then(res => {
  29.  
    //成功后清空最上面声明的formdata
  30.  
    formdata = new FormData()
  31.  
    }).catch(err => {
  32.  
    console.log(err)
  33.  
    })
  34.  
    // jquery实现
  35.  
    // $.ajax({
  36.  
    // url: "http://localhost:3000/users/?age=1",
  37.  
    // type: "POST",
  38.  
    // data: formdata,
  39.  
    // processData: false, // 表示不需要对数据进行处理
  40.  
    // cache: false,// 不需要对数据进行缓存
  41.  
    // contentType: false,// 不需要设置请求头
  42.  
    // xhr: function () {
  43.  
    // var xhr = new XMLHttpRequest();
  44.  
    // //使用XMLHttpRequest.upload监听上传过程,注册progress事件,打印回调函数中的event事件
  45.  
    // xhr.upload.addEventListener('progress', function (e) {
  46.  
    // //loaded代表上传了多少total代表总数为多少
  47.  
    // var progressRate = (e.loaded / e.total) * 100 '%';
  48.  
    // //进度条
  49.  
    // $('.speed').css('display', 'block');
  50.  
    // $('.content').css('width', progressRate);
  51.  
    // if (progressRate == '100%') {
  52.  
    // setTimeout(() => {
  53.  
    // $('.speed').css('display', 'none');
  54.  
    // }, 500)
  55.  
    // }
  56.  
    // })
  57.  
    // return xhr
  58.  
    // },
  59.  
    // success: (res) => {
  60.  
    // // 清空上一次的文件(也就是新创建一个)
  61.  
    // formdata = new FormData()
  62.  
    // $('#img')[0].value = ''
  63.  
    // $(".imgbox").empty()
  64.  
    // },
  65.  
    // error: (err) => {
  66.  
    // console.log(err)
  67.  
    // }
  68.  
    // })
  69.  
    })
学新通

nodejs部分,这里主要是基于express,首先起服务就不说了

解决跨域,在App.js中添加,注意添加的位置

  1.  
    app.all('*', function (req, res, next) { //处理跨域
  2.  
    res.header("Access-Control-Allow-Origin", "*");
  3.  
    res.header("Access-Control-Allow-Headers", "X-Requested-With,Content-Type");
  4.  
    res.header("Access-Control-Allow-Methods", "PUT,POST,GET,DELETE,OPTIONS");
  5.  
    res.header("X-Powered-By", ' 3.2.1')
  6.  
    res.header("Content-Type", "application/json;charset=utf-8");
  7.  
    next();
  8.  
    });

       node路由

这里我们需要安装一个模块formidable,使用yarn add formidable -s安装,npm安装也可以,推荐使用yarn,他会锁定当前项目依赖的版本,这样别人在下载依赖的时候就不会出现依赖版本问题。

下面可以实现基本的功能,也可以自己做判断分辨文件的类型啊,存储在不同的文件夹等等

  1.  
    // 解析带文件上传的表单需要
  2.  
    const formidable = require("formidable")
  3.  
     
  4.  
    router.post('/', function (req, res, next) {
  5.  
    console.log(req.body)
  6.  
    var form = new formidable.IncomingForm()
  7.  
    // console.log(path.resolve(__dirname, '../'))
  8.  
    //path.resolve(__dirname, '../')代表当前目录的上一级__dirname表示当前的根目录
  9.  
    form.uploadDir = `${path.resolve(__dirname, '../')}/public/images` // 上传目录
  10.  
    form.keepExtensions = true //上传文件保持原来的扩展名
  11.  
    form.parse(req, function (err, fields, files) {
  12.  
    console.log(files) //上传的文件参数
  13.  
    console.log(fields) //上传的除了文件以外的参数
  14.  
    if (err) {
  15.  
    res.send(err)
  16.  
    }
  17.  
    let response = {
  18.  
    msg: `成功上传至${form.uploadDir}`
  19.  
    }
  20.  
    res.send(response)
  21.  
    })
  22.  
    });
学新通

从服务端下载文件

服务端部分,这里我们读取文件后直接返回文件的blob编码,我们在前端响应的时候将相应类型设置为buffer就可以接收到了,我这里还判断了前端需要下载什么类型的文件,目前是有视频和图片。

  1.  
    router.get('/download', async function (req, res, next) {
  2.  
    let { type } = req.query
  3.  
    let video = []
  4.  
    let images = []
  5.  
    let file = ''
  6.  
    const filesName = fs.readdirSync(path.resolve(__dirname, '../public/images'))
  7.  
    function filelist() {//读取文件列表
  8.  
    filesName.forEach(item => {
  9.  
    if (item.includes('mp4')) {
  10.  
    video.push(item)
  11.  
    } else {
  12.  
    images.push(item)
  13.  
    }
  14.  
    })
  15.  
    }
  16.  
    filelist()
  17.  
    function read(url) { //读取文件
  18.  
    filelist()
  19.  
    return new Promise((resolve, rejects) => {
  20.  
    //fs读取文件如果不添加第二个参数data是buffer类型的数据,如果添加的话就是字符串
  21.  
    fs.readFile(`${path.resolve(__dirname, '../')}/public/images/${url}`, function (err, data) {
  22.  
    resolve(data)
  23.  
    rejects(err)
  24.  
    })
  25.  
    })
  26.  
    }
  27.  
    if (type === 'mp4') {
  28.  
    if (video.length === 0) {
  29.  
    res.send({
  30.  
    msg: '视频不存在',
  31.  
    })
  32.  
    } else {
  33.  
    file = video[0]
  34.  
    let data = await read(file)
  35.  
    //如果要前端下载的话这个响应头必须设置
  36.  
    res.setHeader('Content-Type', 'application/octet-stream')
  37.  
    res.send(data)
  38.  
    }
  39.  
    } else {
  40.  
    if (images.length === 0) {
  41.  
    res.send({
  42.  
    msg: '图片不存在',
  43.  
    })
  44.  
    } else {
  45.  
    file = images[0]
  46.  
    let data = await read(file)
  47.  
    //如果要前端下载的话这个响应头必须设置
  48.  
    res.setHeader('Content-Type', 'application/octet-stream')
  49.  
    res.send(data)
  50.  
    }
  51.  
    }
  52.  
    });
学新通

前端

  1.  
    function download(type) {
  2.  
    axios.get(`http://localhost:3000/users/download?type=${type}`, {
  3.  
    responseType: 'blob',
  4.  
    // responseType: 'arraybuffer' //这两种格式都可以,都是二进制流,但是如果使用这个,就不能判断type值了
  5.  
    }).then(res => {
  6.  
    console.log(res)
  7.  
    if (res.data.type.includes('application/json')) {
  8.  
    // blob转json
  9.  
    var reader = new FileReader();
  10.  
    reader.readAsText(res.data,'utf-8');
  11.  
    reader.onload = function (event) {
  12.  
    content = JSON.parse(reader.result);
  13.  
    alert(content.msg)
  14.  
    };
  15.  
    } else {
  16.  
    let url = window.URL.createObjectURL(new Blob([res.data]))
  17.  
    let link = document.createElement('a')
  18.  
    link.style.display = 'none'
  19.  
    link.href = url
  20.  
    link.setAttribute('download', '资源.' type)
  21.  
    document.body.appendChild(link)
  22.  
    link.click()
  23.  
    document.body.removeChild(link) //下载完成移除元素
  24.  
    window.URL.revokeObjectURL(url) //释放掉blob对象
  25.  
    }
  26.  
    })
  27.  
    }
学新通

这篇好文章是转载于:学新通技术网

  • 版权申明: 本站部分内容来自互联网,仅供学习及演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系,请提供相关证据及您的身份证明,我们将在收到邮件后48小时内删除。
  • 本站站名: 学新通技术网
  • 本文地址: /boutique/detail/tanhggafbk
系列文章
更多 icon
同类精品
更多 icon
继续加载