【Vue】 前端上传图片时限制只可以按文件夹上传图片( webkitdirectory )

2023-11-12

前言:

         最近再对公司前后端不分离的【  C#、Winform 】系统进行【 Java、Web 】重构,为了保持客户使用习惯所以要高度还原,其中有一个功能就是上传图片时,以文件夹进行上传,要读取文件夹内所有的图片!

        看了挺多大神的博客,也看了【 Element-UI 】 的 el-upload 发现都没有合适的,只能利用 【input 标签的 type 属性】来实现这个需求了!!!

 一、webkitdirectory

    撸代码之前还是先了解一下 input 标签的【webkitdirectory】属性,今天也是主要依赖 这个属性来帮助我们实现需求!

  

 A Boolean indicating whether or not to only allow the user to choose a directory (or directories, if multiple is also present)

一个布尔值,指示是否只允许用户选择一个目录(如果同时存在多个目录,则为一个或多个目录)

这是 MDN 上对 【 webkitdirectory 】属性的解释。一句话,非常通透!

 这段话就不做翻译了,大概我们可以看出来,【webkitdirectory 】属性的兼容性不是特别好,所以对【ie6,ie7.....】兼容的小伙伴要慎用....

二、具体实现

    因为用的是 【Vue2.0】的技术栈,所以演示就直接用 Vue 来做演示了!

  1. Template 设计 

唯一的注意点就是:这里通过【v-show 隐藏 DOM 节点,然后用 ref 获得节点去调用原生 input 的方法】,然后通过 input change 是获取的 e.target 去进行解析; 

<template>
  <div class="receive-img">
    <input
      v-show="false"
      type="file"
      ref="inputFile"
      accept="image/*"
      webkitdirectory
      @change="receiveImg"
    />
    <div class="btn">
      <button @click="chooseImgList">点击选择文件夹</button>
    </div>
    <div class="image-list-container">
      <div v-for="item in imageList" :key="item.imgUrl">
        <div class="image-list-item">
          <el-image fit="cover" :src="item.imgUrl"></el-image>
        </div>
        <div class="image-list-text">
          <div>{{ item.imgName }}</div>
          <div>{{ item.size + "KB" }}</div>
        </div>
      </div>
    </div>
  </div>
</template>

<style lang="scss">
.receive-img {
  width: 100%;
  height: 100%;
  .btn {
    margin: 100px auto 0 auto;
  }
  .image-list-container {
    width: 100%;
    height: 250px;
    display: flex;
    align-items: flex-start;
    justify-content: flex-start;
    border: 1px solid #d2d2d2;
    padding: 0 10px;
    .image-list-item {
      width: 210px;
      height: 210px;
      margin-left: 15px;
      text-align: center;
    }
    .image-list-text {
      width: 210px;
      overflow: hidden;
      text-overflow: ellipsis;
      white-space: nowrap;
      text-align: center;
    }
    .image-list-item:hover {
      cursor: pointer;
    }
  }
}
</style>

2. JavaScript 执行

通过 【 FileReader 】去读取文件的 进而读取出图片的name/path/size ;不过需要注意这里需要手动调用 【API】上传图片,演示的图片是 base64

import uploadFormData from "@/utils/uploadFormData.js"
<script>
export default {
  name: "ReceiveImage",
  data() {
    return {
      imageList: [],
    };
  },
  methods: {
    chooseImgList() {
      if (this.imageList.length == 0) {
        this.$refs["inputFile"].click();
      }
    },
    receiveImage (e) {
      var fmDataList = [];
      var count = e.target.files.length;
      for (let item in e.target.files) {
        let reader = new FileReader();
        const file = e.target.files[item];
        if (typeof file == 'object' && (file.name.indexOf('jpg') > -1 || file.name.indexOf('png') || file.name.indexOf('jpeg'))) {
          reader.readAsDataURL(e.target.files[item]);
          reader.onloadend = (e) => {
            // 这里的e.target就是reader
            let base64 = e.target.result;
            fmDataList.push({ file: base64, fileName: file.name })
            this.imageList.push({ imgName: file.name, size: Math.ceil(file.size / 1000) })
            count--;
            if (count == 0) {
              uploadFormData(fmDataList).then(result => {
                if (result.fileNames) {
                  this.imageList.forEach((t, index) => {
                    t['fileName'] = result.fileNames[index]
                  })
                }
                this.imageListStatus = true;
              })
            }
          }
        }
      }
    },
  },
};
</script>

3. 原生方式实现上传

值得介绍的是上述代码中的封装好的 uploadFormData 方法,因为我们用原生的方式去上传,且上传的是一个二进制流formData ,所以我们就不能再用项目里面已经封装好的 request 去发起请求,而是要用 new XMLHttpRequest(),具体怎么实现,可以看下面实现步骤( 当然具体要看后端 API 怎么去做),以下面为例:

封装 uploadFormData.js 

/**
 * @param {string} file base64格式的图片
 * @param {string} imgFormat 需要转化为 formData 的图片格式
 */
var uploadImgUrl = process.env.VUE_APP_BASE_API + "/common/upload"; // 上传的图片服务器地址
import data2blob from "@/lib/data2blob.js";
import mimes from "@/lib/mimes.js";
import { getToken } from "@/utils/auth";


export default function (files, imgFormat = 'png') {
  // files 就是上面 fmDataList 里的 base64 数组
  const allowImgFormat = ["jpg", "png"];
  const format = allowImgFormat.indexOf(imgFormat) > -1 ? 'jpg' : imgFormat;
  const fmData = new FormData();
  if (Array.isArray(files) && files.length > 0) {
    files.forEach(t =>
      // data2blob() 方法是通过 Blob 转化为二进制流
      fmData.append('file', data2blob(t.file, mimes[format]))
    )
  } else {
    fmData.append('file', data2blob(files, mimes[format]))
  }
  // XMLHttpRequest 去做具体请求
  return new Promise((resolve, reject) => {
    let client = new XMLHttpRequest();
    client.open("POST", uploadImgUrl, true);
    client.withCredentials = false; // 是否支持跨域
    client.onreadystatechange = function () {
      if (this.readyState !== 4) {
        return;
      }
      if (this.status === 200 || this.status === 201) {
        resolve(JSON.parse(this.responseText));
      } else {
        reject(this.status);
      }
    };
    client.setRequestHeader("Authorization", "Bearer " + getToken());
    client.send(fmData);
  })
}

base64 转 二进制 data2blob.js

/**
 * database64文件格式转换为2进制
 *
 * @param  {[String]} data dataURL 的格式为 “data:image/png;base64,****”,逗号之前都是一些说明性的文字,我们只需要逗号之后的就行了
 * @param  {[String]} mime [description]
 * @return {[blob]}      [description]
 */
export default function(data, mime) {
	data = data.split(',')[1];
	data = window.atob(data);
	var ia = new Uint8Array(data.length);
	for (var i = 0; i < data.length; i++) {
		ia[i] = data.charCodeAt(i);
	};

	return new Blob([ia], {
		type: mime
	});
};

文件格式 mimes.js 

export default {
    'jpg': 'image/jpeg',
    'png': 'image/png',
    'gif': 'image/gif',
    'svg': 'image/svg+xml',
    'psd': 'image/photoshop'
};

 


 边记录边学习边成长,加油加油加油~~~~

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

【Vue】 前端上传图片时限制只可以按文件夹上传图片( webkitdirectory ) 的相关文章

随机推荐

  • C#知识结构

    对于一个工作多年的程序员而言 接口 反射 索引器 事件 委托这些耳熟能详的词汇 提起来别说多简单了 但是让老司机坐在那一个人拿起一支笔 把脑海中对C 知识结构进行梳理一下 大抵是写不了多内容的 原因是什么呢 是遗忘 当然不是 每天面对代码的
  • mkdir函数-linux

    mkdir函数 头文件库 include
  • Heron 编译错误:no such package ‘@org_apache_thrift_libthrift//jar’

    错误 ERROR heron heron metricsmgr src java BUILD 5 1 no such package org apache thrift libthrift jar Failed to fetch Maven
  • The 19th ZCPC -G. Easy Glide

    Grammy is playing a boring racing game named Easy Gliding The game s main content is to reach the destination as fast as
  • 安全工具杂烩

    20201103 本来想单独列出来一个文章来记录每个工具 但是发现并没有那么多精力 这里仅仅记录一下看到的一些不错的工具 sdnewhop grinder 据其描述 这个是一个通过shodan或者censys来获取主机信息的工具 是不是跟一
  • 阿里云服务器一直提示安全事件如何解决

    介绍 这几天一直收到阿里云官方的短信和邮箱提示阿里云安全事件提醒 阿里云的官方的客服也打电话询问过我需不需要帮助 由于我的阿里云服务器没有用于商业用途 只是学习的时候使用 所有也就决定自己解决了 影响 由于最近比较忙 就没有怎么注意阿里云短
  • 433MHz工业级无线数传通信模块

    433MHz工业级无线数传通信模块 无线RS232 RS485透明传输 距离1 3000米 DTD465系列工业无线数传模块采用最先进的电子和无线通信技术 能为众多的工业与应用提供高性能 中等距离和可靠数据传输的低成本解决方案 它的工业级电
  • 计算机date时间和‘千年虫事件’

    目录 一 千年虫事件 1 千年虫事件 名词解析 2 应对2000年计算机问题的解决方法 二 Unix Linux 2038问题 Linux系统的几种时间 1 时间戳 date 2 UTC时间和本地时间 timedatectl 3 避免因时间
  • 日精注塑机联网

    不改造程序的话 日精支持输出CSV和txt数据作为其他软件的接口 改造后可以支持63协议 在软件层面日精也有专用的软件 可以看到其实设备厂家提供的软件功能已经非常丰富了 但这类软件最大的缺点是只能自己家的机器使用 要想其他家也兼容进来 既要
  • 【星海随笔】计组数学小课堂

    计算机组成原理 https www bilibili com video BV1ps4y1d73V p 8 16的负一次方既为1 16 16 1 16进制转换为10进制 例如 5 8 5 16 1 8 16 1 十进制转N进制 则除以N 然
  • Transformers中文本生成方法model.generate()参数解释

    本博客仅作为记录 参考 LLM 大语言模型 解码时是怎么生成文本的 爱码网
  • python字符串中所有符合条件的索引

    使用re库中的finditer import re s 1111ah11111ah test re finditer ah s print i for i in test
  • mvp关联activity生命周期_Android MVP架构从入门到精通-真枪实弹

    Android MVP架构从入门到精通 真枪实弹 一 前言 你是否遇到过Activity Fragment中成百上千行代码 完全无法维护 看着头疼 你是否遇到过因后台接口还未写而你不能先写代码逻辑的情况 你是否遇到过用MVC架构写的项目进行
  • VMware Workstation 16 Player 安装Centos 7

    环境准备 VMware Workstation 16 Player 官方下载 https www vmware com products workstation player workstation player evaluation ht
  • Cesium 源码解析 Model(一)

    Cesium中对于3DTiles会解析成Model 特别是3DTile中的B3DM 过程主要是对gltf在Cesium中是如何解析并生成绘制命令的 content model new Model gltf gltfView gltf数据 c
  • 全球数字治理白皮书 附下载

    当今世界 科技革命和产业变革日新月异 数字经济蓬勃发展 深刻改变着人类生产生活方式 对各国经济社会发展 全球治理体系 人类文明进程影响深远 在经济全球化遭遇逆流 保护主义 单边主 义上升的背景下 数字化驱动的新一轮全球化仍蓬勃发展 已成为助
  • QT学习笔记(七)

    第12章 输入与输出 Qt提供了读写字节块的设备类QIODevice QIODevice类是抽象的 无法被实例化 一般是使用它的子类 它包括如下子类 其中 QProcess QTcpSocket QUdpSocket QSslSocket都
  • Java 优先级队列

    文章目录 Java 优先级队列 PriorityQueue简介 继承关系 PriorityQueue示例 Comparable比较器 Comparable接口 Comparator比较器 Comparator接口 底层原理 Java 优先级
  • Unity3d 游戏优化 mono等

    GC问题 1 C 变量分为两种类型 值类型和引用类型 值类型分配在栈区 引用类型分配在堆区 GC关注引用类型 2 GC卡顿原因 堆内存垃圾回收 向系统申请新的堆内存 3 GC触发条件 堆内存分配而当内存不足时 按频率自动触发 手动强行触发
  • 【Vue】 前端上传图片时限制只可以按文件夹上传图片( webkitdirectory )

    前言 最近再对公司前后端不分离的 C Winform 系统进行 Java Web 重构 为了保持客户使用习惯所以要高度还原 其中有一个功能就是上传图片时 以文件夹进行上传 要读取文件夹内所有的图片 看了挺多大神的博客 也看了 Element