正则表达式匹配慢

regex match slow

我尝试让 ajax 使用 nodejs 应用程序上传超过 2mb 的文件,
客户端我使用 FileReader api 保存 base64 然后通过 FormData

我的问题是像下面这样的服务器端代码太慢了,我把 console.log 试着找出哪一部分,当上传更大的文件时,似乎卡在了正则表达式 match..
任何建议如何改进这个?

https://regex101.com/r/qS2lB2/1

...
console.log(image.data_base64);  
// 'data:image/jpeg;base64,/9j/4AAQSkZJRgABAgEASABIAAD/7QAsUGhvd ...
var matches = image.data_base64.match(/^data:.+\/(.+);base64,(.*)$/);
console.log('done');  // slow

var fileExtension = matches[1];
var base64 = matches[2];
var buffer = new Buffer(base64, 'base64');

...
yield Promise.resolve( filesystem().writeFile(temporaryFilePath, buffer) );

无需在 multipart/form-data 请求中发送 base64 编码的文件。 FileReader 有一个 .readAsArrayBuffer() 方法,可以为您提供可以直接传递给 formData.append().

的原始数据(作为 ArrayBuffer)

以防万一您出于某种原因仍想使用正则表达式,可以通过将非尾随 .+ 子模式替换为涉及更少回溯的适当否定字符 类 来提高性能。

使用

/^data:[^\/]+\/([^;]+);base64,(.*)$/

参见 regex demo

解释:

  • ^ - 字符串开头
  • data: - 文字字符序列 data:
  • [^\/]+ - /
  • 以外的 1+ 个字符
  • \/ - 斜杠
  • ([^;]+) - 第 1 组:;
  • 以外的 1+ 个字符
  • ;base64, - 文字字符序列 ;base,
  • (.*) - 第 2 组:0+ 除换行符外的任何字符
  • $ - 字符串结尾。

额外的长度意味着正则表达式必须经过的字符串更多。

在以 data:image/jpeg;base64,/9:

开头的字符串上测试您的正则表达式(使用 regex101.com、PHP 模式)

已添加字符 |步骤

0   | 63
1   | 68
2   | 73
10  | 113
100 | 563

每增加一个字符为 5 个步骤。

如何修复正则表达式

(基于 characters added=100 走 563 步)

  • 你最大的问题是.+s

    • 用 .+ 替换第一个?减少到 248 步
    • 将第二个替换为 .+? 将其从 248 步变为 34 步

性能问题的原因

灾难性的回溯。 .+ 会吃掉整个字符串,如果还需要找更多的字符,就得返回,一个一个释放字符。 .+? 是惰性的,这意味着它将尝试尽快在正则表达式中继续前进,消耗尽可能少的字符。