如何用浏览器读取本地文件(兼容IE8),new bing能帮我吗?

2023年3月28日

浏览器读写文件?

有一份老旧而精巧的代码(2006或更早),带js的html,可以只用浏览器来处理一些二进制存档数据。

文件的读写怎么办?通过变动的方法来完成。

利用十六进制编辑软件如WinHEX,直接复制十六进制数值为字符串,贴到一个TextArea以输入;

同样处理过的数据也是生成十六进制字符串,用WinHEX以ASCII Hex的格式粘贴到新文件中。

很巧妙,也有点繁琐。

FileReader:

最近找到了该程序的汉化版,也是好多年前的了,发现里面设计了直接用来加载文件的功能,用的vbs调用Msxml2.XMLHTTP对象来处理。

可是现在的浏览器基本不支持vbs了,就想改一下,用js来完成。

上网搜索了一堆,XMLHTTP/XMLHttpRequest的代码,有些需要服务器端支持,结果都不理想,或浏览器显示无法创建对象之类的。

刚好new bing的申请也通过了,一番对话式交流,新搜索引擎初试身手,效果不错,直接给出了示例代码。

只要是支持HTML5的现代浏览器,调用FileReader,那叫一个驾轻就熟!

依葫芦画瓢,花了一点功夫也就改造完成了。

这时又回想起一个问题,旧浏览器(IE10以下,原网银的最爱)怎么办。

如何兼容IE8?

有这个必要吗?

都3202年了,不支持HTML5、不支持ES6的浏览器就该回垃圾堆或封存至博物馆!

网银都终于要求兼容Edge啦!

但无聊也是无聊,找了台老电脑远程其桌面,继续随便搜搜“JS读取本地文本文件 IE8兼容”,结果是有一大堆,可大多都是标题党。

在有些参考资料中,提到使用“Microsoft.XMLDOM”对象,试了好久,更适用于文本数据;

FSO对象貌似也只能OpenTextFile或OpenAsTextStream。

以上方法,读取到的是文本数据,都少了很多非可打印/显示字符,当然不行。

还是要用ADODB.Stream,因为它有个方法Read(),可读取二进制数据流。

ADODB.Stream:

碰到两个问题:

  1. 浏览器无法创建对象。安全问题,容易给恶意程序随意读写客户的数据,一般不开放这个功能,改改注册表,强行开通吧。
  2. 读不到二进制数据。在IE8中调试程序,一到adodb.Read()后面,产生的东西却不是个object,typeof测试一下,unknown...

正想放弃adodb.stream,又搜到一些资料,既然.Read()不行,严肃地建议我用.ReadText()。

读取文本,用来处理二进制数据,这也行?

adodb.stream支持对字符集的转换处理,刚好有个神奇的字符集系列:

ISO-8859-1~15

ISO-8859-1(Latin1/Windows-1252),MySQL人士比较熟悉,软件默认的拉丁西欧字符集,它的特点在于对单字节完全编码,1Byte=8bit, 它把所有256个码位全部都排满了。

所以,可用它存储任意二进制数据而不会丢失。

至于编码解码的处理是另外一回事,后续折腾也是由此……

程序好像改造成功,一个数据也没少,不管是否为可打印/显示字符,或者对拉丁来说全是合法字符!

然~~而,读取的数据好像有几个地方有差异!不多、但是不同!

换成变体标准ISO-8859-15差异少了许多,但还是有差异。

十万个为什么?

差异原因

为什么网上的示例代码对图像、声音文件进行复制都不出错,我加载数据到程序中就有差异?

继续追踪调试,找到了端倪,有几个特定的数据,读取出来就变了。

比如84就固定转化为1E80AC……

只是文件复制的话,持续沿用ISO-8859 Latin字符集,同一个管道,怎么In/Out、Read/Write,数据都不会变。

但是一旦用js将数据读取为数值,在转化为16进制字符串时,问题出现了。

因JavaScript引擎内部,所有字符都用 Unicode 表示。而Latin1字符集中的某些符号,在Unicode中是多字节编码。

ISO-8859-15中,这样的字符比较少而已,当然,所处码位也不同。

比如拉丁字符中用1字节0x80表示了“”,而在Unicode中编码是0x20AC;而“”则0x84变成了0x201E,等等……

刚好对上!

原二进制数据就这样被转换了,编码冲突,怎么还原?

再问new bing,多次给出的代码也存在这个问题,继续追问Unicode的编码问题,认错态度非常好,但是没有解决方案。

那只能这样了:

手工转换

懒得写代码,new bing也不理我。

刚好又搜索到一位国外友人的代码,问题解决,但是TA用的是437字符集,直接把256个字符的编码做了个对照查询表,转换函数非常之长,我也不想改用437了。

我直接输出了ISO-8859-15字符集所有00~FF用js转换为数值的结果,和真实二进制数据相比,也就存在8处不同的Unicode字符嘛,处理过程中查询修正一下就行了。

搞定!

还是要自己写……其实也不费力。

示例,读取并显示为HEX



16进制

后记

ISO-8859之外,其它字符集也一般可使用,只要找到冲突编码并转换处理即可;

js生成文件供浏览器下载,现代浏览器用blob加createObjectURL轻松搞定;

在分离FileReader一段代码至子函数时,对异步操作的处理还闹过小问题,Promise的逻辑还真是有些不适合本中老年;

IE8?不想玩了。

奇怪地是,再过了几天,问new bing本文类似的问题,它拒绝给出示例代码,说它不会,说它没有记忆,说IE8没法处理这个读取本地二进制文件的问题……

服务器托管,北京服务器托管,服务器租用 http://www.hhisp.net
机房租用,北京机房租用,IDC机房托管, http://www.e1idc.net

hackdl

咨询热线/微信 13051898268