js判断文件类型详解

news2024/11/18 4:32:04

js判断文件类型详解

通过file的type属性判断

<input type="file" onchange="onchangecb(this)" />
<script>
function onchangecb(e) {
  const file = e.files[0];
  console.log(file.type);
}
</script>

htmlinput标签,就是根据选择文件的后缀来生成一个File对象。

像下面的几种文件:

txt文件:
在这里插入图片描述

jpg文件:
在这里插入图片描述

mp4文件:

在这里插入图片描述

使用文件后缀来判断

function onchangecb(e) {
  const file = e.files[0];
  //获取最后一个.的位置
  const index= file.name.lastIndexOf(".");
  //获取后缀
  const ext = file.name.substr(index+1);
  console.log(ext);
}

在得到文件后缀名后,根据后缀即可判断文件的类型(文件格式)。比如需要判断一个文件是否是图片格式,首先定义一个判断函数:

function isImage(ext) {
 return [
 'png', 'jpg', 'jpeg', 'bmp', 'gif', 'webp', 'psd', 'svg', 'tiff'].
 indexOf(ext.toLowerCase()) !== -1;
}

虽然可以直接通过对象的type属性或者文件后缀来获取文件类型,但是如果强行修改文件后缀,同样可以将其他类型的文件上传至服务器,或者文件压根就没有后缀,那又要怎么判断呢?因此前端需要使用一个更加合理的方式。

根据二进制流及文件头来判断

虽然文件后缀可以手动改,因此可以直接通过读取文件的二进制来判断。

通常来说固定类型的文件头都是相同的,比如说jpeg的文件头是FF D8 FF E0

这里提供一些常用的文件头:

const fileMap = {
  JPEG: "FF D8 FF E0",
  JPG: "FF D8 FF E1",
  PNG: "89 50 4E 47",
  GIF: "47 49 46 38",
  TIFF: "49 49 2A 00",
  BMP: "42 4D",
  DWG: "41 43 31 30",
  PSD: "38 42 50 53",
  RTF: "7B 5C 72 74 66",
  XML: "3C 3F 78 6D 6C",
  HTML: "68 74 6D 6C 3E",
  EML: "44 65 6C 69 76 65 72 79 2D 64 61 74 65 3A",
  DBX: "CF AD 12 FE C5 FD 74 6F",
  PST: "21 42 44 4E",
  XLS: "D0 CF 11 E0",
  DOC: "D0 CF 11 E0",
  MDB: "53 74 61 6E 64 61 72 64 20 4A",
  WPD: "FF 57 50 43",
  PDF: "25 50 44 46 2D 31 2E",
  QDF: "AC 9E BD 8F",
  PWL: "E3 82 85 96",
  ZIP: "50 4B 03 04",
  RAR: "52 61 72 21",
  WAV: "57 41 56 45",
  AVI: "41 56 49 20",
  RAM: "2E 72 61 FD",
  RM: "2E 52 4D 46",
  MPG: "00 00 01 BA",
  MPG: "00 00 01 B3",
  MOV: "6D 6F 6F 76",
  ASF: "30 26 B2 75 8E 66 CF 11",
  MID: "4D 54 68 64",
  MP3: "49 44 33",
};

通过onchange方法获取到选择的文件后,使用FileReader读取文件的二进制,之后判断二进制的前几位是否跟符合相应类型文件的文件头。

以下是一些使用文件头来判断文件类型的简单代码

// 判断文件后缀与该文件内容是否相同类型
async function isSameFileType(file) {
  const suffix = getFileSuffix(file.name).toUpperCase();
  const fileBlobString = await blobToString(file.slice(0, 14));
  // 如果文件类型中没有该类型,默认为false
  if (!(suffix in fileMap)) {
    return false;
  }

  return fileBlobString.includes(fileMap[suffix]);
}

async function blobToString(blob) {
  return new Promise((resolve) => {
    const reader = new FileReader();
    reader.onload = function () {
      const ret = reader.result
        .split("") // 分隔开
        .map((v) => v.charCodeAt()) // 循环返回指定位置的字符的 Unicode 编码
        .map((v) => v.toString(16).toUpperCase()) // 返回十六进制格式
        .map((v) => v.padStart(2, "0")) // 给空的那个填充 00 ,防止空缺
        .join(" "); // 每个子节之间空格隔开
      resolve(ret);
    };
    reader.readAsBinaryString(blob); // 调用之后触发onload事件
  });
  // 二进制=》ascii码=》转成16进制字符串
}

// 获取文件后缀
function getFileSuffix(filename) {
  return filename.substring(filename.lastIndexOf(".") + 1, filename.length);
}

判断是否是png类型:

async function isPng(file) {
  // 同理
  const ret = await blobToString(file.slice(0, 4));
  const ispng = ret === fileMap.PNG;
  return ispng;
}

当然也可以针对图片高宽进行限制:
png二进制中,第18-20位是图片的宽,22-24是高。

获取图片宽高:

function getRectByOffset(file, widthOffset, heightOffset, reverse) {
  let width = await blobToString(file.slice(...widthOffset));
  let height = await blobToString(file.slice(...heightOffset));
  
  const w = parseInt(width.replace(" ", ""), 16);
  const h = parseInt(height.replace(" ", ""), 16);
  return { w, h };
}

修改一下之前判断isPng的方法,加上高宽限制

const IMG_WIDTH_LIMIT = 1000;
const IMG_HEIGHT_LIMIT = 800
function isPng(file) {
  // 同理
  const ret = await this.blobToString(file.slice(0, 4));
  const ispng = ret === fileMap.PNG;
  if (ispng) {
    const { w, h } = await this.getRectByOffset(file, [18, 20], [22, 24]);
    console.log(`png 宽高 ${w},${h}`);
    if (w > IMG_WIDTH_LIMIT || h > IMG_HEIGHT_LIMIT) {
      this.$message.error(
        "png图片宽高不得超过 " + IMG_WIDTH_LIMIT + "和" + IMG_HEIGHT_LIMIT
      );
      return false;
    }
  }
  return ispng;
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/705487.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

地下水数值模拟-Visual modflow Flex软件应用

地下水&#xff08;ground water&#xff09;&#xff0c;是指赋存于地面以下岩石空隙中的水&#xff0c;狭义上是指地下水面以下饱和含水层中的水。在国家标准《水文地质术语》&#xff08;GB/T 14157-93&#xff09;中&#xff0c;地下水是指埋藏在地表以下各种形式的重力水。…

基于协议判断目标机器是否出网

内网渗透中时常会碰到一些不出网的主机&#xff0c;不出网的原因有很多&#xff0c;如常见的有&#xff1a;没有设置网关、系统防火墙或者其他设备设置了出入站限制&#xff0c;只允许特定协议或端口出网等&#xff0c;遇到这种情况时可以用以下命令测试目标主机允许哪些协议出…

桥接模式的学习与使用

1、桥接模式的学习 当你需要将抽象部分与实现部分解耦&#xff0c;使它们可以独立地变化&#xff0c;而又能够灵活地组合在一起时&#xff0c;可以使用桥接模式。桥接模式通过将抽象和实现部分分离&#xff0c;使它们可以独立地进行扩展和变化&#xff0c;同时又能够在运行时动…

代码随想录二战day2

977有序数组的平方 力扣 思路&#xff1a; 第一&#xff1a; 和之前一样的&#xff0c;看见数组我们的第一想法就是使用双指针去解。这道题需要额外开辟一个答案数组去储存结果。 第二&#xff1a; 头指针指向第一个元素&#xff0c;尾指针指向最后一个元素。然后对两个元素分…

RocketMQ安装(Docker)

一、RocketMQ安装之docker 1.下载RockerMQ需要的镜像 docker pull rocketmqinc/rocketmq docker pull styletang/rocketmq-console-ng 2.启动NameServer服务 创建NameServer数据存储路径 mkdir -p /home/rocketmq/data/namesrv/logs /home/rocketmq/data/namesrv/store启动…

拾起王慧文的AI梦,美团冲向“光年之外”?

“十年&#xff0c;我需要休息休息&#xff0c;下一个十年&#xff0c;就托付给兄弟们了&#xff0c;感谢你们。” 2020年底&#xff0c;王慧文在朋友圈写下这句话时&#xff0c;外界本以为这位伴随中国互联网发展而持续创业20年的人物即将告别创业舞台。但是&#xff0c;一个…

Kubernetes创建集群—使用 Minikube 创建集群

一、使用 Minikube 创建集群 1、Kubernetes 集群 Kubernetes 协调一个高可用计算机集群&#xff0c;每个计算机作为独立单元互相连接工作。 Kubernetes 中的抽象允许你将容器化的应用部署到集群&#xff0c;而无需将它们绑定到某个特定的独立计算机。为了使用这种新的部署模型…

keepalived安装与使用(Nginx高可用)

一、Keepalived 简介&#x1f349; 1.什么是Keepalived &#xff1f;&#x1f95d; Keepalived一个基于VRRP 协议来实现的 LVS 服务高可用方案&#xff0c;可以利用其来解决单点故障。一个LVS服务会有2台服务器运行Keepalived&#xff0c;一台为主服务器&#xff08;MASTER&a…

Learn Mongodb DB功能命令索引等搜索 ⑤

作者 : SYFStrive 博客首页 : HomePage &#x1f4dc;&#xff1a; PHP MYSQL &#x1f4cc;&#xff1a;个人社区&#xff08;欢迎大佬们加入&#xff09; &#x1f449;&#xff1a;社区链接&#x1f517; &#x1f4cc;&#xff1a;觉得文章不错可以点点关注 &#x1f44…

layui框架学习(31:下拉菜单模块)

Layui的下拉菜单组件模块dropdown支持动态构建下拉菜单及右键菜单&#xff0c;不同于之前学习的页面元素中的菜单&#xff0c;后者主要是在页面中搭建菜单结构&#xff0c;然后通过设置layui提供的菜单相关的预设类对菜单结构进行样式渲染&#xff0c;而通过dropdown模块则是基…

【单片机】STM32单片机,RTC实时时钟,STM32F103C8T6,程序,万年历,数字时钟

文章目录 基础介绍rtc.hrtc.cmain.c 基础介绍 我以STM32F103C8T6为例&#xff0c;但STM32F103的RTC是通用的&#xff0c;STM32F103C8T6有一个原理图&#xff1a; https://qq742971636.blog.csdn.net/article/details/131288390 用纽扣电池给VBAT供电&#xff08;要共地&…

基于matlab使用多类掩码区域的卷积神经网络对人和汽车的各个实例进行分段(附源码)

一、前言 此示例展示了如何使用基于多类掩码区域的卷积神经网络 &#xff08;R-CNN&#xff09; 对人和汽车的各个实例进行分段。实例分割是一种计算机视觉技术&#xff0c;您可以在其中检测和定位对象&#xff0c;同时为每个检测到的实例生成分割图。 此示例首先演示如何使用…

shardingsphere-proxy 实现postgresql的单库分表

1、docker 安装zookeeper 1、拉取镜像 docker pull zookeeper2、运行容器 docker run -d -e TZ"Asia/Shanghai" -p 2181:2181 -v /home/sunyuhua/docker/zookeeper:/data --name zookeeper --restart always zookeeper3、查看容器是不是运行成功 docker exec -i…

Spring Boot 中的 @SendTo 注解

Spring Boot 中的 SendTo 注解 在 Spring Boot 中&#xff0c;SendTo 注解是一个非常有用的注解&#xff0c;它可以用于实现 WebSocket 的消息转发功能。本文将介绍 SendTo 注解的原理、使用方法和示例代码。 什么是 SendTo 注解 SendTo 注解是 Spring Boot 中用于将消息发送…

个人和企业如何有效保护IP地址?

随着互联网的快速发展&#xff0c;个人和企业对于保护IP地址的重要性越来越清晰。为了帮助读者更好地了解如何有效保护IP地址&#xff0c;以下将介绍几种方法&#xff0c;并提供一些相关的数据和专家意见。 使用防火墙是保护IP地址的一个重要手段。防火墙可以监控和过滤网络流量…

react native 使用Native Module、Intent、广播接收器 实现两个app之间的相互通信

一、react native版本环境: “react”: “18.1.0”, “react-native”: “0.70.6”, “node”: "14.18.2 二、发送端步骤: 在A app中注册一个Native Module模块,使用Intent 连接B app,sendBroadcast 发送广播传递数据。 (1)首先在 /android/app/src/main/java/com/j…

ASP.NET Core MVC从入门到精通[PDF版]

随着技术的发展&#xff0c;ASP.NET Core MVC也推出了好长时间&#xff0c;经过不断的版本更新迭代&#xff0c;已经越来越完善&#xff0c;本系列文章主要讲解ASP.NET Core MVC开发B/S系统过程中所涉及到的相关内容&#xff0c;适用于初学者&#xff0c;在校毕业生&#xff0c…

three.js点材质(PointsMaterial)常用属性设置

一、前景回顾 上一章节简单介绍了下怎么使用点材质和点对象创建物体点对象和点材质介绍 点材质和点对象基本运用示例代码&#xff1a; import * as THREE from "three"; // 导入轨道控制器 import { OrbitControls } from "three/examples/jsm/controls/Orbit…

A核与M核异构通信过程解析

现在越来越多的产品具有M core和A core的异构架构&#xff0c;既能达到M核的实时要求&#xff0c;又能满足A核的生态和算力。比如NXP的i.MX8系列、瑞萨的RZ/G2L系列以及TI的AM62x系列等等。虽然这些处理器的品牌及性能有所不同&#xff0c;但多核通信原理基本一致&#xff0c;都…

Linux操作系统配置代理服务器

PS:本文只是针对Linux操作系统对于代理服务器的配置操作&#xff0c;不涉及广告 1.代理的概念 代理服务器英文全称是Proxy Server&#xff0c;其功能就是代理网络用户去取得网络信息。形象的说&#xff1a;它是网络信息的中转站。在一般情况下&#xff0c;我们使用网络浏览器直…