Pinterest 扩展如何(临时)存储网页中的图像,然后在 iframe 中访问它们?

Posted

技术标签:

【中文标题】Pinterest 扩展如何(临时)存储网页中的图像,然后在 iframe 中访问它们?【英文标题】:How Pinterest extension store (temporarily) images from a web page and then access them in an iframe? 【发布时间】:2016-08-24 03:47:33 【问题描述】:

我一直在尝试创建一个 Pin It button(Pinterest 的扩展),例如 chrome 扩展。 我尝试过的是在单击扩展程序时触发一个脚本,该脚本可以遍历网页上的所有可用图像将其存储在 localStorage。现在我需要调用 iframe(当然是不同的域)访问这些图像。由于只能从同一个域访问本地存储,我很困惑 Pinterest 如何设法存储来自网页的所有图像(暂时而不是在他们的服务器上)然后在 iframe 中使用它。 我还看到了 PinIt Button 扩展的代码,但我无法理解其中的任何内容,因为它被太多混淆/加密或其他任何东西。 我已经阅读了chrome.storage api,但我还不能很好地理解它。我什至不确定这是否是我在这种情况下需要做的事情。 (这是我第一次开发 chrome 扩展)。任何人都可以对此有所了解并指导我实现此功能的最佳方法吗?

附:我已在不使用 <iframe> 的情况下完成了此扩展,但我需要使用 <iframe>编辑 1: 我无法在此处编写完整的代码,但这里是流程/结构/我的尝试 我从background.js开始

chrome.browserAction.onClicked.addListener(function (tab)  /*This fxn fires when extension is clicked*/
    chrome.tabs.executeScript(tab.id, 
        "file": "bookmarklet.js"/*Calls this file*/
    )
);

bookmarklet.js:

jQuery('body').append('<iframe class="vw_parent" id="image-grabber-container" src="" style="height: 100% !important;    width: 100% !important; position: fixed !important; margin: 0% auto !important; background: rgba(17, 17, 17, 0.9) !important; left: 0 !important; right: 0 !important; z-index: 999999999 !important; top: 0% !important;"></iframe>');

jQuery('img').each(function() 
   //do some checks to determine what images need to be stored
   var allImgs = jQuery(this); 
   localStorage.setItem('myLocalImgs', allImgs);
)
vwgrid = "https://mydomain/FileToBeInjectedInIframe.php";
jQuery('#image-grabber-container').attr('src', vwgrid);

现在在FileToBeInjectedInIframe.php

var abcde = localStorage.getItem('myLocalImgs');
console.log(abcde);
//This gives NULL value

编辑 2: 根据 cmets 和 DelightedD0D 的回答,我想解释 此扩展如何工作/应该如何工作 1.用户在任何网页上,然后点击扩展 2. 该网页上所有可用的图像都显示在 iFrame 3. 用户可以从这个 iFrame 中选择多个图像,然后将它们发布到我的网站 4. 使用 iFrame 的原因:如果用户点击 iFrame 中的 POST IMAGE 按钮,并且他没有登录我们的网站发布图像,他应该会在同一个 iFrame 中看到一个登录弹出窗口 5. 如果不是 iFrame,我将如何检查用户是否登录了我的网站,因为我将无法在不同域上读取不同域的会话/cookie。出于同样的原因,我相信(不过我不确定),pinterest 也会在 iFrame 中显示图像

【问题讨论】:

Chrome 扩展可以通过多种方式访问​​任何域的本地存储。但是,您最好将信息存储在Chrome.storage 为了提供更多指导,我们需要准确了解您在做什么。例如,为什么需要 iframe?你在做什么?为什么不只使用图像标签? iframe 到底在哪里?在popup.html中,在扩展打开的一个窗口中,注入到当前页面? 嗯,好吧,这给了我一个更好的画面。 FileToBeInjectedInIframe.php 怎么样?你到底在那儿做什么?我假设有一些服务器处理正在进行,因为它是一个 php 页面? 还没有,但是是的,我稍后要做一些登录的事情,所以我把它做成了一个 php 文件。基本上我会将此 iframe 显示为全屏透明覆盖,其中包含父页面中的所有图像,然后用户可以从中选择多个图像,然后将其发布到某个地方(我们自己的服务器)。 好的,给我一点答案 【参考方案1】:

TL;DR,链接到底部的示例扩展;)

好的,您的问题有点宽泛,但如果我想这样做,我会尝试解释我会采取的方法。

首先,我会删除 iFrame。我看不出有任何理由在这里使用它们,而且我个人不喜欢它们。

我愿意:

有一个内容脚本被注入到所有页面(或特定的,如果需要的话,无论如何) 脚本将有一个 javascript 类,该类将chrome.runtime.onMessage.addListener 添加到页面 这个类会监听来自扩展的消息 将向此类发送消息以触发函数并返回响应 例如像pageAction:"getImages" 这样的消息会触发注入类中的getImages 函数 getImages 将获取所有图像并将它们发送回扩展程序

这里需要注意的是,我更喜欢使用带有类似这样的东西的 base64 字符串编码的图像,而不是来自一大堆不同域的图像 url 以及所有 CORR、链接保护等。出于这个原因,我会让getImagesencodeImagesToBase64.php 进行ajax 调用,服务器会传递一组图像url。 encodeImagesToBase64.php 将返回一个 base64 图像数组,然后将其发送到扩展。

既然扩展程序有一个 base64 图像数组,请将它们保存到 扩展程序的存储区域中的chrome.storage.local。 现在您可以在弹出窗口中显示它们,在新选项卡中显示它们以进行编辑,或其他任何方式 如果您想在页面上以叠加层的形式显示它们,只需在我们创建的 javascript 侦听器类中创建一个函数来执行此操作,并向其发送带有要显示的图像的消息

为了帮助您入门,这里有一个 javascript 侦听器类,我用它来在我的扩展程序中做类似的事情。

(请注意,这依赖于 John Resig 的 Simple JavaScript Inheritance,我强烈建议在编写类时使用它)

// IMPORTANT NOTE you must reload your extension via chrome://extensions 
// AND reload the browser tab in order for changes to this file to be seen!!

var PageActionListener = Class.extend(
    /**
     * This class is meant to be injected into a webpage
     * once there, it listens for messages from an extension
     * messages must pass like pageAction:"someAction", ...  
     * where someAction should map to a function in this class
     * responses should take the form 
     * success:true, pageAction:"someAction", data:"someData", ... 
     */
    attachListener: function() 
        /**
         * Attaches a chrome message listener to the current page
         * this allows the extension to call 
         * the functions in this class from the context of the page
         * and receive responses from those functions via messaging
         */
        var _this=this;
        // Listen for messages from the popup
        chrome.runtime.onMessage.addListener(function (msg, sender, extensionCallback) 
            // First, validate the message links to a function
            if (msg.pageAction) 
                // then make sure its a legit function in this class
                if(typeof _this[msg.pageAction] === "function")
                    // call that fucntion
                    _this[msg.pageAction](msg,function(response)

                        extensionCallback(response);
                    );
                
                else extensionCallback(success:false,msg:msg,error:"Action not found");
                return true;
            
        );
    ,
    getImages:function(msg,callback)
        /**
         * Traverses the DOM looking for images and returning them
         * as an array of base64 strings
         * @param object msg The message that triggered this action
         * @param function callback A function to be called when the action below is complete
         * passes to callback the images gathered from the page
         */
        var images = [];
        var $images= $('img');
        $images.each(function()
            var url = this.src;
            images.push(url);

        );
        // convert images to base64
        $.ajax(
            type: "POST",
            url: "https://somedomain.com/shared-resources/php/encodeImagesToBase64.php", // you'll need to update this to your path
            data: urls:images,
            success: function(response) 
                response.msg=msg;
                send the response back to the extension
                callback(response);
            ,
            error: function(xhr, status, error) 
                callback(success:false,msg:msg,error:error.Message)
            
        );
    ,
    // add other functions that need to be called by the extension here
);

这是encodeImagesToBase64.php的内容,用于将图像转换为base64:

<?php
if (isset($_POST['urls']) )
    $imageStrings=[];
    foreach($_POST['urls'] as $url)
        $imageStrings[]=base64_encode(file_get_contents($url));
    
    echo json_encode(['success'=>true,'images'=>$imageStrings]);
else
    echo json_encode(['success'=>false,'error'=>'Error: No images to encode']);;

Here is an example extension that kindof does what you want.

它需要一种方法来满足您的实际需求,但是,它应该足以让您理解我上面提出的概念和方法。

注意示例扩展使用了我的服务器上托管的encodeImagesToBase64.php 的副本,您需要自己托管并使用其路径更新 ajax 调用。我暂时搁置我的,这样你就可以测试它了,但不要指望它会永远存在:)

【讨论】:

@damio 不正确。如果您将来自另一个域的图像加载到画布中,toDataURL() 将不起作用。 See this question 你必须使用服务器端处理(除非你处理的每个图像都来自支持 CORS 并启用它的域,这里肯定不是这种情况) 首先,感谢您的回答,我非常感谢您的帮助,但是正如我在问题中提到的,我已经在没有 iframe 的情况下实现了此功能,但是我需要使用 iframe 来实现。其次,为什么我需要对图像进行编码,我实际上只需要 URL 并且太临时了,因为我将使用该 URL 来发布该图像。第三,这种 消息传递 方法是否可以在 iFrame 中使用(如果是,那么我的 iFrame 将无法从不同的域读取本地存储)。 请检查我的EDIT 2 @TusharShukla 如果您想要的只是 url,只需跳过 base64 编码并发回 url。就 iframe 而言,不需要它。只需在弹出窗口中提供您的 UI,或者您提到的注入覆盖。让 pageActionListener 或 popup.html 中的 js 通过 ajax 来回发送您需要的任何数据,就像我设置它来编码图像一样。这只是向您展示,您可以在没有 iframe 的情况下完成所有这些事情。它们在这里没用 我也在尝试你的扩展,但它给了我errors

以上是关于Pinterest 扩展如何(临时)存储网页中的图像,然后在 iframe 中访问它们?的主要内容,如果未能解决你的问题,请参考以下文章

当点击扩展程序时,pinterest 如何在任何网站上加载 iframe?

Pinterest 数据切分:解惑快速扩展 MySQL 的数据量

如何使用带有 Pinterest.sharextension 的 UIActivityViewController 设置 Pinterest sourceURL 和描述

如何存储由我的 ASP.NET 模块操作的临时数据?

如何存储已执行过程中的临时表?

临时表作为存储过程中的输出参数