lpetrucci
lpetrucci

Reputation: 1677

Node.js: new File from fetched PNG URL

I'm currently trying to upload an image to Supabase's Storage, this looks fairly simple from the docs

const { data, error } = await supabase.storage
  .from('avatars')
  .upload('public/avatar1.png', avatarFile)

Unfortunately Supabase expects a File type.

In my API I have a url that points to the image I want to save, what's the best way for me to get the image at my URL as a File in Node.js?

I have tried this:

  let response;
  try {
    // fetch here is from the isomorphic-unfetch package so I can use it sever-side
    response = await fetch('https://example.com/image.jpeg');
  } catch (err) {
    throw new Error(err);
  }

  let data = await response?.blob();

  let metadata = {
    type: 'image/jpeg',
  };

  let file = new File([data], 'test.jpg', metadata);
  return file;

But I get a ReferenceError: File is not defined, which leads me to believe only the browser has access to creating a new File().

All I can find are answers about fs, which I think is Google getting confused. I don't think I can use fs to return a File type.

Any ideas?

Upvotes: 1

Views: 1099

Answers (3)

lpetrucci
lpetrucci

Reputation: 1677

After a lot of research, this isn't actually possible. I've tried a lot of npm packages that advertise being able to convert blobs to Files, but none of them seemed to work.

The only actual solution is to download the file as the other answers have suggested, but in my situation it just wasn't doable.

Upvotes: 1

Apoorva Chikara
Apoorva Chikara

Reputation: 8773

You can do something like this:

const fspromise = require('fs').promises;
 let response;
  try {
    // fetch here is from the isomorphic-unfetch package so I can use it sever-side
    response = await fetch('https://example.com/image.jpeg');
  } catch (err) {
    throw new Error(err);
  }

  let data = await response?.blob();

  let metadata = {
    type: 'image/jpeg',
  };

const file = blob2file(data);

function blob2file(blobData) {
  const fd = new FormData();
  fd.set('a', blobData);
  return fd.get('a');
}


const { data, error } = await supabase.storage
  .from('avatars')
  .upload('public/avatar1.png', file)

Upvotes: 1

Nour Alhadi Mahmoud
Nour Alhadi Mahmoud

Reputation: 453

So what you can do is: send an HTTP request to the file

const fs = require('fs');
const http = require('http'); // maybe https?

const fileStream = fs.createWriteStream('image.png');

const request = http.get('URL_HERE', function(response) {
  response.pipe(fileStream);
});

The above code fetches and writes the file from the URL to your server, and then you need to read it and send it to the upload process.

const finalFile = fs.readFileSync( 'image.png', optionsObject );

And now you have your file object do your upload, then don't forget to remove it if not needed anymore.

Upvotes: 1

Related Questions