likes
comments
collection
share

随手记第三弹 - 基于 File 对象生成 MD5

作者站长头像
站长
· 阅读数 26

引言

当谈到前端开发时, 无论是初学者还是经验丰富的开发者, 都能够感受到这个领域的迅速发展和变化。前端技术不断演进, 新的框架和工具层出不穷, 这使得我们需要不断学习和掌握新的知识点。然而, 有时候我们会遇到一些零散的小知识点, 它们虽然看似微小, 但却能为我们的工作和学习带来巨大的帮助。

在本专栏中, 我将总结一些我平时 随手 记录小知识点。这些小的知识点有的是平常项目中遇到的, 有的则是看了一些大佬们分享的博客后摘抄、总结的; 尽管它们可能篇幅较小, 但它们的实际应用价值却是不可忽视的。我会选择一些具有代表性的知识点, 并提供简洁明了的解释和示例, 以便大家能够轻松理解和应用。

最后如果, 如果你对本专栏的知识感兴趣, 欢迎👏🏻👏🏻 点击订阅!!! 无论你是新手还是有经验的开发者, 都希望这些小知识点能够对你有所启发和帮助!!!

一、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));

注意点:

  1. 文件上传需要 POST 请求, 并且 body 必须是 FormData 格式
  2. 在请求头中不要设置 Content-Typemultipart/form-data, 否则可能就会报 Error: Multipart: Boundary not found 错误, 我这次其实就是设置了该请求头, 导致接口报错, 去掉就好了, 上传文件在没有设置 Content-TypeFetch 会自动为我们添加该请求头并且会添加一个 boundary 用来分割消息主体中的每个字段, 如果这个时候我们自己设置了 Content-Type 服务器就不知道怎么分割各个字段, 因此就会报错

参考内容:

  1. multipart data POST using python requests: no multipart boundary was found
  2. 踩坑篇--使用 fetch 上传文件

二、Sudo 命令自动填充密码

sudoLinux 和类 Unix 操作系统中的命令, 用于以超级用户或其他用户的身份执行命令。sudosuperuser do 的缩写, 它允许普通用户在需要时以特权身份执行命令, 前提是他们被授权执行这些命令。通常情况下, 需要输入密码来确认身份验证, 以确保安全性。

但是对于喜欢偷懒的我来说, 每次重新链接终端, 执行 sudo 都需要 先回车输入密码回车, 这一套下来时间久了就让人生厌。

echo "密码" | sudo -S 要执行的命令

大概效果如下(执行完要等一会噢):

随手记第三弹 - 基于 File 对象生成 MD5

参考: shell指令自带sudo密码

三、shell 脚本中大小写转换

这里是在构建 Docker 镜像时, 想要根据环境变量来设置不同的镜像名称, 但是因为环境变量对应的值是大写的, 但巧的是 Docker 镜像名只能是小写

所以这里就需要在 Shell 脚本中将对应的环境变量值, 转为小写

这里使用到的是 tr 命名, 类似脚本内容如下:

TAG=zh_CN
dockerName=$(echo "${TAG}" | tr '[:upper:]' '[:lower:]')

你也可以在终端测试其效果, 执行 echo "m_AX_Sd" | tr '[:upper:]' '[:lower:]' 效果如下:

随手记第三弹 - 基于 File 对象生成 MD5

四、一个 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"
/>

查看控制台看到如下错误:

随手记第三弹 - 基于 File 对象生成 MD5

经排查发现是用户将「硬件加速」功能给关闭了, 关闭 chrome硬件加速 步骤如下:

随手记第三弹 - 基于 File 对象生成 MD5

那么, 最后解决方案就是:

  1. 让用户开启 硬件加速
  2. 做个兜底的方案, 在加载错误情况下, 会默认展示一个封面图, 相关代码如下:
// 这里只是大致代码, 样式什么的还得自己补充
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>
  );
};

参考: Error creating WebGL context. Three js chrome?

五、客户端基于文件流生成 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);
});

参考: How to calculate md5 hash of a file using javascript

六、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 识别内容的方法

  1. 方法一
// 处理 src 使得支持 file 类型
const handledSrc = useMemo(() => {
  if (src instanceof File) {
    return URL.createObjectURL(src);
  }

  return src;
}, [src]);
  1. 方法二
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 时, 定义函数时, 参数提示未定义

随手记第三弹 - 基于 File 对象生成 MD5

解决办法: 修改 .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",
  ]
}

参考: IntelliSense configuration

....

转载自:https://juejin.cn/post/7366948087129325604
评论
请登录