如何在清单v3扩展服务工作者中使用URL.CreateObjectUrl

发布于 2025-02-03 21:33:54 字数 647 浏览 4 评论 0 原文

我的扩展名创建了带有图像的拉链档案。然后我使用chrome.downloads.download下载我的存档到设备。

const url = URL.createObjectURL(archiveBlob);

chrome.downloads.download({
  url,
  filename: `${archiveData.fileName}.zip`,
  saveAs: false
});

当我将ArrayBuffer转换为Image时,我的扩展程序中还需要URL.CreateObjectUrl

async bufferToImage(buffer: ArrayBuffer): Promise<InstanceType<typeof Image>> {
  return new Promise((res, rej) => {
    const blob = new Blob([buffer]);
    const objectURL = URL.createObjectURL(blob);
    const img = new Image();
    img.src = objectURL;
    img.onload = () => res(img);
  });
}

My extension creates zip archive with images inside. And I used chrome.downloads.download to download my archive to device.

const url = URL.createObjectURL(archiveBlob);

chrome.downloads.download({
  url,
  filename: `${archiveData.fileName}.zip`,
  saveAs: false
});

And also URL.createObjectURL required in my extension when I convert ArrayBuffer to Image

async bufferToImage(buffer: ArrayBuffer): Promise<InstanceType<typeof Image>> {
  return new Promise((res, rej) => {
    const blob = new Blob([buffer]);
    const objectURL = URL.createObjectURL(blob);
    const img = new Image();
    img.src = objectURL;
    img.onload = () => res(img);
  });
}

How can I do it now in Manifest v3 ServiceWorker?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

别闹i 2025-02-10 21:33:54

您可以将 blob 转换为 base64

如果要导出图像:

/**
 * capture and download
 * 截图并下载
 */
chrome.runtime.onMessage.addListener((request, sender, sendResponse) => {

  chrome.tabs.query({ active: true }, async (tabs) => {
    const tab = tabs[0];
    const image = await chrome.tabs.captureVisibleTab(tab.windowId, {
      format: "png",
    });

    chrome.downloads.download({
      url: image,
      filename: "1.png",
    })

  });
});

如果要导出zip:

import JSZip from "jszip";

/**
 * example: captureVisibleTab and export zip
 * 案例:截图并导出zip
 */
chrome.runtime.onMessage.addListener((request, sender, sendResponse) => {
  chrome.tabs.query({ active: true }, async (tabs) => {
    const tab = tabs[0];

    // capture
    const image = await chrome.tabs.captureVisibleTab(tab.windowId, {
      format: "png",
    });

    // image base64 => blob
    const blob = await fetch(image).then((response) => response.blob());

    // zip image
    const zip = new JSZip();
    zip.file("insta-snap1.png", blob, { binary: true });
    const zipData = await zip.generateAsync({
      type: "base64",
    });

    // download zip with base64
    chrome.downloads.download({
      url: `data:application/octet-stream;base64,${zipData}`,
      filename: "test.zip",
    });
  });
});

You can convert Blob to base64.

If you want export image:

/**
 * capture and download
 * 截图并下载
 */
chrome.runtime.onMessage.addListener((request, sender, sendResponse) => {

  chrome.tabs.query({ active: true }, async (tabs) => {
    const tab = tabs[0];
    const image = await chrome.tabs.captureVisibleTab(tab.windowId, {
      format: "png",
    });

    chrome.downloads.download({
      url: image,
      filename: "1.png",
    })

  });
});

If you want export zip:

import JSZip from "jszip";

/**
 * example: captureVisibleTab and export zip
 * 案例:截图并导出zip
 */
chrome.runtime.onMessage.addListener((request, sender, sendResponse) => {
  chrome.tabs.query({ active: true }, async (tabs) => {
    const tab = tabs[0];

    // capture
    const image = await chrome.tabs.captureVisibleTab(tab.windowId, {
      format: "png",
    });

    // image base64 => blob
    const blob = await fetch(image).then((response) => response.blob());

    // zip image
    const zip = new JSZip();
    zip.file("insta-snap1.png", blob, { binary: true });
    const zipData = await zip.generateAsync({
      type: "base64",
    });

    // download zip with base64
    chrome.downloads.download({
      url: `data:application/octet-stream;base64,${zipData}`,
      filename: "test.zip",
    });
  });
});
Spring初心 2025-02-10 21:33:54

tl; dr:使用 data urls urls 。服务工作者没有 url.createobjectUrl 由于电位内存泄漏

什么是 url.createobjecturl 做什么?我们为什么使用它?

这个小函数可以做一些我们可以将其与 chrome.download这样的功能以及函数以及函数一起使用的一些事情。

  • 唯一的文件名
  • 字符串内容(文本)
  • MIME类型(选项),

因为它需要一个斑点对象,所以我们已经提供了内容(参数1)和类型 (参数2;选项)。

url.createobjecturl 的返回值不仅是任何URL。此URL是您提供的内容的结果。尝试访问这些URL,这是您的内容托管。

例如“ Hello world” =&gt; url.createobjecturl =&gt; blob:chrome-extension://.../&ult; uuid&gt; =&gt; 现在, “ Hello World”

,如我们的示例,当使用 chrome.downloads 时,将返回的URL值作为 url 参数,文件类型和文件名是自动分配的,当您的内容被重新下载时。

因此,如果您想复制此功能:

// creating a Zip file download prompt
// external variables: archiveData, archiveBlob
const data = btoa(archiveBlob);
const filename = `${archiveData.fileName}.zip`;
const mediatype = "application/octet-stream";
const url = `data:${mediatype};base64,${data}`;

chrome.downloads.download({
    filename,
    url,
});
// base64 binary image data and provide URL to load it
return new Promise((res, rej) => {
    const blob = btoa(buffer);
    const objectURL = `data:;base64,${blob}`;
    const img = new Image();
    img.src = objectURL;
    img.onload = () => res(img);
});

TL;DR: Use Data URLs. Service Workers do not have URL.createObjectURL due to potential memory leaks.

What is URL.createObjectURL doing and why are we using it?

This little function does a few things that we can take for granted when we use it along with functions like chrome.download.

  • Unique filename
  • String content (text)
  • Mime type (options)

Because it requires a Blob object, we are already providing the content (argument 1) and the type (argument 2; options).

The return value of URL.createObjectURL is not just any URL. This URL is the result of your provided content being stored. Try visiting these URLs, it is your content being hosted.

e.g. "hello world" => URL.createObjectURL => blob:chrome-extension://.../<uuid> => "hello world"

Now, as for our example when using chrome.downloads, by providing the returned URL value as the url parameter, the file type and file name are automatically assigned, when your content is being retried to download.

Thus, if you want to replicate this functionality:

// creating a Zip file download prompt
// external variables: archiveData, archiveBlob
const data = btoa(archiveBlob);
const filename = `${archiveData.fileName}.zip`;
const mediatype = "application/octet-stream";
const url = `data:${mediatype};base64,${data}`;

chrome.downloads.download({
    filename,
    url,
});
// base64 binary image data and provide URL to load it
return new Promise((res, rej) => {
    const blob = btoa(buffer);
    const objectURL = `data:;base64,${blob}`;
    const img = new Image();
    img.src = objectURL;
    img.onload = () => res(img);
});
蓝眼睛不忧郁 2025-02-10 21:33:54

在Chrome扩展中不允许通过消息直接传递 BLOB 对象。

您可以将 blob 对象转换为基本64编码的字符串。这是如何进行转换的示例:

背景脚本中,将 blob 转换为 base64String

const response = await fetch(iconUrl, {
    headers: {
        "Content-Type": "application/json",
    }
})
if (!response.ok) {
    throw new Error(`HTTP error! status: ${response.status}`)
}
const imageBlob = await response.blob();
//
const base64String = await new Promise((resolve) => {
    const reader = new FileReader();
    reader.onloadend = () =>resolve(reader.result);
    reader.readAsDataURL(imageBlob);
});
console.log("image base64String ",base64String)

content 脚本,接收 base64String ,然后转换回 blob

// load base64String as image
if (pageIcon.startsWith('data:image/')) {
    return <img src={pageIcon} alt="Icon" className="w-4 h-4" />;
}

// If you still need blob objects, here's the reference
const binaryString = atob(base64String.split(',')[1]);
const len = binaryString.length;
const bytes = new Uint8Array(len);
for (let i = 0; i < len; i++) {
    bytes[i] = binaryString.charCodeAt(i);
}
const blob = new Blob([bytes], { type: 'image/png' });

Passing Blob objects directly via Message is not allowed in Chrome extensions.

You can convert a Blob object to a base64-encoded string. Here's an example of how to do the conversion:

In the background script, convert the blob to a base64String:

const response = await fetch(iconUrl, {
    headers: {
        "Content-Type": "application/json",
    }
})
if (!response.ok) {
    throw new Error(`HTTP error! status: ${response.status}`)
}
const imageBlob = await response.blob();
//
const base64String = await new Promise((resolve) => {
    const reader = new FileReader();
    reader.onloadend = () =>resolve(reader.result);
    reader.readAsDataURL(imageBlob);
});
console.log("image base64String ",base64String)

In the content script, receive the base64String and convert back to a blob:

// load base64String as image
if (pageIcon.startsWith('data:image/')) {
    return <img src={pageIcon} alt="Icon" className="w-4 h-4" />;
}

// If you still need blob objects, here's the reference
const binaryString = atob(base64String.split(',')[1]);
const len = binaryString.length;
const bytes = new Uint8Array(len);
for (let i = 0; i < len; i++) {
    bytes[i] = binaryString.charCodeAt(i);
}
const blob = new Blob([bytes], { type: 'image/png' });
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文