Business
Jobs
  • About Us
  • Solutions
    • Job Postings
      Post your job and receive qualified candidates in 48h.
    • Candidate Assessments
      500+ technical and psychological tests, plus anti-fraud.
    • Headhunting
      Tailor-made executive search from start to finish.
    • Payroll + EOR
      Payroll dispersal and EOR across 15+ LATAM countries.
  • Pricing
  • Jobs

0

227
Views
Transfer response from remote server to content script (Chrome extension)

What I want to achieve: Upon clicking icon of my Chrome extension, a file with downloaded from remote location and the user is presented with saveAs dialog.

Caveats: I'm using latest manifest from Google, namely v3.

I have edited this post many times as I I was able to achieve more and more. I leave only my latest code.

tl;dr Now almost everything works.Crucial thing is missing: response from server (body) is not saved. Instead string [object Object] is saved.

// when icon is clicked
chrome.action.onClicked.addListener(tab => {
  if (tab.url.startsWith('http')) {
    post({url: tab.url})
    .then(async res => ({
      filename: getFilename(res.headers.get('Content-Disposition')),
      blob: await res.blob()
    }))
    .then(response => {
      console.log(response);
      chrome.scripting.executeScript({
        target: {tabId: tab.id},
        func: saveFile,
        args: [response.filename, response.blob],
      })
    })
    .catch((error) => chrome.scripting.executeScript({
      target: {tabId: tab.id},
      func: showAlert,
      args: [error],
    }));
  }
});

function getFilename(header) {
  return /filename="(.+)"/.exec(header)[1];
}

async function post(data = {}) {
    return await fetch('http://localhost:5000/citation',{
        method: 'POST',
        body: new URLSearchParams(data)
    });
}

function showAlert(error) {
    let message = error.error !== null ? error.error : error.message;
    alert("Error: " + message);
}

async function saveFile(filename, blob) {
  let link = document.createElement('a');

  let url = window.URL.createObjectURL(new Blob([blob],
      {type: 'application/octet-stream'}));
  link.href = url;
  link.download = filename;
  link.click();

  // For Firefox it is necessary to delay revoking the ObjectURL.
  setTimeout(() => {
    window.URL.revokeObjectURL(url);
    }, 250);
}
about 4 years ago · Juan Pablo Isaza
1 answers
Answer question

0

The problem is in serializing the blob object from the chrome extension to the content script, which I think it's a bug in chrome. if you try to log the blob object that saveFile() receives, you will notice it's an empty object.

So instead of passing the blob object, you have to pass another serializable object to the content script.

I have converted the blob object to a base64 object then passed it to the content script.

First, let's create a function to convert the blob object to a base64 object

function blobToBase64(blob) {
    return new Promise((resolve, _) => {
        const reader = new FileReader();
        reader.onloadend = () => resolve(reader.result);
        reader.readAsDataURL(blob);
    });
}

Then convert the blob object

chrome.action.onClicked.addListener(tab => {
  if (tab.url.startsWith('http')) {
    post({url: tab.url})
    .then(async res => ({
      filename: getFilename(res.headers.get('Content-Disposition')),
      blob: await res.blob()
    }))
    .then(async response => {
      var base64 = await blobToBase64(response.blob)
      chrome.scripting.executeScript({
        target: {tabId: tab.id},
        func: saveFile,
        args: [response.filename, base64],
      })
    })
    .catch((error) => chrome.scripting.executeScript({
      target: {tabId: tab.id},
      func: showAlert,
      args: [error],
    }));
  }
});

then in the saveFile() method, you need to convert that base64 into a file

async function saveFile(filename, base64URL) {
    fetch(base64URL)
        .then(res => res.blob())
        .then(blob => {
            let link = document.createElement('a');

            let url = window.URL.createObjectURL(new Blob([blob],
                { type: 'application/octet-stream' }));
            link.href = url;
            link.download = filename;
            link.click();

            // For Firefox it is necessary to delay revoking the ObjectURL.
            setTimeout(() => {
                window.URL.revokeObjectURL(url);
            }, 250);
        })
}

If you will not do anything in saveFile() but download the file, then it will be better to download the file from the extension itself because converting the blob to base64 then getting it back to blob again is slowing down the downloading process.

about 4 years ago · Juan Pablo Isaza Report
Answer question
Find remote jobs

Discover the new way to find a job!

Top jobs
Top job categories
Business
Post vacancy Pricing Sales
Legal
Terms and conditions Privacy policy
© 2026 PeakU Inc. All Rights Reserved.
Andres GPT
Show me some job opportunities
There's an error!