Rust 赋能前端 -- 写一个 File 转 Img 的功能

server/2024/9/25 5:32:02/

所有耀眼的成绩,都需要苦熬,熬得过,出众;熬不过,出局

大家好,我是柒八九。一个专注于前端开发技术/RustAI应用知识分享Coder

此篇文章所涉及到的技术有

  1. Rust
  2. wasm-bindgen/js-sys/web-sys
  3. Web Worker
  4. WebAssembly
  5. Webpack/Vite配置WebAssembly
  6. OffscreenCanvas
  7. 脚手架生成项目(npx f_cli_f create xxx
  8. tailwindcss
  9. MuPDF.js/mammoth.js

因为,行文字数所限,有些概念可能会一带而过亦或者提供对应的学习资料。请大家酌情观看。


前言

在前一篇文章写一个类ChatGPT应用,前后端数据交互有哪几种我们介绍了,如果要进行一个类ChatGPT应用的开发,可能会用到的前后端数据交互的方式。同时呢,我们也介绍了最近公司所做的项目,做一款基于文档类问答的AI功能。

而谈到文档相关的应用,从操作文档角度来看,无非就是文件上传文件解析文件展示。而我们之前在文件上传 = 拖拽 + 多文件 + 文件夹介绍过更优雅的上传方式。而文件展示如果大家想了解的话,我们可以单独写一篇文章。

而我们今天来聊聊关于文件解析的相关操作。

业务背景

大家肯定用过很多云盘类的应用。在我们对本地文件进行上传后,在展示的时候一般分为两种模式

  1. 列表模式
    列表模式
  2. 大图模式
    大图模式

如果大家观察过云盘针对大图模式的文件资源的展示,就会发现每个文件的头图都是用一个<img/>接收了一个从后端返回的固定图片资源。

而现在,我们针对大图模式有几点改进

  1. 要求该图片能显示文件资料的概要内容(这块可以借助AI对文本进行Summary处理,这个我们后面会单独写一篇文章),而不是单单的把文件的首页信息(pdf/word/pptx)转换成图片(像阿里云盘一样)
  2. 要求前端在上传过程中,就需要显示文件的概要信息,而不是走接口从服务器获取,也就是这是一个纯前端的事情
  3. 还需要在图片的标识文件的类型,例如展示pdf/word/ppt等的图标

为什么做呢,有没有发现我们通过上述的改造和处理,我们直接在大图模式下,通过文件头图信息就能大致知晓文件的内容(概要信息),其次如果展示的资源信息过多,每次从后端获取对应的图片资源也是一件极其耗费带宽的事情。

前端糅合其他语言

讲到这里,大家可能会疑惑,你上面说了那么多,那么这和Rust有啥关系?

关系大着呢,从上面的需求点出发,我们可以看出,其实针对文档解析的处理,都是在前端环境中操作的。同时,针对大体积的文件资源,对其解析处理是一件极其耗时的事情。有时针对特殊文件,可能前端还暂时无法处理。

既然,我们想要在前端执行这些耗时且不易处理的任务,我们就需要请帮手,而在其他语言中有成熟的方案来处理我们遇到的这些问题。(由于种种原因,其他端的小伙伴无瑕处理这种情况)

那么,我们就可以选择一种方式,在前端环境中通过某种方式来糅合其他语言的操作来执行对应的任务。那思来想去,WebAssembly是再合适不过的方式了。如果不了解它,可以看我们之前的文章 - 浏览器第四种语言-WebAssembly。

当然,其他语言(C/TypeScript)都可以通过编译工具转化成WebAssembly,此片文章中也会涉及,只不过我们是直接使用别人构建好的WebAssembly,而现行阶段,Rust是对WebAssembly最友好的语言。并且,我们也会用Rust手搓一个WebAssembly。这也是为什么这篇文章的主标题叫Rust赋能前端而不是WebAssembly赋能前端(我们在本文的第三部分,Word 解析中详细介绍了用RustWebAssembly,如果不想看mupdf的可以直接跳到第三节)

好了,天不早了,干点正事哇。

我们能所学到的知识点

  1. 服务配置&项目配置
  2. PDF 解析
  3. Word 解析

1. 服务配置&项目配置

由于,WebAssembly是一个新兴技术,在一些常规的打包工具(vite/webpack)中使用,我们需要额外处理。

使用WebAssembly从来源大致可以两类

  1. npm包/公司私包(针对如何发私包可以参考之前的如何在gitlab上发布npm包)
  2. 直接在项目目录中使用已经构建好的wasm

这两种情况我们接下来都会涉及。其实他们的处理方式都是一样的。下面我们就来讲讲Webpack/Vite是如何配置它们的。

Webpack

针对Webpack中使用WebAssembly,我们之前在Rust 编译为 WebAssembly 在前端项目中使用就介绍过。

其实,最关键的点就是需要wasm-pack-plugin

其次,我们还想让WebAssembly模块能够和其他ESM一样,通过import进行方法的导入处理,针对Webapck5我们还可以通过配置experiments的asyncWebAssembly为true来启动该项功能。

最后,为了兼容性,我们处理TextEncoder/TextDecoder

const path = require('path');
const HtmlWebpackPlugin = require('html-webpack-plugin');
const webpack = require('webpack');
const WasmPackPlugin = require("@wasm-tool/wasm-pack-plugin");module.exports = {entry: './index.js',output: {path: path.resolve(__dirname, 'dist'),filename: 'index.js',},plugins: [new HtmlWebpackPlugin({template: 'index.html'}),new WasmPackPlugin({crateDirectory: path.resolve(__dirname, ".")}),// 让这个示例在不包含`TextEncoder`或`TextDecoder`的Edge浏览器中正常工作。new webpack.ProvidePlugin({TextDecoder: ['text-encoding', 'TextDecoder'],TextEncoder: ['text-encoding', 'TextEncoder']})],mode: 'development',experiments: {asyncWebAssembly: true}
};

Vite

Vite官网看,它只兼容了引入预编译的.wasm,但是对 WebAssemblyES 模块集成提案 尚未支持。而恰巧,我们今天所涉及到的.wasm都是ESM格式的。

按照官网的提示,我们可以借助vite-plugin-wasm的帮助。

配置也很简单,按照下面的处理即可。

import wasm from "vite-plugin-wasm";
import topLevelAwait from "vite-plugin-top-level-await";export default defineConfig({plugins: [wasm(),topLevelAwait()],worker: {plugins: [wasm(),topLevelAwait()]}
});

项目配置

由于,我们公司的打包工具是Vite,还记得我们之前介绍过的脚手架工具吗。

大家可以在自己电脑中执行,npx f_cli_f create file_to_img来构建一个以Vite为打包工具的前端项目。

然后,我们就可以将上面逻辑写到对应的文件中。

执行到这里,我们的前期的配置工作就算完成了。

如果使用过我们的f_cli_f的人,会知道。我们在项目中内置了很多东西,可以算是开箱即用。

所以,我们保留之前的结构的基础上,在pages中新建一个FileToImg的目录结构,并且将其放置于main路由下。

最后的页面结构如下

  • 左侧的待处理文件类型我们提供了针对pdf/word/text的常规文件的解析
  • 附件上传就是使用最原始的<input type="file"/>
  • 搜索区块的话,是针对PDF的内容检索
  • 右侧的格式输出,可以切换文件的输

http://www.ppmy.cn/server/42859.html

相关文章

PHP质量工具系列之php_CodeSniffer

PHP_CodeSniffer 是一组两个 PHP 脚本&#xff1a;主脚本 phpcs 对 PHP、JavaScript 和 CSS 文件进行标记&#xff0c;以检测是否违反定义的编码标准&#xff1b;第二个脚本 phpcbf 自动纠正违反编码标准的行为。PHP_CodeSniffer 是一个重要的开发工具&#xff0c;可以确保你的…

【Linux】LAMP集群分布式安全方案

LAMP集群分布式安全方案主要涉及确保Linux、Apache、MySQL和PHP&#xff08;LAMP&#xff09;组合构成的集群环境的安全性和稳定性。 本次实验通过网络层安全对防火墙配置&#xff1a;使用防火墙&#xff08;如iptables或firewalld&#xff09;来限制对集群的访问&#xff0c;只…

Unity vscode在mac上的编译环境设置

在settings.json文件中配置以下信息。 settings.json路径一般在/Users/xxx/Library/Application Support/Code/User/settings.json {"omnisharp.useGlobalMono": "always","editor.fontLigatures": false,"omnisharp.useModernNet": …

算法打卡 Day9(字符串KMP 算法)-实现 strStr+ 重复的子字符串

KMP 算法 KMP 算法解决的是字符串匹配的问题&#xff0c;其经典思想是&#xff1a;当出现的字符串不匹配时&#xff0c;可以记录一部分之前已经匹配的文本内容&#xff0c;利用这些信息避免从头再去做匹配。 前缀表 next 数组就是一个前缀表。前缀表是用来回退的&#xff0c…

自然资源-中华人民共和国土地管理法实施条例(2021年修订)

中华人民共和国土地管理法实施条例&#xff08;2021年修订&#xff09; 中华人民共和国土地管理法实施条例 &#xff08;1998年12月27日中华人民共和国国务院令第256号发布 根据2011年1月8日《国务院关于废止和修改部分行政法规的决定》第一次修订 根据2014年7月29日《国务院…

c++11 标准模板(STL)本地化库 - 平面类别(std::numpunct_byname) 表示系统提供的具名本地环境的 std::numpunct

本地化库 本地环境设施包含字符分类和字符串校对、数值、货币及日期/时间格式化和分析&#xff0c;以及消息取得的国际化支持。本地环境设置控制流 I/O 、正则表达式库和 C 标准库的其他组件的行为。 平面类别 表示系统提供的具名本地环境的 std::numpunct std::numpunct_byn…

逻辑回归模型的背景与应用

1.1逻辑回归模型的背景与应用 逻辑回归模型&#xff0c;作为一种经典的机器学习方法&#xff0c;起源于统计学领域。在众多实际应用场景中&#xff0c;逻辑回归模型都发挥着重要作用&#xff0c;尤其在分类问题中。当我们需要对具有离散特征的数据进行建模和预测时&#xff0c…

Spring (17)Spring Boot和Spring MVC区别

Spring MVC 和 Spring Boot 都是 Spring 框架的一部分&#xff0c;但他们解决的问题和使用的方式有显著的不同。以下是两者的详细对比&#xff1a; Spring MVC&#xff08;Spring Web MVC Framework&#xff09; Spring MVC 是建立在 Spring Framework 上的原始 Web 框架。它…