在 CefBrowser 中使用 JavascriptResponse 获取图像(无需下载两次)
Fetching images with JavascriptResponse in CefBrowser (Without downloading twice)
我正在尝试使用 CefSharp
(Offscreen) 获取网页中的图像信息。我想避免两次下载内容(我知道我可以从图像标签中提取 src 字符串,然后再次下载图像)。现在,这是我的代码:
using (var browser = new ChromiumWebBrowser("http://example.com"))
{
//All this does is wait for the entire frame to be loaded.
await LoadPageAsync(browser);
var res1 = await browser.EvaluateScriptAsync("document.getElementsByTagName('img')[0].src");
//res1.Result = the source of the image (A string)
var res2 = await browser.EvaluateScriptAsync("document.getElementsByTagName('img')[0]");
//This causes an APPCRASH on CefSharp.BrowserSubprocess.exe
}
据我所知,CefSharp
已经在下载这些图像以呈现网页。我想避免再次请求从客户端拉取这些图像,并直接从客户端拉取它们。这可能吗? JavascriptResponse
对象的局限性是什么,为什么它会在这里导致 APPCRASH?
一些想法:我考虑过对图像进行 base64 编码,然后以这种方式将其拉出,但这需要我生成一个 canvas 并每次为每个图像填充 canvas想要,生成一个base64字符串,把它作为字符串带到c#,然后再解码回图像。我不知道那会有多高效,但我希望有更好的解决方案。
尝试执行此 javascript...
How to get base64 encoded data from html image
CefSharp 应该有 FileReader api。
然后您可以让 EvaluateScriptAsync 调用 return base64 编码的图像数据。
我是这样解决的:
result = await browser.EvaluateScriptAsync(@"
;(function() {
var getDataFromImg = function(img) {
var canvas = document.createElement('canvas');
var context = canvas.getContext('2d');
context.drawImage(img, 0, 0 );
var dataURL = canvas.toDataURL('image/png');
return dataURL.replace(/^data:image\/(png|jpg);base64,/, '');
}
var images = document.querySelectorAll('.image');
var finalArray = {};
for ( var i=0; i<images.length; i++ )
{
//I just filled in array. Depending on what you're grabbing, you may want to fill
//This with objects instead with text to identify each image.
finalArray.push(getDataFromDiv(images[i]));
}
return finalArray;
})()");
//Helper function for below
private static string FixBase64ForImage(string image)
{
var sbText = new StringBuilder(image, image.Length);
sbText.Replace("\r\n", string.Empty);
sbText.Replace(" ", string.Empty);
return sbText.ToString();
}
//In c# convert the data to a memory stream, and then load it from that.
var bitmapData = Convert.FromBase64String(FixBase64ForImage(image));
var streamBitmap = new MemoryStream(bitmapData);
var sourceImage = (Bitmap) Image.FromStream(streamBitmap);
我正在尝试使用 CefSharp
(Offscreen) 获取网页中的图像信息。我想避免两次下载内容(我知道我可以从图像标签中提取 src 字符串,然后再次下载图像)。现在,这是我的代码:
using (var browser = new ChromiumWebBrowser("http://example.com"))
{
//All this does is wait for the entire frame to be loaded.
await LoadPageAsync(browser);
var res1 = await browser.EvaluateScriptAsync("document.getElementsByTagName('img')[0].src");
//res1.Result = the source of the image (A string)
var res2 = await browser.EvaluateScriptAsync("document.getElementsByTagName('img')[0]");
//This causes an APPCRASH on CefSharp.BrowserSubprocess.exe
}
据我所知,CefSharp
已经在下载这些图像以呈现网页。我想避免再次请求从客户端拉取这些图像,并直接从客户端拉取它们。这可能吗? JavascriptResponse
对象的局限性是什么,为什么它会在这里导致 APPCRASH?
一些想法:我考虑过对图像进行 base64 编码,然后以这种方式将其拉出,但这需要我生成一个 canvas 并每次为每个图像填充 canvas想要,生成一个base64字符串,把它作为字符串带到c#,然后再解码回图像。我不知道那会有多高效,但我希望有更好的解决方案。
尝试执行此 javascript...
How to get base64 encoded data from html image
CefSharp 应该有 FileReader api。
然后您可以让 EvaluateScriptAsync 调用 return base64 编码的图像数据。
我是这样解决的:
result = await browser.EvaluateScriptAsync(@"
;(function() {
var getDataFromImg = function(img) {
var canvas = document.createElement('canvas');
var context = canvas.getContext('2d');
context.drawImage(img, 0, 0 );
var dataURL = canvas.toDataURL('image/png');
return dataURL.replace(/^data:image\/(png|jpg);base64,/, '');
}
var images = document.querySelectorAll('.image');
var finalArray = {};
for ( var i=0; i<images.length; i++ )
{
//I just filled in array. Depending on what you're grabbing, you may want to fill
//This with objects instead with text to identify each image.
finalArray.push(getDataFromDiv(images[i]));
}
return finalArray;
})()");
//Helper function for below
private static string FixBase64ForImage(string image)
{
var sbText = new StringBuilder(image, image.Length);
sbText.Replace("\r\n", string.Empty);
sbText.Replace(" ", string.Empty);
return sbText.ToString();
}
//In c# convert the data to a memory stream, and then load it from that.
var bitmapData = Convert.FromBase64String(FixBase64ForImage(image));
var streamBitmap = new MemoryStream(bitmapData);
var sourceImage = (Bitmap) Image.FromStream(streamBitmap);