0

So i'm trying to send image files uploaded by my users to firebase storage using the file type input element. Like this:

<input
className={inputStyle}
{...register("donorPhotoFile")}
type="file"
accept=".png, .jpg,.jpeg"
></input>
So when I try to console.log the value returned of that input, im getting an object with the following properties:

name: "file_name.jpg",
size: ,
type: "image/png"
webkitRelativePath: ""

The /api/firebase is my api endpoint in next.js to upload my form data to firestore. From the firebase documentation, the 'file' should come from File API which I've did but its always unsuccessful and im not sure what im doing wrong.

  const submitForm = async (data) => {
    const  imageFile = data.donorPhotoFile[0] //this is the file 

    const imageUpload = await fetch("/api/firestorage", {
      method: "POST",
      body: imageFile
    });

    const res = await imageUpload.json()
    console.log(res)
 }
 
 //in my firestorage endpoint  i've done this:
 
 const storage = getStrorage(app) //app here is an instance of my firebase initialized
 
 const handler =  async (req, res) => {
  const storageRef= ref(storage) 
  const imageFile = req.body
  
  try {
    uploadBytes(storageRef, imageFile);
    res.status(200).json({statusRes: "success"})
  } catch(error) {
    res.status(400).json({statusRes: "failed", errorMessage: error})
  }
 }

Doing that returns a storage/invalid-root-operation error code with a message of:

"Firebase Storage: The operation 'uploadBytes' cannot be performed on a root reference, create a non-root reference using child, such as .child('file.png')

So tried to make a reference to a specific file and inserted the file name as a second parameter to storageRef like this:

const storageRef = ref(storage).child(`images/${req.body.name}`)

but its still not working but now i'm getting an empty error object so I can't figure out what's wrong now. So i actually tried checking what req.body is and it's returning this: file object in my api endpoint

I don't understand why is it like that? And what im actually looking at? What i've sent in my post request is a File object. Like this: File object i attached to my post request

  • You can upload files to Firebase storage directly from client. Is there any reason to create an API endpoint to do this? – Dharmaraj Apr 10 '22 at 12:36
  • @Dharmaraj next.js only allows you to access environment variables in api routes. If i were to do it client side, I would need to expose my api keys in the client side as well. I haven't found a work around so i do all my api calls now in the api routes. –  Apr 10 '22 at 12:46
  • 1
    If you are referring to the API key in Firebase config then that is meant to be public, There's no issue with doing this on client side as long as you have security rules setup. Checkout [Is it safe to expose Firebase apiKey to the public?](https://stackoverflow.com/q/37482366/13130697) – Dharmaraj Apr 10 '22 at 12:58

1 Answers1

0

You can create a reference to a path using Modular SDK as shown below:

const storageRef= ref(storage, `images/${req.body.name}`) 

The .child() method is used in older name-spaced syntax.

Dharmaraj
  • 47,845
  • 8
  • 52
  • 84
  • Still not working unfortunately. Error object returns empty still so i can't figure out where is the error exactly. –  Apr 10 '22 at 12:49
  • @Duts the problem is `req.body` is not a your [File](https://developer.mozilla.org/en-US/docs/Web/API/File) object. I would recommend uploading files directly from client with security rules setup as I don't see anything else being processed in the API route. The API key is meant to be public as I mentioned in the comment above. (Not the service account if you are using Firebase Admin SDK). If you want to upload a file via an API then you'll have to use something like [multer](https://www.npmjs.com/package/multer) for file handling. – Dharmaraj Apr 10 '22 at 13:02
  • Can i ask why is it that req.body is not my File object although it's the one I attached to my post request? –  Apr 10 '22 at 13:06
  • 1
    @Duts I'd recommend checking out [MDN](https://stackoverflow.com/q/36067767/13130697) for more information on File and uploading files using `fetch`. They have detailed examples for this. Then you can checkout https://stackoverflow.com/a/56767117/13130697 to parse your FormData from the request in API. – Dharmaraj Apr 10 '22 at 13:10
  • a day after i still haven't figured out why body.req is not my File object. So what i did was just to convert it to base64 and fortunately, firebase storage accepts that form and i was able to make it work. I unfortunately couldn't to the method you suggested because i can't use express as of the moment (project restriction for easy deployment with vercel). –  Apr 11 '22 at 10:45