从server/index.js发送文件时无法在background.js接收文件(制作chrome扩展)

问题描述 投票:0回答:1

所以,我想在 chrome 扩展程序中通过 socket.io 网络共享文件。 我的代码流程如下:

  1. 我在弹出窗口中有一个 file-input 字段,用户可以在其中上传文件。我在 popup.js 接收文件并将相应的缓冲区发送到background.js(其中存在 socket.io 的实例),这里是代码:

//popup.js

shareButton.addEventListener("click", async () => {
  if (fileInputElement.files.length === 0) {
    alert("Choose the file you want to send 📁");
    return;
  }

  let file = fileInputElement.files[0];
  let reader = new FileReader(); 

  reader.onload = () => {
    let buffer = new Uint8Array(reader.result);

    console.log(buffer); 

    initFileShare({ filename: file.name, bufferSize: buffer.length }, buffer);
  };

  reader.readAsArrayBuffer(file);
});

function initFileShare(metadata, buffer) {
  const bufferArray = Array.from(buffer);
  chrome.runtime.sendMessage({ event: "file-share", metadata, bufferArray});
}
  1. background.js监听事件并将其传递到服务器文件(index.js):
  if (message.event === "file-share") {
    const buffer = new Uint8Array(message.buffer);

    socket.emit("file-share", {
      metadata: message.metadata,
      buffer: buffer,
      targetRoomId: curr_roomID,
    });
  }
  1. 在index.js内部,我有一个套接字侦听器,它将文件的块发送到客户端,直到发送整个文件:
io.on("connection", (socket) => {
  console.log(`Connection made to socket id ${socket.id}`);

socket.on("file-share", ({ metadata, buffer, targetRoomId }) => {
 
console.log('metadata : ' , metadata  ) ; 

if (buffer && buffer.slice instanceof Function) {
  console.log('Buffer:');
} else {
  console.log('Invalid buffer:', buffer);
}

console.log('targetRoomId' , targetRoomId) ; 

  // Emit the file metadata to the target socket
  io.to(targetRoomId).emit("file-metadata", metadata);

  // Send file chunks to the target socket
  let chunkSize = 1024;
  let initialChunk = 0;

  function sendNextChunk() {
    if (initialChunk < metadata.bufferSize) {
      let start = initialChunk;
      let end = Math.min(initialChunk + chunkSize, metadata.bufferSize);
      let filePiece = buffer.slice(start, end);

      console.log(metadata.bufferSize, filePiece.length);
 
      io.to(targetRoomId).emit("file-chunk", filePiece);

      initialChunk += chunkSize;
 
      // Check if all chunks have been sent
      if (initialChunk >= metadata.bufferSize) {
        console.log("poori file send ho gyi hai ");
        socket.emit("file-sent", metadata); 
      } else {
        setTimeout(sendNextChunk, 0);
      }
    }
  }

  // Start sending chunks
  sendNextChunk();
});
  1. background.js 在客户端监听 'file-chunk' 事件:

window.addEventListener("load", () => {

  let newFile = {
    buffer: [],
    metadata: null,
  };


  socket.on("file-chunk", (chunk) => {
    let chunkSize = 1024;

    newFile.buffer.push(chunk);
    console.log(newFile.buffer);

    if (newFile.metadata) {
      console.log("Buffer size and metadata buffer size:",newFile.buffer.length,newFile.metadata.bufferSize);

      if (newFile.buffer.length * chunkSize >= newFile.metadata.bufferSize) {
        console.log("All chunks received. Initiating download...");
        console.log("Received buffer size:", newFile.buffer.length);

        let receivedFile = new Blob(newFile.buffer);

        console.log("receivedFile", receivedFile);

        chrome.runtime.sendMessage({
          event: "downloadFile",
          buffer: receivedFile,
          filename: newFile.metadata.filename,
        });

        newFile = {};
        alert("Yayy! File received 🎉");
      }
    }
  });
发送完整文件后,在background.js 中创建的

blob 并不是它应该的样子。我的意思是 blob 的最终大小应该等于文件的大小,但事实并非如此。 由于我无法在客户端接收原始文件,我的意思是当我下载收到的文件时,它只是一个空白文档,上面写着'[object][object]'


让我进一步解释一下,我尝试使用相同的代码做同样的事情,通过制作一个简单的网络应用程序来通过套接字连接共享文件,并且它神奇地工作了。

假设我正在上传一个 ~5kb 文件,请注意输出中的 blob 大小:

带有镀铬扩展

使用网络应用程序

javascript google-chrome-extension websocket socket.io google-chrome-devtools
1个回答
0
投票

chrome

 消息传递不支持 Chrome 中的二进制数据类型。请改用标准 
navigator.serviceWorker
 消息传递机制。

//背景.js

/** @type MessagePort */ let port; self.onmessage = evt => { if (evt.data === 'port') { port = evt.ports[0]; port.onmessage = onPortMessage; } } function onPortMessage(data) { console.log(data); }
//popup.js

async function initSWPort() { const mc = new MessageChannel(); navigator.serviceWorker.controller.postMessage('port', [mc.port2]); return mc.port1; } async function usageExample() { const port = initSWPort(); port.postMessage({ foo: new Blob(['bar']) }); port.onmessage = evt => console.log(evt); }
    
© www.soinside.com 2019 - 2024. All rights reserved.