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


    前言:

             最近再对公司前后端不分离的【  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 去进行解析; 

    1. <template>
    2. <div class="receive-img">
    3. <input
    4. v-show="false"
    5. type="file"
    6. ref="inputFile"
    7. accept="image/*"
    8. webkitdirectory
    9. @change="receiveImg"
    10. />
    11. <div class="btn">
    12. <button @click="chooseImgList">点击选择文件夹button>
    13. div>
    14. <div class="image-list-container">
    15. <div v-for="item in imageList" :key="item.imgUrl">
    16. <div class="image-list-item">
    17. <el-image fit="cover" :src="item.imgUrl">el-image>
    18. div>
    19. <div class="image-list-text">
    20. <div>{{ item.imgName }}div>
    21. <div>{{ item.size + "KB" }}div>
    22. div>
    23. div>
    24. div>
    25. div>
    26. template>
    27. <style lang="scss">
    28. .receive-img {
    29. width: 100%;
    30. height: 100%;
    31. .btn {
    32. margin: 100px auto 0 auto;
    33. }
    34. .image-list-container {
    35. width: 100%;
    36. height: 250px;
    37. display: flex;
    38. align-items: flex-start;
    39. justify-content: flex-start;
    40. border: 1px solid #d2d2d2;
    41. padding: 0 10px;
    42. .image-list-item {
    43. width: 210px;
    44. height: 210px;
    45. margin-left: 15px;
    46. text-align: center;
    47. }
    48. .image-list-text {
    49. width: 210px;
    50. overflow: hidden;
    51. text-overflow: ellipsis;
    52. white-space: nowrap;
    53. text-align: center;
    54. }
    55. .image-list-item:hover {
    56. cursor: pointer;
    57. }
    58. }
    59. }
    60. style>

    2. JavaScript 执行

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

    1. import uploadFormData from "@/utils/uploadFormData.js"

    3. 原生方式实现上传

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

    封装 uploadFormData.js 

    1. /**
    2. * @param {string} file base64格式的图片
    3. * @param {string} imgFormat 需要转化为 formData 的图片格式
    4. */
    5. var uploadImgUrl = process.env.VUE_APP_BASE_API + "/common/upload"; // 上传的图片服务器地址
    6. import data2blob from "@/lib/data2blob.js";
    7. import mimes from "@/lib/mimes.js";
    8. import { getToken } from "@/utils/auth";
    9. export default function (files, imgFormat = 'png') {
    10. // files 就是上面 fmDataList 里的 base64 数组
    11. const allowImgFormat = ["jpg", "png"];
    12. const format = allowImgFormat.indexOf(imgFormat) > -1 ? 'jpg' : imgFormat;
    13. const fmData = new FormData();
    14. if (Array.isArray(files) && files.length > 0) {
    15. files.forEach(t =>
    16. // data2blob() 方法是通过 Blob 转化为二进制流
    17. fmData.append('file', data2blob(t.file, mimes[format]))
    18. )
    19. } else {
    20. fmData.append('file', data2blob(files, mimes[format]))
    21. }
    22. // XMLHttpRequest 去做具体请求
    23. return new Promise((resolve, reject) => {
    24. let client = new XMLHttpRequest();
    25. client.open("POST", uploadImgUrl, true);
    26. client.withCredentials = false; // 是否支持跨域
    27. client.onreadystatechange = function () {
    28. if (this.readyState !== 4) {
    29. return;
    30. }
    31. if (this.status === 200 || this.status === 201) {
    32. resolve(JSON.parse(this.responseText));
    33. } else {
    34. reject(this.status);
    35. }
    36. };
    37. client.setRequestHeader("Authorization", "Bearer " + getToken());
    38. client.send(fmData);
    39. })
    40. }

    base64 转 二进制 data2blob.js

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

    文件格式 mimes.js 

    1. export default {
    2. 'jpg': 'image/jpeg',
    3. 'png': 'image/png',
    4. 'gif': 'image/gif',
    5. 'svg': 'image/svg+xml',
    6. 'psd': 'image/photoshop'
    7. };

     


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

  • 相关阅读:
    【Rust日报】2023-09-05 cargo-audit 0.18 版本 - 性能、兼容性和安全性改进
    Linux基础命令学习笔记
    PyQt5快速开发与实战 4.1 QMainWindow
    Java 性能优化实战SpringBoot 服务性能优化
    Java基础面试,重载和重写的区别
    【Linux系统管理】05 常用命令 & 06 vim编辑器
    常用机器视觉开发软件介绍
    彻底吃透 JavaScript 的执行机制
    Matter over Wi-Fi : Linux开发环境设置
    Linux账号管理(用户和用户组)
  • 原文地址:https://blog.csdn.net/weixin_56650035/article/details/127114706