如何将Blob从Chrome扩展程序传递到Chrome应用

CJ阿尔法

一点背景

我已经在Chrome扩展程序上工作了几天,该扩展程序一天多次拍摄给定网页的屏幕截图。以此为指导,事情按预期进行。

不过,有一个小的需求扩展无法满足。用户必须有权访问保存图像(屏幕快照)的文件夹,但Chrome扩展程序无权访问文件系统另一方面,Chrome Apps可以。因此,环顾四周后,我得出结论,我必须同时创建Chrome扩展程序和Chrome应用程序。这个想法是,扩展程序将创建屏幕快照的blob,然后将该blob发送到应用程序,然后将其作为图像保存到用户指定的位置。而这正是我正在做的事情–我正在扩展端创建一个屏幕截图,然后将其发送到应用程序,在该应用程序中,用户被要求选择保存图像的位置。

问题

直到节省部分,一切都按预期进行。在扩展上创建Blob,将其发送到应用程序,由应用程序接收,要求用户将文件保存在哪里,并保存图像...。生成的图像不可用。当我尝试打开它时,出现一条消息“无法确定类型”。以下是我使用的代码:

  1. 首先在扩展端,创建一个blob并将其发送过来,如下所示:

     chrome.runtime.sendMessage(
        APP_ID, /* I got this from the app */
        {myMessage: blob}, /* Blob created previously; it's correct */
        function(response) {
          appendLog("response: "+JSON.stringify(response));
        }
     );
    
  2. 然后,在APP端,我收到了Blob,并尝试像这样保存它:

    // listen for external messages
    chrome.runtime.onMessageExternal.addListener(
      function(request, sender, sendResponse) {
        if (sender.id in blacklistedIds) {
          sendResponse({"result":"sorry, could not process your message"});
          return;  // don't allow this extension access
        } else if (request.incomingBlob) {
          appendLog("from "+sender.id+": " + request.incomingBlob);
    
          // attempt to save blob to choosen location
          if (_folderEntry == null) {
             // get a directory to save in if not yet chosen
             openDirectory();
          }
          saveBlobToFile(request.incomingBlob, "screenshot.png");
    
          /*
          // inspect object to try to see what's wrong
          var keys = Object.keys(request.incomingBlob);
          var keyString = "";
          for (var key in keys) {
             keyString += " " + key;
          }
          appendLog("Blob object keys:" + keyString);
          */
    
          sendResponse({"result":"Ok, got your message"});
        } else {
          sendResponse({"result":"Ops, I don't understand this message"});
        }
      }
    );
    

    这是执行实际保存的APP上的功能:

    function saveBlobToFile(blob, fileName) {
      appendLog('entering saveBlobToFile function...');
      chrome.fileSystem.getWritableEntry(_folderEntry, function(entry) {         
        entry.getFile(fileName, {create: true}, function(entry) {         
          entry.createWriter(function(writer) {
            //writer.onwrite = function() {
            //   writer.onwrite = null;
            //   writer.truncate(writer.position);
            //};
            appendLog('calling writer.write...');
            writer.write(blob);                       
            // Also tried writer.write(new Blob([blob], {type: 'image/png'}));
          });
        });
      });
    }
    

没有错误。没有打ic。该代码有效,但是图像无用。我到底在想什么?我要去哪里错了?是我们只能在扩展程序/应用程序之间传递字符串吗?Blob在途中是否已损坏?我的应用程序是在扩展程序上创建的,因此无法访问它吗?任何人都可以阐明一下吗?

更新(9/23/14)对不起,我很晚才进行更新,但是我被分配到了一个不同的项目,直到两天前我才回到这个状态。

因此,在环顾四周之后,我决定接受@Danniel Herr的建议,该建议建议使用SharedWorker和嵌入在应用程序框架中的页面。这个想法是,扩展程序将把blob提供给SharedWorker,后者将blob转发到扩展程序中嵌入应用程序框架中的页面。该页面然后使用parent.postMessage(...)将Blob转发到应用程序。这有点麻烦,但这似乎是我唯一的选择。

让我发布一些代码,使它更有意义:

扩大:

var worker = new SharedWorker(chrome.runtime.getURL('shared-worker.js'));
worker.port.start();
worker.postMessage('hello from extension'); // Can send blob here too
worker.port.addEventListener("message", function(event) {
   $('h1Title').innerHTML = event.data;
});

proxy.js

var worker = new SharedWorker(chrome.runtime.getURL('shared-worker.js'));
worker.port.start();

worker.port.addEventListener("message",
   function(event) {      
      parent.postMessage(event.data, 'chrome-extension://[extension id]');
   }
);

proxy.html

<script src='proxy.js'></script>

shared-worker.js

var ports = [];
var count = 0;
onconnect = function(event) {
    count++;
    var port = event.ports[0];
    ports.push(port);
    port.start(); 

    /* 
    On both the extension and the app, I get count = 1 and ports.length = 1
    I'm running them side by side. This is so maddening!!!
    What am I missing?
    */
    var msg = 'Hi, you are connection #' + count + ". ";
    msg += " There are " + ports.length + " ports open so far."
    port.postMessage(msg);

    port.addEventListener("message",       
      function(event) {
        for (var i = 0; i < ports.length; ++i) {
            //if (ports[i] != port) {
                ports[i].postMessage(event.data);
            //}
        }
    });
};

在应用程式上

context.addEventListener("message", 
    function(event) {
        appendLog("message from proxy: " + event.data);
    } 
);

这就是执行流程...在扩展上,我创建了一个共享工作器并向其发送消息。共享工作者应该能够接收Blob,但是出于测试目的,我只发送一个简单的字符串。

接下来,共享工作者将收到消息并将其转发给已连接的每个人。此时,应用程序框架内的proxy.html / js确实已连接,并且应该接收共享工作程序转发的任何内容。

接下来,proxy.js [应该]从共享工作程序接收消息,并使用parent.postMessage(...)将其发送到应用程序。该应用程序正在通过window.addEventListener(“ message”,...)进行监听。

要测试此流程,我首先打开应用程序,然后单击扩展按钮。我在该应用上未收到任何消息。我也没有错误。

该扩展程序可以与共享工作程序来回通信。该应用程序可以很好地与共享工作者进行通信。但是,我从扩展名->代理-> app发送的消息未到达该应用程序。我想念什么?

对那些长期任职的家伙们感到抱歉,但是我希望有人能给我一些启发,因为这使我发疯。

谢谢

CJ阿尔法

感谢您的帮助。我发现解决方案是将blob转换为扩展名上的二进制字符串,然后使用chrome的消息传递API将字符串发送到应用程序。然后在应用程序上,我执行了Francois建议的将二进制字符串转换回blob的操作。我之前曾尝试过此解决方案,但由于我在应用程序上使用了以下代码,因此无法使用:

blob = new Blob([blobAsBinString], {type: mimeType});

该代码可能适用于文本文件或简单字符串,但不适用于图像(可能由于字符编码问题)。那是我发疯的地方。解决方案是使用Francois从一开始就提供的内容:

var bytes = new Uint8Array(blobAsBinString.length);
for (var i=0; i<bytes.length; i++) {
   bytes[i] = blobAsBinString.charCodeAt(i);            
}             
blob = new Blob([bytes], {type: mimeString});

该代码重新训练了二进制字符串的完整性,并且在应用程序上正确创建了blob。

现在,我还结合了我在这里的一些人和其他地方的RobW所建议的内容,这是将blob分成多个块,然后以这种方式将其发送,以防blob过大。整个解决方案如下:

关于扩展:

function sendBlobToApp() {  

  // read the blob in chunks/chunks and send it to the app
  // Note: I crashed the app using 1 KB chunks. 1 MB chunks work just fine. 
  // I decided to use 256 KB as that seems neither too big nor too small
  var CHUNK_SIZE = 256 * 1024;
  var start = 0;
  var stop = CHUNK_SIZE;      

  var remainder = blob.size % CHUNK_SIZE;
  var chunks = Math.floor(blob.size / CHUNK_SIZE);      

  var chunkIndex = 0;

  if (remainder != 0) chunks = chunks + 1;           

  var fr = new FileReader();
  fr.onload = function() {
      var message = {
          blobAsText: fr.result,
          mimeString: mimeString,                 
          chunks: chunks 
      };          
      // APP_ID was obtained elsewhere
      chrome.runtime.sendMessage(APP_ID, message, function(result) {
          if (chrome.runtime.lastError) {
              // Handle error, e.g. app not installed
              // appendLog is defined elsewhere
              appendLog("could not send message to app");
          } 
      });

      // read the next chunk of bytes
      processChunk();
  };
  fr.onerror = function() { appendLog("An error ocurred while reading file"); };
  processChunk();

  function processChunk() {
     chunkIndex++;         

     // exit if there are no more chunks
     if (chunkIndex > chunks) {
        return;
     }

     if (chunkIndex == chunks && remainder != 0) {
        stop = start + remainder;
     }                           

     var blobChunk = blob.slice(start, stop);

     // prepare for next chunk
     start = stop;
     stop = stop + CHUNK_SIZE;

     // convert chunk as binary string
     fr.readAsBinaryString(blobChunk);
  } 
}

在APP上

chrome.runtime.onMessageExternal.addListener(
  function(request, sender, sendResponse) {
    if (sender.id in blacklistedIds) {
      return;  // don't allow this extension access
    } else if (request.blobAsText) {                  
       //new chunk received  
      _chunkIndex++;                   

      var bytes = new Uint8Array(request.blobAsText.length);                     
      for (var i=0; i<bytes.length; i++) {
         bytes[i] = request.blobAsText.charCodeAt(i);            
      }         
      // store blob
      _blobs[_chunkIndex-1] = new Blob([bytes], {type: request.mimeString});           

      if (_chunkIndex == request.chunks) {                      
         // merge all blob chunks
         for (j=0; j<_blobs.length; j++) {
            var mergedBlob;
            if (j>0) {                  
               // append blob
               mergedBlob = new Blob([mergedBlob, _blobs[j]], {type: request.mimeString});
            }
            else {                  
               mergedBlob = new Blob([_blobs[j]], {type: request.mimeString});
            }
         }                         

         saveBlobToFile(mergedBlob, "myImage.png", request.mimeString);
      }
    }
 }
);

本文收集自互联网,转载请注明来源。

如有侵权,请联系[email protected] 删除。

编辑于
0

我来说两句

0条评论
登录后参与评论

相关文章

来自分类Dev

如何将Google表格集成到Chrome扩展程序

来自分类Dev

将数据从Chrome扩展名传递到.net应用

来自分类Dev

将数据从Chrome扩展程序传递到网页

来自分类Dev

从网站将信息传递到chrome扩展程序

来自分类Dev

如何将Angular对象传递给Google Chrome扩展程序中的Javascript函数?

来自分类Dev

如何从Chrome扩展程序启动Chrome应用?

来自分类Dev

如何将HTML格式的文本从Google Chrome扩展程序复制到剪贴板上?

来自分类Dev

如何将扩展程序从一个Chrome安装复制到另一个安装?

来自分类Dev

Chrome扩展程序:如何将HTML附加到新创建的chrome标签中?

来自分类Dev

如何将chrome.alarms用于Google Chrome扩展程序

来自分类Dev

如何从扩展程序获取Chrome应用的ID

来自分类Dev

Chrome扩展程序和Blob

来自分类Dev

在Swift中,我如何将永久变量从主iOS应用传递到扩展程序(例如,今天的扩展程序,自定义键盘)

来自分类Dev

chrome扩展程序内部是否使用JSON.stiringify将Message传递到后台页面?

来自分类Dev

chrome扩展程序-将数据从后台传递到自定义html页面

来自分类Dev

如何通过Chrome应用了解Chrome扩展程序ID

来自分类Dev

如何将数据从Windows应用程序传递到Web应用程序?

来自分类Dev

如何将NSString数据从我的应用程序传递到iOS本机应用程序

来自分类Dev

在Chrome扩展程序中将变量从后台传递到弹出窗口

来自分类Dev

Chrome扩展程序消息从弹出窗口传递到内容

来自分类Dev

在Chrome打包的应用和扩展程序之间传递消息

来自分类Dev

Chrome扩展程序消息传递

来自分类Dev

Chrome扩展程序消息传递-如何传递HTML

来自分类Dev

如何将Web应用程序转换为本地Chrome应用程序

来自分类Dev

如何将chrome扩展ID动态发送到网页以进行消息传递

来自分类Dev

扩展程序内的Chrome应用

来自分类Dev

解码Chrome应用或扩展程序

来自分类Dev

如何将图像 blob 从 MySQL 检索到 C# 应用程序中?

来自分类Dev

Chrome应用程序:如何在后台将Blob内容保存到fileSystem?

Related 相关文章

  1. 1

    如何将Google表格集成到Chrome扩展程序

  2. 2

    将数据从Chrome扩展名传递到.net应用

  3. 3

    将数据从Chrome扩展程序传递到网页

  4. 4

    从网站将信息传递到chrome扩展程序

  5. 5

    如何将Angular对象传递给Google Chrome扩展程序中的Javascript函数?

  6. 6

    如何从Chrome扩展程序启动Chrome应用?

  7. 7

    如何将HTML格式的文本从Google Chrome扩展程序复制到剪贴板上?

  8. 8

    如何将扩展程序从一个Chrome安装复制到另一个安装?

  9. 9

    Chrome扩展程序:如何将HTML附加到新创建的chrome标签中?

  10. 10

    如何将chrome.alarms用于Google Chrome扩展程序

  11. 11

    如何从扩展程序获取Chrome应用的ID

  12. 12

    Chrome扩展程序和Blob

  13. 13

    在Swift中,我如何将永久变量从主iOS应用传递到扩展程序(例如,今天的扩展程序,自定义键盘)

  14. 14

    chrome扩展程序内部是否使用JSON.stiringify将Message传递到后台页面?

  15. 15

    chrome扩展程序-将数据从后台传递到自定义html页面

  16. 16

    如何通过Chrome应用了解Chrome扩展程序ID

  17. 17

    如何将数据从Windows应用程序传递到Web应用程序?

  18. 18

    如何将NSString数据从我的应用程序传递到iOS本机应用程序

  19. 19

    在Chrome扩展程序中将变量从后台传递到弹出窗口

  20. 20

    Chrome扩展程序消息从弹出窗口传递到内容

  21. 21

    在Chrome打包的应用和扩展程序之间传递消息

  22. 22

    Chrome扩展程序消息传递

  23. 23

    Chrome扩展程序消息传递-如何传递HTML

  24. 24

    如何将Web应用程序转换为本地Chrome应用程序

  25. 25

    如何将chrome扩展ID动态发送到网页以进行消息传递

  26. 26

    扩展程序内的Chrome应用

  27. 27

    解码Chrome应用或扩展程序

  28. 28

    如何将图像 blob 从 MySQL 检索到 C# 应用程序中?

  29. 29

    Chrome应用程序:如何在后台将Blob内容保存到fileSystem?

热门标签

归档