HalesEnchanted
HalesEnchanted

Reputation: 665

Upload image from URL to Firebase Storage

I'm wondering how to upload file onto Firebase's storage via URL instead of input (for example). I'm scrapping images from a website and retrieving their URLS. I want to pass those URLS through a foreach statement and upload them to Firebase's storage. Right now, I have the firebase upload-via-input working with this code:

var auth = firebase.auth();
var storageRef = firebase.storage().ref();

function handleFileSelect(evt) {
  evt.stopPropagation();
  evt.preventDefault();
 var file = evt.target.files[0];


  var metadata = {
    'contentType': file.type
  };

  // Push to child path.
  var uploadTask = storageRef.child('images/' + file.name).put(file, metadata);

  // Listen for errors and completion of the upload.
  // [START oncomplete]
  uploadTask.on('state_changed', null, function(error) {
    // [START onfailure]
    console.error('Upload failed:', error);
    // [END onfailure]
  }, function() {
    console.log('Uploaded',uploadTask.snapshot.totalBytes,'bytes.');
    console.log(uploadTask.snapshot.metadata);
    var url = uploadTask.snapshot.metadata.downloadURLs[0];
    console.log('File available at', url);
    // [START_EXCLUDE]
    document.getElementById('linkbox').innerHTML = '<a href="' +  url + '">Click For File</a>';}

Question what do I replace

var file = evt.target.files[0];

with to make it work with external URL instead of a manual upload process?

var file = "https://i.sstatic.net/oonjz.jpg"; doesn't work!

Upvotes: 20

Views: 31377

Answers (4)

dagalti
dagalti

Reputation: 1956

Javascript solution to this using fetch command.

var remoteimageurl = "https://example.com/images/photo.jpg"
var filename = "images/photo.jpg"

fetch(remoteimageurl).then(res => {
  return res.blob();
}).then(blob => {
    //uploading blob to firebase storage
  firebase.storage().ref().child(filename).put(blob).then(function(snapshot) {
    return snapshot.ref.getDownloadURL()
 }).then(url => {
   console.log("Firebase storage image uploaded : ", url); 
  }) 
}).catch(error => {
  console.error(error);
});

Upvotes: 12

galki
galki

Reputation: 8715

This answer is similar to @HalesEnchanted's answer but with less code. In this case it's done with a Cloud Function but I assume the same can be done from the front end. Notice too how createWriteStream() has an options parameter similar to bucket.upload().

const fetch = require("node-fetch");

const bucket = admin.storage().bucket('my-bucket');
const file = bucket.file('path/to/image.jpg');

fetch('https://example.com/image.jpg').then((res: any) => {
  const contentType = res.headers.get('content-type');
  const writeStream = file.createWriteStream({
    metadata: {
      contentType,
      metadata: {
        myValue: 123
      }
    }
  });
  res.body.pipe(writeStream);
});

Upvotes: 10

KpTheConstructor
KpTheConstructor

Reputation: 3291

There's no need to use Firebase Storage if all you're doing is saving a url path. Firebase Storage is for physical files, while the Firebase Realtime Database could be used for structured data.

Example . once you get the image url from the external site this is all you will need :

var externalImageUrl = 'https://foo.com/images/image.png';

then you would store this in your json structured database:

databaseReference.child('whatever').set(externalImageUrl);

OR

If you want to actually download the physical images straight from external site to storage then this will require making an http request and receiving a blob response or probably may require a server side language ..

Javascript Solution : How to save a file from a url with javascript

PHP Solution : Saving image from PHP URL

Upvotes: 10

HalesEnchanted
HalesEnchanted

Reputation: 665

Hopefully this helps somebody else :)

    // Download a file form a url.
 function saveFile(url) {
 // Get file name from url.
  var filename = url.substring(url.lastIndexOf("/") + 1).split("?")[0];
  var xhr = new XMLHttpRequest();
    xhr.addEventListener("load", transferComplete);
xhr.addEventListener("error", transferFailed);
xhr.addEventListener("abort", transferCanceled);

  xhr.responseType = 'blob';
  xhr.onload = function() {
    var a = document.createElement('a');
    a.href = window.URL.createObjectURL(xhr.response); // xhr.response is a blob
    a.download = filename; // Set the file name.
    a.style.display = 'none';
    document.body.appendChild(a);
    a.click();
    delete a;

          if (this.status === 200) {
        // `blob` response
        console.log(this.response);
        var reader = new FileReader();
        reader.onload = function(e) {

                    var auth = firebase.auth();
    var storageRef = firebase.storage().ref();

                     var metadata = {
        'contentType': 'image/jpeg'
      };

                    var file = e.target.result;
                    var base64result = reader.result.split(',')[1];
                    var blob = b64toBlob(base64result);


                       console.log(blob);

                var uploadTask = storageRef.child('images/' + filename).put(blob, metadata);

                uploadTask.on('state_changed', null, function(error) {
        // [START onfailure]
        console.error('Upload failed:', error);
        // [END onfailure]
      }, function() {
        console.log('Uploaded',uploadTask.snapshot.totalBytes,'bytes.');
        console.log(uploadTask.snapshot.metadata);
        var download = uploadTask.snapshot.metadata.downloadURLs[0];
        console.log('File available at', download);
        // [START_EXCLUDE]
        document.getElementById('linkbox').innerHTML = '<a href="' +  download + '">Click For File</a>';
        // [END_EXCLUDE]
      });
            // `data-uri`

        };
        reader.readAsDataURL(this.response);        
    };
  };



  xhr.open('GET', url);
  xhr.send();
}

function b64toBlob(b64Data, contentType, sliceSize) {
  contentType = contentType || '';
  sliceSize = sliceSize || 512;

  var byteCharacters = atob(b64Data);
  var byteArrays = [];

  for (var offset = 0; offset < byteCharacters.length; offset += sliceSize) {
    var slice = byteCharacters.slice(offset, offset + sliceSize);

    var byteNumbers = new Array(slice.length);
    for (var i = 0; i < slice.length; i++) {
      byteNumbers[i] = slice.charCodeAt(i);
    }

    var byteArray = new Uint8Array(byteNumbers);
    byteArrays.push(byteArray);
  }

  var blob = new Blob(byteArrays, {type: contentType});
  return blob;
}



    function transferComplete(evt) {        


            window.onload = function() {
      // Sign the user in anonymously since accessing Storage requires the user to be authorized.
    auth.signInAnonymously().then(function(user) {
        console.log('Anonymous Sign In Success', user);
        document.getElementById('file').disabled = false;
      }).catch(function(error) {
        console.error('Anonymous Sign In Error', error);
      });
    } 
}



function transferFailed(evt) {
  console.log("An error occurred while transferring the file.");
}

function transferCanceled(evt) {
  console.log("The transfer has been canceled by the user.");
}

Upvotes: 3

Related Questions