1

I am trying to achieve the following:

  1. User selects file on website
  2. User calls Firebase Cloud function and passes file into the function
  3. Cloud function uploads the file that to storage.

So far I am able to do all of the above, however, when I try to access the above file in storage, a file with no extension is downloaded. The original file was a pdf, but I am still unable able to open it with PDF viewers. It appears I am storing something in storage, although I am not exactly sure what.

Here is an example of how my front-end code works:

const getBase64 = file => new Promise((resolve, reject) => {
  const reader = new FileReader();
  reader.readAsDataURL(file);
  reader.onload = () => resolve(reader.result);
  reader.onerror = error => reject(error);
});

var document_send = document.getElementById('myFile')
var send_button = document.getElementById('send_button')

send_button.addEventListener('click', async () => {
  var sendDocument = firebase.functions().httpsCallable('sendDocument')
  try {
    await sendDocument({
      docu: await getBase64(document_send.files[0])
    })
  } catch (error) {
    console.log(error.message);
  }
})

Here is an example of how my cloud function works:

const functions = require("firebase-functions");
const admin = require("firebase-admin");

exports.sendDocument = functions.https
  .onCall((data, context) => {
    return admin.storage().bucket()
      .file("randomLocationName")
      //.file("randomLocationName"+".pdf") - tried this also
      .save(data.docu);
  })
  .catch((error) => {
    console.log(error.message);
    return error;
  });
});

I do not receive an error message as the function runs without error.

Dharmaraj
  • 47,845
  • 8
  • 52
  • 84
Charmalade
  • 645
  • 1
  • 6
  • 14
  • Does this answer your question? [Uploading file to firebase storage via cloud functions](https://stackoverflow.com/questions/74196431/uploading-file-to-firebase-storage-via-cloud-functions) – Zenoheld Oct 26 '22 at 12:20
  • That was my original question. Someone was kind enough to solve that section of it, but the error I am now getting might extends beyond the scope of that question and hence I have asked another. – Charmalade Oct 26 '22 at 12:27

1 Answers1

1

The save() function seems to take either a string or Buffer as first parameter.

> save(data: string | Buffer, options?: SaveOptions)

The issue arises when you pass the base64 string directly instead of a Buffer. Try refactoring the code as shown below:

return admin.storage().bucket()
  .file("randomLocationName" + ".pdf") // <-- file extension required
  .save(Buffer.from(data.docu, "base64"));

Cloud Functions also have a 10 MB max request size so you won't be able to upload large images that way. You can use Firebase client SDKs to upload files directly, restrict access using security rules and use Cloud Storage Triggers for Cloud Function in case you want to process the file and update the database. Alternatively, use signed URLs for uploading the files if you are using GCS without Firebase.

Dharmaraj
  • 47,845
  • 8
  • 52
  • 84
  • Thanks for you contribution. I implemented the above. The document appears to have been saved into the correct location with the correct extension etc. However, if I try to open the document, I receive the following error in my browser: Failed to load PDF document. – Charmalade Oct 26 '22 at 13:54
  • 1
    @Charmalade can you please share the complete base64 string that you are using i.e the `data.docu` maybe in a [pastebin](https://pastebin.com) so I can test once? – Dharmaraj Oct 26 '22 at 14:01
  • It's too long to paste in comments or edit. I just saved a pdf that said the word "test" on it. Perhaps you could run the same through the function? – Charmalade Oct 26 '22 at 14:23
  • 2
    @Charmalade do you have `data:application/pdf;base64,` at the start of your string? If yes, then you just need to pass the base64 part. Try `Buffer.from(data.docu.split(",")[1], "base64")` – Dharmaraj Oct 26 '22 at 14:33