Node.js中按顺序从Firebase Storage获取文件URL并存入MongoDB
问题:Firebase Storage遍历子文件夹并同步URL到MongoDB失败
业务场景
Firebase Storage中有一个主文件夹,其下包含多个子文件夹,每个子文件夹内有两个文件。需要在Node.js中遍历每个子文件夹,获取其中每个文件的下载URL,并将每个子文件夹的两个URL作为一个文档存储到MongoDB中。
原实现代码
const info={} const Ref = ref(storage, 'main folder in firebase') listAll(Ref).then((res) => { res.prefixes.forEach((folderRef) => { console.log("prefix" + folderRef); listAll(folderRef).then((res) => { getDownloadURL(res.items[0]) .then((url) => { console.log(url); if (url.search("html") === -1) { info.image = `${url}`; } else { info.doc = `${url}`; } return info; }) .then((info) => { getDownloadURL(res.items[1]) .then((url) => { console.log(url); if (url.search("html") === -1) { info.image = `${url}`; } else { info.doc = `${url}`; } return info; }) .then((info) => { console.log(info); }); }); }); }); });
Firebase Storage结构
main folder --> template1 (CV1.png, test.html) --> template2 (CV2.png, test.html) --> template3 (CV3.png, test.html)
错误输出
执行后生成的对象并未包含同一子文件夹的两个文件URL,输出示例:
prefixgs://my-first-project.appspot.com/data/template1 prefixgs://my-first-project.appspot.com/data/template2 prefixgs://my-first-project.appspot.com/data/template3 https://firebasestorage.googleapis.com/v0/b/my-first-project-9f749.appspot.com/o/data%2Ftemplate1%2Fcv1.PNG https://firebasestorage.googleapis.com/v0/b/my-first-project-9f749.appspot.com/o/data%2Ftemplate2%2Fcv2.PNG? https://firebasestorage.googleapis.com/v0/b/my-first-project-9f749.appspot.com/o/data%2Ftemplate3%2Fcv3.PNG? https://firebasestorage.googleapis.com/v0/b/my-first-project-9f749.appspot.com/o/data%2Ftemplate1%2Ftest.html? { image: 'https://firebasestorage.googleapis.com/v0/b/my-first-project-9f749.appspot.com/o/data%2Ftemplate3%2Fcv3.PNG?', doc: 'https://firebasestorage.googleapis.com/v0/b/my-first-project-9f749.appspot.com/o/data%2Ftemplate1%2Ftest.html?' } https://firebasestorage.googleapis.com/v0/b/my-first-project-9f749.appspot.com/o/data%2Ftemplate2%2Ftest.html? { image: 'https://firebasestorage.googleapis.com/v0/b/my-first-project-9f749.appspot.com/o/data%2Ftemplate3%2Fcv3.PNG?', doc: 'https://firebasestorage.googleapis.com/v0/b/my-first-project-9f749.appspot.com/o/data%2Ftemplate2%2Ftest.html?' } https://firebasestorage.googleapis.com/v0/b/my-first-project-9f749.appspot.com/o/data%2Ftemplate3%2Ftest.html? { image: 'https://firebasestorage.googleapis.com/v0/b/my-first-project-9f749.appspot.com/o/data%2Ftemplate3%2Fcv3.PNG?', doc: 'https://firebasestorage.googleapis.com/v0/b/my-first-project-9f749.appspot.com/o/data%2Ftemplate3%2Ftest.html?' }
解决方案
问题根源在于listAll()和getDownloadURL()都是异步函数,原代码未正确等待异步操作完成,导致不同子文件夹的URL互相覆盖。通过Promise.all()批量等待异步操作完成,确保每个子文件夹的两个URL被正确关联后再存入MongoDB。
修正后的代码:
listAll('main folder Reference').then((res) => { const folders = res.prefixes.map(folderRef => listAll(folderRef)); Promise.all(folders).then((folderResults) => { folderResults.forEach((folderData) => { const fileUrlPromises = folderData.items.map(itemRef => getDownloadURL(itemRef)); Promise.all(fileUrlPromises).then((urls) => { const info = {}; urls.forEach((url) => { if (url.search("html") === -1) { info.image = url; } else { info.doc = url; } }); console.log(info); const newList = new templates({ ...info, }); try { newList.save(); console.log(info); } catch (error) { console.log(error); } }); }); }); });
内容的提问来源于stack exchange,提问作者Hasnain Ali
相关产品推荐
相关产品推荐

