7

简而言之,我想将图像的二进制数据发送到我的处理程序,该处理程序将作为字节数组保存在数据库中。使用我的 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 转换是否包含有关其数据类型的元数据?

4

1 回答 1

9

看看你在代码中做了什么真的很有帮助,这就是我要求你展示它的原因。我你的代码是这样的:

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...

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

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

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

但是,这不适用于您的image变量,它包含来自readAsBinaryString()结果的实际二进制数据,格式为"raw binary data[sic]"。哦,松散的类型,谁在乎你返回什么。我猜/希望是一个字节数组。您现在需要将其发送到服务器。文件上传最好由<input type="file" />元素处理,但有时您需要使用 AJAX 进行操作。您不能真正通过 JavaScript 进行真正的文件上传,尽管据我所知浏览器支持似乎正在增加。

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

首先确保请求是使用content-typeof发出的application/x-www-form-urlencoded。您可以在 Fiddler 中或通过查阅手册进行检查。后者根本没有提到任何编码,你必须弄清楚

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

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

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

但是,为什么您仍然拥有该格式的文件内容?正如这个答案所提到的,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"]);

这是如何运作的?

于 2013-05-17T23:59:02.583 回答