我想将照片上传到Firebase存储。
在React组件的状态下,我有带有照片的数组。照片是用户通过文件输入浏览的文件。如果文件需要上传到存储空间,则照片的属性为.needUpload
至true
。
这是上传功能:
uploadPhotos = () => {
let photosToSave = []
if (this.state.photos.length) {
photosToSave = this.state.photos
.filter(photo => photo.needUpload && true)
.map(photo => {
const extensionPattern = /(?:\.([^.]+))?$/
const fileName = photo.value.name
const fileExtension = extensionPattern.exec(fileName)[1]
const newFileName = new Date().getTime()
const fileLocation = storageRef.child('estateObjects/' + newFileName + '.' + fileExtension)
return new Promise(resolve => {
fileLocation.put(photo.value).on(
firebase.storage.TaskEvent.STATE_CHANGED,
snapshot => {
//let progress = (snapshot.bytesTransferred / snapshot.totalBytes) * 100
},
null,
() => {
fileLocation.getDownloadURL().then(url => {
resolve({ url: url, file: newFileName + '.' + fileExtension })
})
}
)
})
})
return Promise.all(photosToSave).then(response => {
return response
})
} else return Promise.all(photosToSave).then(response => [])
}
主要问题是,当上传开始时,它(耐心地)等待,我想先上传2-3个文件,然后在“解析”数组中,我得到重复的数组元素。所以有些事情做错了,但是我不明白是什么...
也许是新文件名的问题??当文件重命名为新的Date.getTime()会为几个文件同时返回时,会导致它们同时上传吗?
答案 0 :(得分:1)
map循环运行非常快,因此两次迭代之间的时间不会改变
因此,我建议您使用index
来确保文件名唯一性
uploadPhotos = () => {
let photosToSave = [];
if (this.state.photos.length) {
photosToSave = this.state.photos.filter(photo => photo.needUpload && true).map((photo, index) => {
const extensionPattern = /(?:\.([^.]+))?$/;
const fileName = photo.value.name;
const fileExtension = extensionPattern.exec(fileName)[1];
const newFileName = `${new Date().getTime()}_${index}`;
const fileLocation = storageRef.child('estateObjects/' + newFileName + '.' + fileExtension);
return new Promise(resolve => {
fileLocation.put(photo.value).on(firebase.storage.TaskEvent.STATE_CHANGED, snapshot => {//let progress = (snapshot.bytesTransferred / snapshot.totalBytes) * 100
}, null, () => {
fileLocation.getDownloadURL().then(url => {
resolve({
url: url,
file: newFileName + '.' + fileExtension
});
});
});
});
});
return Promise.all(photosToSave).then(response => {
return response;
});
} else return Promise.all(photosToSave).then(response => []);
}
答案 1 :(得分:0)
我认为在newFileName上添加同步方法的替代方法可以起作用。
var time = ''; //Global variable
function getTime() {
if(new Date().getTime() === time){return getTime()}
else time = new Date().getTime();
return time;
}
答案 2 :(得分:-1)
我在控制台上运行了此命令,结果是猜测可能是谁出了问题。
[...Array(7).keys()].map(v=> console.log(new Date().getTime()))
VM676:2 1572510011727
VM676:5 1572510011728
有一个零依赖库uuid,您可以用来确保使用唯一的文件名here
npm install uuid
const uuidv1 = require('uuid/v1');
uuidv1(); // ⇨ '2c5ea4c0-4067-11e9-8bad-9b1deb4d3b7d'