验证图片格式
方式一
后缀
function isValidImage(filename) {
// 正则表达式匹配常见的图片格式
const imageRegex = /.(jpg|jpeg|png|gif|bmp|webp)$/;
return imageRegex.test(filename.toLowerCase());
}
方式二
file.type
方式三
根据文件头信息判断
支持的图片格式
const TYPES = {
JPG: "JPG",
JPEG: "JPEG",
PNG: "PNG",
GIF: "GIF",
WEBP: "WEBP",
ICO: "ICO",
BMP: "BMP",
};
文件头信息
const FILE_HEADER_INFO = {
[TYPES.JPG]: {
headerLength: 3, // 代表图片格式的文件头信息长度
hexInfo: "FF D8 FF", // 十六进制图片格式文件头信息
},
[TYPES.JPEG]: {
headerLength: 3,
hexInfo: "FF D8 FF",
},
[TYPES.PNG]: {
headerLength: 4,
hexInfo: "89 50 4E 47",
},
[TYPES.GIF]: {
headerLength: 6,
hexInfo: ["47 49 46 38 39 61", "47 49 46 38 37 61"],
},
[TYPES.WEBP]: {
headerLength: 4,
hexInfo: "52 49 46 46",
},
[TYPES.ICO]: {
headerLength: 4,
hexInfo: "00 00 01 00",
},
[TYPES.BMP]: {
headerLength: 2,
hexInfo: "42 4D",
},
};
如何查看文件的Hex信息
vscode插件:Hex Editor
判断传入的文件内容是否与定义好的数据匹配
/**
*
* @param {*} file 文件对象
* @param {*} imageTypes 所需要支持的图片格式
* @returns {Promise} 返回一个Promise对象
*/
function verifyFormatByBinary(
file,
imageTypes = files.DEFAULTIMAGETYPES
) {
return new Promise(async (resolve, reject) => {
imageTypes = imageTypes.map((item) => item.toUpperCase());
const fileHeaderInfo = filterKeys(files.FILE_HEADER_INFO, imageTypes);
// 遍历文件头匹配信息
for (const format in fileHeaderInfo) {
// headerLength:代表格式的文件头长度;hexInfo:代表格式的标准文件头字符串
const { headerLength, hexInfo } = fileHeaderInfo[format];
// 将文件对象进行截取
const sliceFile = file.slice(0, headerLength);
// 将截取后文件对象转为16进制字符串
const str = await blobToString(sliceFile);
// 将字符串与标准字符串进行匹配
if (Array.isArray(hexInfo) ? hexInfo.includes(str) : str === hexInfo) {
resolve(str);
}
}
reject(false);
});
}
依赖:将文件头二进制数据转为十六进制字符串
async function blobToString(blob) {
// 返回一个二进制ArrayBuffer, ArrayBuffer 对象用来表示通用的原始二进制数据缓冲区。
const buffer = await blob.arrayBuffer();
// 创建一个Uint8Array并将其转为数组, Uint8Array 数组类型表示一个 8 位无符号整型数组,创建时内容被初始化为 0。创建完后,可以以对象的方式或使用数组下标索引的方式引用数组中的元素。
const uintBuffer = [...new Uint8Array(buffer)];
// 将Uint8Array每个元素转为十六进制,再转大写, 个位数补0
const hexArray = uintBuffer.map(item =>
item
.toString(16)
.toUpperCase()
.padStart(2, '0')
);
return hexArray.join(' ');
}
依赖:过滤对象的指定属性
/**
* 过滤对象的指定属性
* @param {*} obj 对象
* @param {*} keysToFilter
* @returns {Object} 返回一个新对象
*/
function filterKeys(obj, keysToFilter) {
return Object.keys(obj)
.filter((key) => keysToFilter.includes(key))
.reduce((newObj, key) => {
newObj[key] = obj[key];
return newObj;
}, {});
}
发布npm包
创建npm账号
创建npm包
npm init
package name: (validate-image)
version: (1.0.0)
description: validate real image
entry point: (index.js)
test command:
git repository:
keywords: image validate
author: kris_zhang
license: (ISC)
About to write to /Users/zhangjiewen/Desktop/projects/study/npm/validate-image/package.json:
{
"name": "validate-image",
"version": "1.0.0",
"description": "validate real image",
"main": "index.js",
"scripts": {
"test": "echo "Error: no test specified" && exit 1"
},
"keywords": [
"image",
"validate"
],
"author": "kris_zhang",
"license": "ISC"
}
license选择
其他配置项
发布npm包
zhangjiewen@zhangjiewendeMacBook-Pro validate-image % npm config set registry https://registry.npmjs.org/
zhangjiewen@zhangjiewendeMacBook-Pro validate-image % npm login
npm WARN adduser `adduser` will be split into `login` and `register` in a future version. `adduser` will become an alias of `register`. `login` (currently an alias) will become its own command.
npm notice Log in on https://registry.npmjs.org/
Username: zhangjiewen
Password:
Email: (this IS public) 474350393@qq.com
npm notice Please check your email for a one-time password (OTP)
Enter one-time password: 91832573
Logged in as zhangjiewen on https://registry.npmjs.org/.
zhangjiewen@zhangjiewendeMacBook-Pro validate-image % npm publish
npm notice
npm notice 📦 validate-image@1.0.0
npm notice === Tarball Contents ===
npm notice 662B index.js
npm notice 288B package.json
npm notice 191B util/hexInfo.json
npm notice === Tarball Details ===
npm notice name: validate-image
npm notice version: 1.0.0
npm notice filename: validate-image-1.0.0.tgz
npm notice package size: 765 B
npm notice unpacked size: 1.1 kB
npm notice shasum: edf0e0b5ddd3e9e7e0eeabf319dcab33cdf96578
npm notice integrity: sha512-Pyx6NjgFXhu4x[...]FRhqBma86GWyA==
npm notice total files: 3
npm notice
npm notice Publishing to https://registry.npmjs.org/
+ validate-image@1.0.0
验证npm包
<template>
<div>
<el-upload
class="avatar-uploader"
:show-file-list="false"
:before-upload="beforeAvatarUpload"
>
<img v-if="imageUrl" :src="imageUrl" class="avatar" />
<el-icon v-else class="avatar-uploader-icon"><Plus /></el-icon>
</el-upload>
<span v-show="validMessage">{{ validMessage }}</span>
</div>
</template>
<script lang="ts" setup>
import { ref } from "vue";
import { ElMessage } from "element-plus";
import { Plus } from "@element-plus/icons-vue";
import fileUtil from "../utils/index";
import validateImage from "validate-image";
import type { UploadProps } from "element-plus";
const imageUrl = ref("");
const validMessage = ref("");
const beforeAvatarUpload: UploadProps["beforeUpload"] = (rawFile) => {
fileUtil
.verifyFormatByBinary(rawFile, ['png', 'webp'])
.then((hexNumber) => {
imageUrl.value = URL.createObjectURL(rawFile);
validMessage.value = `验证成功,文件头Hex为:${hexNumber}`;
})
.catch(() => {
validMessage.value = `验证失败`;
});
return true;
};
</script>
<style scoped>
.avatar-uploader .avatar {
width: 178px;
height: 178px;
display: block;
object-fit: cover;
}
</style>
<style>
.avatar-uploader .el-upload {
border: 1px dashed var(--el-border-color);
border-radius: 6px;
cursor: pointer;
position: relative;
overflow: hidden;
transition: var(--el-transition-duration-fast);
}
.avatar-uploader .el-upload:hover {
border-color: var(--el-color-primary);
}
.el-icon.avatar-uploader-icon {
font-size: 28px;
color: #8c939d;
width: 178px;
height: 178px;
text-align: center;
}
</style>
更新npm包
更新npm version
每次更新应保证版本号唯一
error code E403
error 403 403 Forbidden - PUT http://af.hikvision.com.cn/artifactory/api/npm/npm-BBG/validate-image - forbidden
error 403 In most cases, you or one of your dependencies are requesting
error 403 a package version that is forbidden by your security policy, or
error 403 on a server you do not have access to.
手动
手动修改package.json中的version,可以成功,但不建议,需要手动commit
自动
npm version [ | major | minor | patch | premajor | preminor | prepatch | prerelease | from-git]
The newversion argument should be a valid semver string, a valid second argument to semver.inc (one of patch, minor, major, prepatch, preminor, premajor, prerelease), or from-git. In the second case, the existing version will be incremented by 1 in the specified field. from-git will try to read the latest git tag, and use that as the new npm version.
| npm version | 功能 |
|---|---|
| major | 1. 如果没有预发布号,则直接升级一位大号,其他位置都是0,2. 如果有预发布号:中号和小号都为0,则不升级大号,而是将预发布号删掉。即2.0.0-1变为2.0.0,这就是预发布的作用3. 如果中号和小号任意一个不是0, 那么会升级一位大号,其他位置都为0, 清空预发布号。即2.0.1-1变为3.0.0 |
| minor | 如果没有预发布号,则直接升级一位中号,大号不动,小号置为0如果有预发布号:如果小号为0, 则不升级中号,将预发布号去掉如果小号不为0, 同理没有预发布号 |
| patch | 如果没有语法不好:直接升级小号,去掉预发布号如果有预发布号:去掉预发布号,其他不动 |
| premajor | 直接升级大号, 中号和小号置为0, 增加预发布号为0 |
| preminor | 直接升级中号, 下号置为0,增加预发布号为0 |
| prepatch | 直接升级小号,增加预发布号为0 |
| prerelease | 如果没有预发布号:增加小号,增加预发布号为0如果 有预发布号,则不升级预发布号 |
语义化版本
| Code status | Stage | Rule | Example version |
|---|---|---|---|
| First release | New product | Start with 1.0.0 | 1.0.0 |
| Backward compatible bug fixes | Patch release | Increment the third digit | 1.0.1 |
| Backward compatible new features | Minor release | Increment the middle digit and reset last digit to zero | 1.1.0 |
| Changes that break backward compatibility | Major release | Increment the first digit and reset middle and last digits to zero | 2.0.0 |