fileReader.readAsBinaryString 上传文件

2023-12-01

尝试使用 fileReader.readAsBinaryString 通过 AJAX 将 PNG 文件上传到服务器,精简代码(fileObject 是包含我的文件信息的对象);

var fileReader = new FileReader();

fileReader.onload = function(e) {
    var xmlHttpRequest = new XMLHttpRequest();
    //Some AJAX-y stuff - callbacks, handlers etc.
    xmlHttpRequest.open("POST", '/pushfile', true);
    var dashes = '--';
    var boundary = 'aperturephotoupload';
    var crlf = "\r\n";

    //Post with the correct MIME type (If the OS can identify one)
    if ( fileObject.type == '' ){
        filetype = 'application/octet-stream';
    } else {
        filetype = fileObject.type;
    }

    //Build a HTTP request to post the file
    var data = dashes + boundary + crlf + "Content-Disposition: form-data;" + "name=\"file\";" + "filename=\"" + unescape(encodeURIComponent(fileObject.name)) + "\"" + crlf + "Content-Type: " + filetype + crlf + crlf + e.target.result + crlf + dashes + boundary + dashes;

    xmlHttpRequest.setRequestHeader("Content-Type", "multipart/form-data;boundary=" + boundary);

    //Send the binary data
    xmlHttpRequest.send(data);
}

fileReader.readAsBinaryString(fileObject);

在上传之前检查文件的前几行(使用 VI)给我

enter image description here

上传后显示相同的文件

enter image description here

所以它看起来像是某个地方的格式/编码问题,我尝试在原始二进制数据上使用简单的 UTF8 编码函数

    function utf8encode(string) {
        string = string.replace(/\r\n/g,"\n");
        var utftext = "";

        for (var n = 0; n < string.length; n++) {

            var c = string.charCodeAt(n);

            if (c < 128) {
                utftext += String.fromCharCode(c);
            }
            else if((c > 127) && (c < 2048)) {
                utftext += String.fromCharCode((c >> 6) | 192);
                utftext += String.fromCharCode((c & 63) | 128);
            }
            else {
                utftext += String.fromCharCode((c >> 12) | 224);
                utftext += String.fromCharCode(((c >> 6) & 63) | 128);
                utftext += String.fromCharCode((c & 63) | 128);
            }

        }

        return utftext;
    )

然后在原来的代码中

//Build a HTTP request to post the file
var data = dashes + boundary + crlf + "Content-Disposition: form-data;" + "name=\"file\";" + "filename=\"" + unescape(encodeURIComponent(file.file.name)) + "\"" + crlf + "Content-Type: " + filetype + crlf + crlf + utf8encode(e.target.result) + crlf + dashes + boundary + dashes;

这给了我的输出

enter image description here

仍然不是原始文件=(

如何对文件进行编码/加载/处理以避免编码问题,以便 HTTP 请求中收到的文件与上传之前的文件相同。

其他一些可能有用的信息,如果我使用 fileObject.getAsBinary() 来获取二进制数据而不是使用 fileReader.readAsBinaryString() ,它可以正常工作。但 getAsBinary 仅适用于 Firefox。我已经在 Mac 上的 Firefox 和 Chrome 中对此进行了测试,得到了相同的结果。后端上传正在由NGINX 上传模块,再次在 Mac 上运行。服务器和客户端在同一台机器上。我尝试上传的任何文件都会发生同样的事情,我只是选择 PNG,因为它是最明显的例子。


(以下是迟到但完整的答案)

FileReader 方法支持


FileReader.readAsBinaryString() is 已弃用。不要使用它!它不再在W3C 文件 API 工作草案:

void abort();
void readAsArrayBuffer(Blob blob);
void readAsText(Blob blob, optional DOMString encoding);
void readAsDataURL(Blob blob);

注意:请注意File是一种扩展Blob结构。

Mozilla 仍然实现readAsBinaryString()并在中描述它MDN FileApi 文档:

void abort();
void readAsArrayBuffer(in Blob blob); Requires Gecko 7.0
void readAsBinaryString(in Blob blob);
void readAsDataURL(in Blob file);
void readAsText(in Blob blob, [optional] in DOMString encoding);

背后的原因readAsBinaryString()我认为弃用如下:JavaScript 字符串的标准是DOMString它只接受 UTF-8 字符,而不接受随机二进制数据。因此,不要使用 readAsBinaryString(),这根本不安全且不符合 ECMAScript。

我们知道JavaScript 字符串不应该存储二进制数据但 Mozilla 在某种程度上可以。我认为这很危险。Blob and typed arrays (ArrayBuffer以及尚未实施但不必要的StringView)的发明目的只有一个:允许使用纯二进制数据,不受 UTF-8 字符串限制。

XMLHttpRequest上传支持


XMLHttpRequest.send()有以下调用选项:

void send();
void send(ArrayBuffer data);
void send(Blob data);
void send(Document data);
void send(DOMString? data);
void send(FormData data);

XMLHttpRequest.sendAsBinary()有以下调用选项:

void sendAsBinary(   in DOMString body );

sendAsBinary() 不是标准,Chrome 可能不支持。

解决方案


所以你有几个选择:

  1. send() the FileReader.result of FileReader.readAsArrayBuffer ( fileObject )。操作起来比较复杂(你必须为它创建一个单独的 send() ),但它是推荐方法.
  2. send() the FileReader.result of FileReader.readAsDataURL( fileObject )。它会产生无用的开销和压缩延迟,需要在服务器端执行解压缩步骤,但很容易在 Javascript 中作为字符串进行操作。
  3. 不符合标准且sendAsBinary() the FileReader.result of FileReader.readAsBinaryString( fileObject )

MDN指出:

发送二进制内容(如文件上传)的最佳方法是使用 ArrayBuffers 或 Blob 与 send() 方法结合使用。然而, 如果要发送可字符串化的原始数据,请使用 sendAsBinary() 方法,或 StringView(非本机)类型数组超类。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

fileReader.readAsBinaryString 上传文件 的相关文章

随机推荐

  • 如何将命名向量作为行添加到数据框中,并根据列名称顺序重新排序?

    如何将命名向量添加到数据框中 并根据数据框的列名称重新排序向量的组件 我需要一次一行构建一个数据框 通过某种处理获得命名向量 它提供要插入的行的值 问题是命名向量的分量与数据框列的顺序不同 这使得rbind产生错误的结果 这是非常简化的示例
  • 如何在Windows服务器上安装Apple Push证书

    我需要安装从 Apple 开发门户下载的证书 以便在 Windows 服务器上测试推送通知 我在网上搜索了一个解决方案 但每个人对此都有不同的看法 有人有关于如何执行此操作的分步指南吗 我也一直在研究这个课题 以下链接可能对您有用 http
  • Laravel 4,在 JavaScript 中传递变量到路由

    How Can I pass the variable stock id return from Ajax response to the route to generate the url to edit a stock ajax url
  • 检测手机休眠时的手势[关闭]

    Closed 这个问题需要多问focused 目前不接受答案 我正在开发一个 SOS Android 应用程序 如果手机处于睡眠 待机模式 我想检测手势 例如屏幕上的几次触摸 并开始发送帮助请求 例如发送短信 我怎样才能检测到这个手势 有人
  • 使用 Cypress 登录 WordPress,无需使用 UI

    In the 有关登录的 Cypress 文档他们指出不应使用 UI 设置状态 但看起来 WordPress 的 API 中没有提供登录功能 由于黑客攻击是大多数 WordPress 站点上的一个问题 所以我不想添加它 如何使用 Cypre
  • 如何在 django 通道上使用令牌身份验证对 Websocket 进行身份验证?

    我们想为我们的 websocket 使用 django channels 但我们也需要进行身份验证 我们有一个与 django rest framework 一起运行的 Rest api 我们使用令牌来验证用户身份 但 django cha
  • NSXMLParser 因 & 符号而阻塞

    我正在使用 NSXMLParser 解析一些 HTML 只要遇到 符号 它就会遇到解析器错误 我可以在解析它之前过滤掉 符号 但我宁愿解析那里的所有内容 它给我错误 68 NSXMLParserNAMERequiredError 名称是必需
  • 在一行与 1 和 0 矩阵之间进行异或的更快方法?

    我有一行数据 比如说A 0 1 1 1 0 0 矩阵 B 包含许多行 对于一个虚拟的例子 我们假设它只是B 1 1 1 0 1 0 1 0 0 1 0 1 我想找到 A 和 B 的行不同的列数 并使用该差异向量来查找 B 的哪一行与 A 最
  • 使用字符串创建 Red 语言的单词和路径

    我有字符串在namelist 对应于应用程序中的变量和字段名称 该函数应该从名称列表中读取字符串 添加 f 以获取 field names 然后将变量值放入相应的字段中 我尝试了以下代码 没有给出任何错误 但也不起作用 namelist v
  • Rstudio不会编织

    Rstudio 不会编织 我已经在课程中使用它几个星期了 当我尝试编织时 它会执行直到遇到一些代码并停止 代码是 ggplot 数据 gss aes x 年 填充 度 几何酒吧 消息是 找不到函数 ggplot 其他函数也会发生这种情况 注
  • C#8 接口及其中定义的属性/方法 - 显然不起作用

    这是我使用的界面 public interface IPresentism public abstract bool isPresent get public virtual bool isAbsent gt isPresent isPre
  • Oracle 中的 OVER 子句

    Oracle中的OVER子句是什么意思 The OVER子句指定分析函数运行的 分区 排序和窗口 示例 1 计算移动平均线 AVG amt OVER ORDER BY date ROWS BETWEEN 1 PRECEDING AND 1
  • 如何通过解析 TTF 字体文件获取字形宽度?

    用于捕获 a 的字形宽度TrueType字体 我转换对应的TTF归档依据fontforge into AFM 它是文本格式 不是二进制 然后 解析文本文件以捕获字形宽度 应该有更简单的方法来直接解析二进制文件TTF文件来捕获字形宽度 我很欣
  • C# 索引属性?

    我使用 Visual Basic 已经有一段时间了 最 近决定开始学习 C 作为学习更复杂语言的一个步骤 作为这次跳跃的一部分 我决定将一些旧的 VB 项目手动转换为 C 我遇到的问题是转换一个具有使用带有参数 索引的属性的类的库 在 VB
  • 如何调试IE11 APPCACHE

    我有一个适用于 CHROME 和 SAFARI 的 HTML5 页面 但使用 Internet Explorer 11 不起作用 我的缓存清单根据http manifest validator com 我很沮丧 这是 AppCache 清单
  • 将 XHTML 转换为 Word ML

    将 Word HTML 转换为 Word XML 的最佳方法是什么 我无法购买工具 因此需要最好是 XSLT 它是免费的 并且适用于段落 列表 粗体和斜体等基本格式 斯蒂芬 布永写了一篇blog关于这一点 请参阅 MSDN 她提供了一个非常
  • Firebase Cloud 代码(后端逻辑)

    我正在考虑使用 Firebase 而不是 Parse 因为它即将关闭 来满足我未来的移动后端需求 我真的很喜欢它的实时数据库方面 但它没有像 Parse 与 Cloud Code 那样轻松集成后端逻辑 有没有简单的方法可以实现此功能 或者很
  • 无效的正则表达式错误

    我正在尝试检索该字符串的类别部分 property id 516 category featured properties 所以结果应该是 featured properties 我想出了一个正则表达式并在这个网站上进行了测试http gs
  • 将 Ado.net DataReader 转换为 IDataRecord 给出奇怪的结果

    我有一个针对数据库运行的查询 我可以看到有一条 2013 年 5 月 31 日的记录 当我使用 ADO NET 从 C 运行此查询 然后使用以下代码时 我丢失了 2013 年 5 月 31 日的记录 var timeSeriesList n
  • fileReader.readAsBinaryString 上传文件

    尝试使用 fileReader readAsBinaryString 通过 AJAX 将 PNG 文件上传到服务器 精简代码 fileObject 是包含我的文件信息的对象 var fileReader new FileReader fil