【问题标题】:Does FileReader.readAsBinaryString return binary or an ASCII-based character set?FileReader.readAsBinaryString 是否返回二进制或基于 ASCII 的字符集?
【发布时间】:2013-05-12 21:02:24
【问题描述】:

简而言之,我想将图像的二进制数据发送到我的处理程序,该处理程序将作为字节数组保存在数据库中。在我的 Javascript 中使用 readAsBinaryString(f) 读取文件输入的值,我将得到如下输出:

GIF89a,úæÿÿÿ2c½3fÌ Smaäµééúþc«T.[ÈéùAtεÚõ[ãX߯î*[µc³8Ûõüÿfj¥æ§ÈïÛå÷ËØñI}ÓQ×
*\»q£E}Ûÿå§ÓõþÿIÛv¤Þ´Åè«æ ³][us¬çAy×MÞ,a½«ÔóZÝL2äëùQ×(Eq<pË5V¨·ÏIÓ¨»åQßY¥3bØÈ
æ¬z³é<uÓ3£ÎñE¾á÷RÛR¢K­®ÎØØìÍAtÓÑÔØrÀ-hݪÑïôõüR|ÎäóÖUËåæçXÔw»^s®ëI}ÛQ}ÔEÛ·Îñ½Óêd»Ì
ÌëöåóôöÖàñE×Cr¿C¤3óúëLÍYÜ3fõûöÑðû Øûÿõw²ñ`ª»ßÀy|Á¿ÃIuÔM×ûñû{¹R4¼ìe¡äl«ç!ÿNETSCA
PE2.0!ÿXMP DataXMP<?xpacket begin="" id="W5M0MpCehiHzreSzNTczkc9d"?> <x:xmpm
eta xmlns:x="adobe:ns:meta/" x:xmptk="Adobe XMP Core 5.3-c011 66.145661, 2012/02
/06-14:56:27   // etc..  

该数据是通过 AJAX 发送的:

$.ajax({
    url: theUrl,
    type: 'POST',
    data: { Image: image } // image = data above
});

这是一个二进制字符串?当我将此字符串发送到我的处理程序 (IHttpHandler) 时,为了将其存储到字节数组中,如果我将编码设置为 ISO-8859-1,我可能只会获取字节。

public void ProcessRequest (HttpContext aContext) 
{ 
    // This works as long as requestValidationMode = "2.0" in web.config
    // Is there a way to bypass HttpRequestValidationException  just on 
    // THIS data?
    byte[] imageBytes = System.Text.Encoding.GetEncoding("ISO-8859-1").GetBytes(_Context.Request["Image"]);

    //...
}

这正常吗?这也会引发 HttpRequestValidationException(从...中检测到潜在危险的 Request.Form 值)。我宁愿不更改requestValidationMode,因为它对 XSS 开放,那么如何转义二进制字符串? Base64 编码是否涵盖了这一点,如果是,在处理程序中从 Base64 转换是否包含有关其数据类型的元数据?

【问题讨论】:

  • 感谢您的回复,斯图尔特。我的问题是我最初的“二进制字符串”没有表示为 1 和 0,就像 sn-p 上面的那个,这显然不是二进制的,我认为。为什么readAsBinaryString 将其返回为that?那是我不熟悉的另一种二进制形式吗?
  • 对我来说这看起来像Assembly。这本身就很奇怪。
  • 是的,该字符串是正常的...如果您将字符串传递给处理程序,则应将其编码为 base64 并在处理程序中将数据解码回来... 1 和 0 用于组装......传递这样的数据效率低下......
  • 很公平。如果我将它作为 base64 发送并解码,然后存储为字节数组,最终结果是否会包含数据类型?这样当我以后从DB中检索数据时,它就会知道是png,gif等?

标签: c# javascript asp.net


【解决方案1】:

看看你在代码中做了什么真的很有帮助,这就是我asked你展示它的原因。我您的代码如下所示:

var f = $("image").files[0];
var reader = new FileReader();
reader.readAsBinaryString(f);
var image = reader.result;

$.ajax({
    url: theUrl,
    type: 'POST',
    data: { Image: image }
});

现在当你说:

我会得到这样的输出:

GIF89a,úæÿÿÿ2c½3...

Is我的输出 [...] 二进制数据?

嗯,是的,但你可以阅读它,所以它是文本。二进制数据和文本数据之间的区别有点令人困惑,如果您想更加困惑,请阅读this。如那篇文章所述,问题的原因是编码。

这取决于您如何将其输出到您的页面,但浏览器可能会或可能不会对其接收的数据应用某种编码(Fiddler 检查可以让您了解更多关于通过 HTTP 线路发送的内容)和将其显示为或多或少可读的文本。

这不适用于您的image 变量,它包含来自readAsBinaryString() 结果的实际二进制数据,格式为“原始二进制数据[原文如此]”。哦,松散的类型,谁在乎你返回什么。我猜/希望是一个字节数组。您现在需要将其发送到服务器。文件上传最好由&lt;input type="file" /&gt; 元素处理,但有时您需要使用 AJAX 来处理。你can't 确实通过 JavaScript 进行真正的文件上传,尽管据我所知浏览器对seems to be 的支持正在增加。

因此,您需要POST 将文件内容作为已发布表单的参数之一。为了让二进制数据成功实现这一点,您需要对其进行正确编码以提交表单。

首先确保使用content-typeapplication/x-www-form-urlencoded 发出请求。您可以在 Fiddler 中或通过咨询manual 进行检查。后者根本没有提到任何编码,你要figure that out

现在您需要url-encode 二进制数据才能发布它。此函数返回输入字节,解释为 UTF-8,作为可以安全发布的 URL 编码字符串。然后是服务器端,可以替换

System.Text.Encoding.GetEncoding("ISO-8859-1").GetBytes(_Context.Request["Image"]);

System.Text.Encoding.UTF8.GetBytes(_Context.Request["Image"]);

但是为什么你仍然有那种形式的文件内容呢?正如this answer 提到的,FileReader 还包含一个readAsDataURL 方法,它允许您将reader.result 直接用作POST 变量。

所以,你的代码变成了这样:

var f = $("image").files[0];
var reader = new FileReader();
reader.readAsDataURL(f);
var image = reader.result;

$.ajax({
    url: theUrl,
    type: 'POST',
    data: { Image: image }
});

然后是服务器端,你必须从 base 64 解码数据:

byte[] imageBytes = System.Convert.FromBase64String(_Context.Request["Image"]);

它是如何工作的?

【讨论】:

  • +1 感谢您的回答!不幸的是,我被指示通过线路发送二进制数据而无需对其进行 base64 编码,因为它会产生膨胀的有效负载。我在发送之前在前端对图像进行编码。但是我觉得很奇怪,但这可能是由于我对这个主题的浅薄理解,当我在服务器端获取 UTF8 编码字节时,当图像约为 40kB 时,我的字节数组长度为 25 .如果没有编码和按原样使用(来自我的 OP),我剩下的字节数组长度约为 40k,这是图像的大小,但会出现上述异常。
  • 对不起,不是 25 -- ~159k
  • 经过进一步调查,我稍微了解了这是怎么回事。对二进制数据进行编码似乎是必要的,是的,但会过度膨胀有效载荷,因此大小为 159kB。有没有办法按原样发送二进制数据没有编码?请注意,我们在后端有安全措施,可确保图像的二进制数据有效。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2011-02-20
  • 1970-01-01
  • 1970-01-01
  • 2010-10-25
  • 1970-01-01
  • 2021-02-20
  • 1970-01-01
相关资源
最近更新 更多