title: How to create a folder in Firebase Storage using Admin API
body: <blockquote>
    <p>Aim: to upload a file into a folder within Firebase Storage</p>
  </blockquote>
  
  <p><strong>E.g.</strong></p>
  
  <pre><code>default_bucket/folder1/file1
  default_bucket/folder1/file2
  default_bucket/folder2/file3
  </code></pre>
  
  <p>Using Firebase <strong>client-side</strong> I am able to upload a file to a folder within Firebase Storage like this:</p>
  
  <pre><code>    const storageRef = firebase.storage().ref();
      const fileRef = storageRef.child(`${folder}/${filename}`);
      const metadata = {
        contentType: file.type,
        customMetadata: { }
      };
      return fileRef.put(file, metadata);
  </code></pre>
  
  <p>If the folder does not exist, it get's created.</p>
  
  <blockquote>
    <p>However I have not managed to do the same server-side using the Admin SDK.</p>
  </blockquote>
  
  <p>The code below, uploads the file into the default bucket.</p>
  
  <p>But, I want to upload the file into a named folder within the default bucket.</p>
  
  <p>The client side makes a POST request to the GCF, sending the file and a folder name.</p>
  
  <p>Busboy is used to extra the folder name and file and pass them to the upload function; which uploads the file, then returns a donwnload link for it.</p>
  
  <p><strong>index.js</strong></p>
  
  <pre><code>const task = require('./tasks/upload-file-to-storage');
  
  app.post('/upload', (req, res, next) =&gt; {
    try {
      let uploadedFilename;
      let folder;
  
      if (req.method === 'OPTIONS') {
        optionsHelper.doOptions(res);
      } else if (req.method === 'POST') {
        res.set('Access-Control-Allow-Origin', '*');
  
        const busboy = new Busboy({ headers: req.headers });
        const uploads = [];
  
        busboy.on('file', (fieldname, file, filename, encoding, mimetype) =&gt; {
          uploadedFilename = `${folder}^${filename}`;
  
          const filepath = path.join(os.tmpdir(), uploadedFilename);
          uploads.push({ file: filepath, filename: filename, folder: folder });
          file.pipe(fs.createWriteStream(filepath));
        });
  
        busboy.on('field', (fieldname, val) =&gt; {
          if (fieldname === 'folder') {
            folder = val;
          } 
        });
  
        busboy.on('finish', () =&gt; {
          if (uploads.length === 0) {
            res.end('no files found');
          }
          for (let i = 0; i &lt; uploads.length; i++) {
            const upload = uploads[i];
            const file = upload.file;
  
            task.uploadFile(helpers.fbAdmin, upload.folder, upload.file, uploadedFilename).then(downloadLink =&gt; {
              res.write(`${downloadLink}\n`);
              fs.unlinkSync(file);
              res.end();
            });
          }
        });
        busboy.end(req.rawBody);
      } else {
        // Client error - only support POST
        res.status(405).end();
      }
    } catch (e) {
      console.error(e);
      res.sendStatus(500);
    }
  });
  
  const api = functions.https.onRequest(app);
  
  module.exports = {
    api
  ;
  </code></pre>
  
  <p><strong>upload-file-to-storage.js</strong></p>
  
  <pre><code>exports.uploadFile = (fbAdmin, folder, filepath, filename) =&gt; {
    // get the bucket to upload to
    const bucket = fbAdmin.storage().bucket(); //`venture-spec-sheet.appspot.com/${folder}`
  
  const uuid = uuid();
    // Uploads a local file to the bucket
    return bucket
      .upload(filepath, {
        gzip: true,
        metadata: {
          //destination: `/${folder}/${filename}`,
          cacheControl: 'public, max-age=31536000',
          firebaseStorageDownloadTokens: uuid
        }
      })
      .then(() =&gt; {
        const d = new Date();
        const expires = d.setFullYear(d.getFullYear() + 50);
  
        // get file from the bucket
        const myFile = fbAdmin
          .storage()
          .bucket()
          .file(filename);
  
        // generate a download link and return it
        return myFile.getSignedUrl({ action: 'read', expires: expires }).then(urls =&gt; {
          const signedUrl = urls[0];
          return signedUrl;
        });
      });
  };
  
  </code></pre>
  
  <blockquote>
    <p>I've tried a few things</p>
  </blockquote>
  
  <p>Setting the bucket name to default and a folder. This resulted in a server error.</p>
  
  <pre><code>const bucket = fbAdmin.storage().bucket(`${defaultName}/${folder}`); 
  </code></pre>
  
  <p>Setting the bucket name to the folder. This resulted in a server error.</p>
  
  <pre><code>const bucket = fbAdmin.storage().bucket(folder); 
  </code></pre>
  
  <p>And, I've also tried using the destination property of <em>uploadOptions</em>.
  But this still puts the file in the default bucket.</p>
  
  <pre><code>    .upload(filepath, {
        gzip: true,
        metadata: {
          destination: `${folder}/${filename}`, // and /${folder}/${filename}
        }
      })
  </code></pre>
  
  <blockquote>
    <p>Is it possible to upload to a folder using the Admin SDK?</p>
  </blockquote>
  
  <p>E.g. I want to upload a file so that is is placed in a named "folder".</p>
  
  <p>I.e. so I can reference the file at the path: bucket/folder/file.jpg</p>
  
  <p>In the example below, each "folder" is named with a firebase key.</p>
  
  <p><a href="https://i.stack.imgur.com/aSgem.png" rel="noreferrer"><img src="https://i.stack.imgur.com/aSgem.png" alt="enter image description here"></a></p>