随手记第三弹 - 基于 File 对象生成 MD5
引言
当谈到前端开发时, 无论是初学者还是经验丰富的开发者, 都能够感受到这个领域的迅速发展和变化。前端技术不断演进, 新的框架和工具层出不穷, 这使得我们需要不断学习和掌握新的知识点。然而, 有时候我们会遇到一些零散的小知识点, 它们虽然看似微小, 但却能为我们的工作和学习带来巨大的帮助。
在本专栏中, 我将总结一些我平时 随手
记录小知识点。这些小的知识点有的是平常项目中遇到的, 有的则是看了一些大佬们分享的博客后摘抄、总结的; 尽管它们可能篇幅较小, 但它们的实际应用价值却是不可忽视的。我会选择一些具有代表性的知识点, 并提供简洁明了的解释和示例, 以便大家能够轻松理解和应用。
最后如果, 如果你对本专栏的知识感兴趣, 欢迎👏🏻👏🏻 点击订阅!!! 无论你是新手还是有经验的开发者, 都希望这些小知识点能够对你有所启发和帮助!!!
一、Fetch 文件上传(请不要设置「Content-Type」)
一个简单
DEMO
简单做个记录, 方便后面可以直接CV
使用
const formdata = new FormData();
formdata.append("avatar", fileInput.files[0]);
const requestOptions = {
method: "POST",
body: formdata,
};
fetch("http://localhost:8001/api/oss/getImageDetectionAndCelebrity", requestOptions)
.then((response) => response.text())
.then((result) => console.log(result))
.catch((error) => console.error(error));
注意点:
- 文件上传需要
POST
请求, 并且body
必须是FormData
格式- 在请求头中不要设置
Content-Type
为multipart/form-data
, 否则可能就会报Error: Multipart: Boundary not found
错误, 我这次其实就是设置了该请求头, 导致接口报错, 去掉就好了, 上传文件在没有设置Content-Type
下Fetch
会自动为我们添加该请求头并且会添加一个boundary
用来分割消息主体中的每个字段, 如果这个时候我们自己设置了Content-Type
服务器就不知道怎么分割各个字段, 因此就会报错
参考内容:
二、Sudo 命令自动填充密码
sudo
是 Linux
和类 Unix
操作系统中的命令, 用于以超级用户或其他用户的身份执行命令。sudo
是 superuser do
的缩写, 它允许普通用户在需要时以特权身份执行命令, 前提是他们被授权执行这些命令。通常情况下, 需要输入密码来确认身份验证, 以确保安全性。
但是对于喜欢偷懒的我来说, 每次重新链接终端, 执行 sudo
都需要 先回车
再 输入密码
再 回车
, 这一套下来时间久了就让人生厌。
echo "密码" | sudo -S 要执行的命令
大概效果如下(执行完要等一会噢):
参考: shell指令自带sudo密码
三、shell 脚本中大小写转换
这里是在构建 Docker
镜像时, 想要根据环境变量来设置不同的镜像名称, 但是因为环境变量对应的值是大写的, 但巧的是 Docker
镜像名只能是小写
所以这里就需要在 Shell
脚本中将对应的环境变量值, 转为小写
这里使用到的是 tr
命名, 类似脚本内容如下:
TAG=zh_CN
dockerName=$(echo "${TAG}" | tr '[:upper:]' '[:lower:]')
你也可以在终端测试其效果, 执行 echo "m_AX_Sd" | tr '[:upper:]' '[:lower:]'
效果如下:
四、一个 WebGL 报错
项目中使用了 spline 发现有的用户在 chrome
下无法正常展示(展示空白)
spline 调用代码如下:
<Spline
className={clsx('absolute inset-y-0 right-0 flex !h-auto !w-2/3 justify-end')}
scene="https://prod.spline.design/AZIERplA/scene.splinecode"
/>
查看控制台看到如下错误:
经排查发现是用户将「硬件加速」功能给关闭了, 关闭 chrome
的 硬件加速
步骤如下:
那么, 最后解决方案就是:
- 让用户开启
硬件加速
- 做个兜底的方案, 在加载错误情况下, 会默认展示一个封面图, 相关代码如下:
// 这里只是大致代码, 样式什么的还得自己补充
const CustomSpline = (props) => {
const { scene, className, poster, classNames } = props;
const [isLoad, setIsLoad] = useState(false);
return (
<div>
{poster && !isLoad ? (
<img
alt="Spline"
src={poster}
/>
) : null}
<Spline
scene={scene}
onLoad={() => setIsLoad(true)}
/>
</div>
);
};
五、客户端基于文件流生成 MD5
在实际项目中, 上传文件采用 前端直传
的方式进行, 前端先向后端获取临时 Token
, 前端获取到 Token
后直接上传到对应存储
在这种情况下, 为了避免用户多次上传同一文件, 则需要对上传的文件生成一个 MD5
并将相关数据保存到数据库, 每次获取获取临时 Token
时需要将 MD5
提供给后端, 如果当前文件已上传则不进行任何操作
那么问题就来了, 我们要如果在前端生成 MD5
呢?
下面直接看代码:
- 使用
FileReader.readAsText
将文件流转为文本 - 拿到文本了, 剩下就是
MD5
的生成了, 这里我使用的是crypto-es
import Crypto from 'crypto-es';
<input
type="file"
onChange={(event) => {
// 利用 FileReader, 读取文件并转换为 ArrayBuffer
const fileReader = new FileReader();
fileReader.readAsText(event.target.files[0]);
fileReader.onloadend = () => {
const md5 = Crypto.MD5(fileReader.result as string);
console.log('md5:', md5.toString());
};
fileReader.onerror = (error) => {
console.log('error:', error);
};
}}
/>
简单封装:
import Crypto from 'crypto-es';
/** 获取文件 MD5 */
const getMd5WithFiles = (file) => new Promise(async (resolve, reject) => {
const fileReader = new FileReader();
fileReader.readAsText(file);
fileReader.onloadend = () => {
// 获取 MD5 值
const md5 = Crypto.MD5(fileReader.result as string);
resolve({ file, md5: md5.toString() });
};
fileReader.onerror = (error) => reject(error);
});
六、Node 读取 docx 内的文本内容
该问题是群里小伙伴提出的一个问题,「Node
中如何获取到 docx
内的文本部分?」 该小伙伴直接使用 fs.readFileSync
读取到的内容是一对乱码, 所有很多人都猜测是编码问题, 固执的我则认为并不是这个原因?
个人认为, 这不太可能是编码的问题, 原因是 docx
并不是常规的文本文件, 他包含很多文本布局、样式、图片、表格等等....所以就算拿到的不是乱码, 内容肯定也是不对的, 也是需要进行各种解析的?
当时刚好有空就试了下, 最后找到一个可以使用的工具包 textract, 演示代码如下:
import fs from 'fs';
import textract from 'textract';
const res = fs.readFileSync('demo.docx', 'utf8');
console.log('直接读取:', res);
console.log('\n\n\n\n');
textract.fromFileWithPath('./demo.docx', {
preserveLineBreaks: true,
preserveOnlyMultipleLineBreaks: true,
includeAltText: true
},function( error, text ) {
console.log('使用 textract:\n\n\n', text);
})
七、File 图片文件预览
两个
File
图片文件转成可被img
src
识别内容的方法
- 方法一
// 处理 src 使得支持 file 类型
const handledSrc = useMemo(() => {
if (src instanceof File) {
return URL.createObjectURL(src);
}
return src;
}, [src]);
- 方法二
const reader = new FileReader();
reader.readAsDataURL(realValue);
reader.onloadend = () => setImageData(reader.result as string);
八、Pode Pdf 合并小方法
来自对象的一个需求: 就是需要将指定的一批 Pdf
文件, 将它们合并到一个文件内
故找了一个工具包 pdf-lib, 用 Node
简单写了个小脚本
脚本内容如下:
/**
* 合并多个 PDF 为一个 PDF 文件
* 这个是使用的 pdf-lib 对 PDF 进行合并
*/
const { PDFDocument } = require('pdf-lib');
const fs = require('fs');
const mergePDF = async ({ sourceFiles, outputFile }) => {
const pdfDoc = await PDFDocument.create();
for (let i = 0; i < sourceFiles.length; i += 1) {
const localPath = sourceFiles[i];
const PDFItem = await PDFDocument.load(fs.readFileSync(localPath));
for (let j = 0;j < PDFItem.getPageCount(); j += 1) {
const [PDFPageItem] = await pdfDoc.copyPages(PDFItem, [j]);
pdfDoc.addPage(PDFPageItem);
}
}
const pdfBytes = await pdfDoc.save();
fs.writeFileSync(outputFile || 'merge.pdf', pdfBytes);
};
const sourceFiles = ['./1.pdf', './2.pdf'];
mergePDF({ sourceFiles });
九、Nextjs 遇到如下
在定义 typescript
时, 定义函数时, 参数提示未定义
解决办法: 修改 .eslintrc.js
配置, 换个 parser
module.exports = {
+ parser: '@typescript-eslint/parser',
}
十、Vscode TailwindCSS 插件在 React 中不生效
在 Vscode
安装完 TailwindCSS
后记得配置下针对哪些属性启动该插件
{
"tailwindCSS.classAttributes": [
"class",
"className",
"ngClass",
"enter",
"enterFrom",
"enterTo",
"leave",
"leaveFrom",
"leaveTo",
]
}
....
转载自:https://juejin.cn/post/7366948087129325604