关于获取页面元素的二进制数据并再次上传的问题的解决

3 篇文章 0 订阅
2 篇文章 0 订阅

在实际工作中产生了一个需求。我们负责A系统,B系统为旧系统有相应的权限控制用session来判断登录。

用户会在一系列的人工操作后得到一个html页面的数据,要求我们把这个页面的内容记录下来并提交到A系统中。

由于人工操作和session权限控制的问题。我首先放弃了服务器端的httprequest,webservice之类的方法。

由于A系统为一个BS架构的系统,所以不到万不得已不考虑,winform程序的解决方案。

 

由此,我打算用ajax、JS来解决问题。

首先是获取异主域数据。不论用什么方法,这个都有一个跨域访问的问题。使用jsonp就只支持GET也没有办法,访问二进制数据。

所以用同域代理页是不可避免的。所幸我们可以有B系统的管理权可以在上面放html网页。

所以我们在上面放了一个网页src_prosy.html。

其主要页面元素有

<input type="button" value="得到正文" οnclick="javascript:getHtml();" />
<input type="button" value="得到图片" οnclick="javascript:getImg1();" />
<input type="button" value="得到图片2" οnclick="javascript:getImg2();" />
<form id="form1" method="post" action="self_get_html_and_img.ashx">
<textarea id="textarea_htmltext" cols="20" rows="20" ></textarea>
<textarea id="textarea_image1" cols="20" rows="20" ></textarea>
</form>
<iframe id="iframe1" src="src_login.aspx" width="300px" height="300px"></iframe>



我们首先访问这一页,然后在iframe中完成B系统的登录,人工操作等行为,最终来到了目的页,比如 getTable.asp?id=1233155436236876

下面开始进行数据获取的测试。

 首先使用document.documentElement.outerHTML;

来获取页面的html正文文本,没有问题。

 

function GetIframeInnerHtml(IFrameID) 
{ 
     return document.getElementById(IFrameID).contentWindow.document.documentElement.outerHTML; 
} 

function getHtml()
{
     $("#textarea_htmltext").val(GetIframeInnerHtml("iframe1"));
}

问题来了,在这个正文中有两个图片。我需要得到这两个图片的内容。

jquery是肯定不行了。没办法,直接使用XMLHttpRequest

function getImg1()
{
    $("#iframe1").contents().find("IMG").each(function(){
       
        theimageurl = $(this).attr("src");
        var myDate = new Date();
        var url =  theimageurl + "?time=" + myDate.toLocaleString();    
        var xmlhttp;
        if (window.XMLHttpRequest)
        {// code for IE7+, Firefox, Chrome, Opera, Safari
            xmlhttp=new XMLHttpRequest();
        }
        else
        {// code for IE6, IE5
            xmlhttp=new ActiveXObject("Microsoft.XMLHTTP");
        }
                
        xmlhttp.open("GET",url,true); 
        xmlhttp.setRequestHeader("Content-Type", "application/x-www-form-urlencoded"); 
        xmlhttp.onreadystatechange = function() { 
            if (xmlhttp.readyState == 4 && xmlhttp.status==404) 
            {
                alert('图片数据加载失败:<br />错误信息,访问数据不存在!<br />' + url);
                return;
            }
            if (xmlhttp.readyState == 4 && xmlhttp.status == 200) 
            {
                 //在这里的数据要处理
            }
        } 
        xmlhttp.send();
    });
}


又出现了问题,首先

var theValue = xmlhttp.responseBody IE 会报错

var theValue = xmlhttp.responseStream 没报错,但在后面发送时,表示对象为空或不是对象。

var theValue = xmlhttp.responseText 报c00ce514错误。

这儿产生的错误和我试图进行的解决方案已经记不太清楚了,我好象记得xmlhttp.responseStream可以得到数据,但转Send的时候数据被截断了,好象是碰到0/这种字符串结束符,数据就断开了,自己写一个函数来完成byte[] to Base64String 实在是最后的选择。

所以,如何获取二进制数据并且进行编码就成为了一个大问题。

所以我在csdn上发贴问了下,非常自然的,没有任何有效回答。话说我已经连续三个问题在csdn无解了。.net大版已经快成纯静水工厂了。

以上的牢骚话。下面继续。

有网友介绍使用一套脚本。

/**
 * 将符合字节流的string转化成Blob对象
 * 
 * @param {String} data
 * @return {Blob} 
 * @api public
 */
function binaryToBlob(data) {
    var bb = new BlobBuilder();
    var arr = new Uint8Array(data.length);
    for(var i = 0, l = data.length; i < l; i++) {
        arr[i] = data.charCodeAt(i);
    }
    bb.append(arr.buffer);
    return bb.getBlob();
};

/**
 * 根据URL获取图片的Blob对象
 * 
 * @param {String} url
 * @return {Blob} 
 * @api public
 */
function getImageBlob(url) {
    var r = new XMLHttpRequest();
    r.open("GET", url, false);
    // 详细请查看: https://developer.mozilla.org/En/XMLHttpRequest/Using_XMLHttpRequest#Receiving_binary_data
    // XHR binary charset opt by Marcus Granado 2006 [http://mgran.blogspot.com]
    r.overrideMimeType('text/plain; charset=x-user-defined');
    r.send(null);
    var blob = binaryToBlob(r.responseText);
    blob.name = blob.fileName = url.substring(url.lastIndexOf('/') + 1);
    blob.fileType = "image/jpeg"; //"image/octet-stream";
    return blob;
};

/**
 * 将dataUrl转化成Blob对象
 * 
 * @param {String} dataurl
 * @return {Blob} 
 * @api public
 */
function dataUrlToBlob(dataurl) {
    // data:image/jpeg;base64,xxxxxx
    var datas = dataurl.split(',', 2);
    var blob = binaryToBlob(atob(datas[1]));
    blob.fileType = datas[0].split(';')[0].split(':')[1];
    blob.name = blob.fileName = 'pic.' + blob.fileType.split('/')[1];
    return blob;
};


好心人提供的脚本,又一次印证了IE的不靠谱,以上是FF的。IE中是不可用的,主要有以下几个问题。

首先

r.overrideMimeType('text/plain; charset=x-user-defined');

这个overrideMimeType在IE7中是不支持的高版本的我没试。

其次

其中最为关键的 BlobBuilder 对象,对于IE来说仅在IE10的Beta2中才支持。魂淡啊,我才用IE7!

好了,自己解决吧。除了盗版和八卦以外,度娘是不感兴趣的,google到了。

                var xmldom = new ActiveXObject('MSXML2.DOMDOCUMENT');
                xmldom.async = false;
                var base64 = xmldom.createElement('base64');
                base64.dataType = 'bin.base64';
                base64.nodeTypedValue = xmlhttp.responseBody;
                $("#textarea_image1").val(base64.text);

 

这个xmldom没有问题可以成功得到并使用base64编码来编码数据。

把这个得到base64编码字符串,放到一个textarea中提交,self_get_html_and_img.ashx

                string Base64Str = context.Request["text1"].ToString();
                MemoryStream ms = new MemoryStream(Convert.FromBase64String(Base64Str));
                FileStream fs = new FileStream(AppDomain.CurrentDomain.BaseDirectory + "/a.jpg", FileMode.Create, FileAccess.ReadWrite);
                ms.WriteTo(fs);
                fs.Close();


没问题测试成功。

后继要解决的是,文本长度超出64k限定IE的input控件不支持的问题,最终是把文本截断,生成几个hidden来存放,再提交,这才最终的解决了问题。


 

 

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值