* Refactored all instances of "failedIds" and "albumIds" to "failedids" and "albumids" respectively. Abandoning camel case for these ones.

* Refactored the way it looks into which albums the files are supposed to be added into.
For /api/upload/finishchunks, you can add "albumid" to each object in files[] to specify which album you want the finsihed chunks to be added into. Each object may have different album IDs.
For /api/upload, which is regular uploads, unfortunately you can only choose one album at a time (by adding "albumid" to the request headers, like usual). It uses the same function as the one used for finishchunks to add the files into album, so it shouldn't be hard to extend this ability to regular uploads, someday in the future.

* Fixed a bug in /api/upload/finishchunks. Previously you couldn't ever get it to work.

* Updated error message when successful uploads could not be added to album.

* "albumid" will no longer be added to request headers if they are chunked uploads. They'd have been ignored anyways.
This commit is contained in:
Bobby Wibowo 2018-04-05 19:54:24 +07:00
parent b1dbb931c1
commit 3ca692d8c7
No known key found for this signature in database
GPG Key ID: 51C3A1E1E22D26CF
7 changed files with 93 additions and 87 deletions

View File

@ -92,7 +92,7 @@ albumsController.delete = async (req, res, next) => {
}
let ids = []
let failedIds = []
let failedids = []
if (purge) {
const files = await db.table('files')
.where({
@ -101,9 +101,9 @@ albumsController.delete = async (req, res, next) => {
})
ids = files.map(file => file.id)
failedIds = await utils.bulkDeleteFilesByIds(ids, user)
failedids = await utils.bulkDeleteFilesByIds(ids, user)
if (failedIds.length === ids.length) {
if (failedids.length === ids.length) {
return res.json({
success: false,
description: 'Could not delete any of the files associated with the album.'
@ -120,7 +120,7 @@ albumsController.delete = async (req, res, next) => {
return res.json({
success: true,
failedIds
failedids
})
}
@ -248,7 +248,7 @@ albumsController.addFiles = async (req, res, next) => {
if (typeof albumid !== 'number') { albumid = parseInt(albumid) }
if (isNaN(albumid) || (albumid < 0)) { albumid = null }
const albumIds = []
const albumids = []
if (albumid !== null) {
const album = await db.table('albums')
@ -265,7 +265,7 @@ albumsController.addFiles = async (req, res, next) => {
})
}
albumIds.push(albumid)
albumids.push(albumid)
}
const files = await db.table('files')
@ -276,11 +276,11 @@ albumsController.addFiles = async (req, res, next) => {
}
})
const failedIds = ids.filter(id => !files.find(file => file.id === id))
const failedids = ids.filter(id => !files.find(file => file.id === id))
await Promise.all(files.map(file => {
if (file.albumid && !albumIds.includes(file.albumid)) {
albumIds.push(file.albumid)
if (file.albumid && !albumids.includes(file.albumid)) {
albumids.push(file.albumid)
}
return db.table('files')
@ -288,19 +288,19 @@ albumsController.addFiles = async (req, res, next) => {
.update('albumid', albumid)
.catch(error => {
console.error(error)
failedIds.push(file.id)
failedids.push(file.id)
})
}))
if (failedIds.length < ids.length) {
await Promise.all(albumIds.map(albumid => {
if (failedids.length < ids.length) {
await Promise.all(albumids.map(albumid => {
return db.table('albums')
.where('id', albumid)
.update('editedAt', Math.floor(Date.now() / 1000))
}))
return res.json({
success: true,
failedIds
failedids
})
}

View File

@ -147,18 +147,8 @@ uploadsController.upload = async (req, res, next) => {
req.headers.filelength = user.fileLength
}
const albumid = req.headers.albumid || req.params.albumid
if (albumid && user) {
const album = await db.table('albums').where({ id: albumid, userid: user.id }).first()
if (!album) {
return res.json({
success: false,
description: 'Album doesn\'t exist or it doesn\'t belong to the user.'
})
}
return uploadsController.actuallyUpload(req, res, user, albumid)
}
let albumid = parseInt(req.headers.albumid || req.params.albumid)
if (isNaN(albumid)) { albumid = null }
return uploadsController.actuallyUpload(req, res, user, albumid)
}
@ -180,17 +170,18 @@ uploadsController.actuallyUpload = async (req, res, user, albumid) => {
if (chunkedUploads && req.body.uuid) { return res.json({ success: true }) }
const infoMap = req.files.map(file => {
if (albumid) { file.albumid = albumid }
return {
path: path.join(__dirname, '..', config.uploads.folder, file.filename),
data: file
}
})
const result = await uploadsController.writeFilesToDb(req, res, user, albumid, infoMap)
const result = await uploadsController.writeFilesToDb(req, res, user, infoMap)
.catch(erred)
if (result) {
return uploadsController.processFilesForDisplay(req, res, result.files, result.existingFiles, albumid)
return uploadsController.processFilesForDisplay(req, res, result.files, result.existingFiles)
}
})
}
@ -222,18 +213,8 @@ uploadsController.finishChunks = async (req, res, next) => {
req.headers.filelength = user.fileLength
}
const albumid = req.headers.albumid || req.params.albumid
if (albumid && user) {
const album = await db.table('albums').where({ id: albumid, userid: user.id }).first()
if (!album) {
return res.json({
success: false,
description: 'Album doesn\'t exist or it doesn\'t belong to the user.'
})
}
return uploadsController.actuallyFinishChunks(req, res, user, albumid)
}
let albumid = parseInt(req.headers.albumid || req.params.albumid)
if (isNaN(albumid)) { albumid = null }
return uploadsController.actuallyFinishChunks(req, res, user, albumid)
}
@ -251,7 +232,7 @@ uploadsController.actuallyFinishChunks = async (req, res, user, albumid) => {
let iteration = 0
const infoMap = []
for (const file of files.length) {
for (const file of files) {
const { uuid, count } = file
if (!uuid || !count) { return erred(new Error('Missing UUID and/or chunks count.')) }
@ -282,23 +263,28 @@ uploadsController.actuallyFinishChunks = async (req, res, user, albumid) => {
if (!appended) { return }
const data = {
filename: name,
originalname: file.original || '',
mimetype: file.type || '',
size: file.size || 0
}
data.albumid = parseInt(file.albumid)
if (isNaN(data.albumid)) { data.albumid = albumid }
infoMap.push({
path: destination,
data: {
filename: name,
originalname: file.original || '',
mimetype: file.type || '',
size: file.size || 0
}
data
})
iteration++
if (iteration >= files.length) {
const result = await uploadsController.writeFilesToDb(req, res, user, albumid, infoMap)
const result = await uploadsController.writeFilesToDb(req, res, user, infoMap)
.catch(erred)
if (result) {
return uploadsController.processFilesForDisplay(req, res, result.files, result.existingFiles, albumid)
return uploadsController.processFilesForDisplay(req, res, result.files, result.existingFiles)
}
}
})
@ -329,7 +315,8 @@ uploadsController.appendToStream = async (destFileStream, chunksDirUuid, chunks)
})
}
uploadsController.writeFilesToDb = async (req, res, user, albumid, infoMap) => {
uploadsController.writeFilesToDb = async (req, res, user, infoMap) => {
const albumsAuthorized = {}
return new Promise((resolve, reject) => {
let iteration = 0
const files = []
@ -361,6 +348,16 @@ uploadsController.writeFilesToDb = async (req, res, user, albumid, infoMap) => {
.first()
if (!dbFile) {
if (info.data.albumid && albumsAuthorized[info.data.albumid] === undefined) {
const authorized = await db.table('albums')
.where({
id: info.data.albumid,
userid: user.id
})
.first()
albumsAuthorized[info.data.albumid] = Boolean(authorized)
}
files.push({
name: info.data.filename,
original: info.data.originalname,
@ -368,7 +365,7 @@ uploadsController.writeFilesToDb = async (req, res, user, albumid, infoMap) => {
size: info.data.size,
hash: fileHash,
ip: req.ip,
albumid,
albumid: albumsAuthorized[info.data.albumid] ? info.data.albumid : null,
userid: user !== undefined ? user.id : null,
timestamp: Math.floor(Date.now() / 1000)
})
@ -386,7 +383,7 @@ uploadsController.writeFilesToDb = async (req, res, user, albumid, infoMap) => {
})
}
uploadsController.processFilesForDisplay = async (req, res, files, existingFiles, albumid) => {
uploadsController.processFilesForDisplay = async (req, res, files, existingFiles) => {
const basedomain = config.domain
if (files.length === 0) {
return res.json({
@ -409,29 +406,36 @@ uploadsController.processFilesForDisplay = async (req, res, files, existingFiles
files.push(efile)
}
const albumids = []
for (const file of files) {
const ext = path.extname(file.name).toLowerCase()
if ((config.uploads.generateThumbnails.image && utils.imageExtensions.includes(ext)) || (config.uploads.generateThumbnails.video && utils.videoExtensions.includes(ext))) {
file.thumb = `${basedomain}/thumbs/${file.name.slice(0, -ext.length)}.png`
utils.generateThumbs(file)
}
if (file.albumid && !albumids.includes(file.albumid)) {
albumids.push(file.albumid)
}
}
let albumSuccess = true
if (albumid) {
albumSuccess = await db.table('albums')
.where('id', albumid)
.update('editedAt', files[files.length - 1].timestamp)
.then(() => true)
.catch(error => {
console.log(error)
return false
})
if (albumids.length) {
const editedAt = Math.floor(Date.now() / 1000)
await Promise.all(albumids.map(albumid => {
return db.table('albums')
.where('id', albumid)
.update('editedAt', editedAt)
.then(() => {})
.catch(error => {
console.log(error)
albumSuccess = false
})
}))
}
return res.json({
success: albumSuccess,
description: albumSuccess ? null : 'Successfully uploaded file(s) but unable to add to album.',
description: albumSuccess ? null : 'Warning: Some files may have failed to be added to album.',
files: files.map(file => {
return {
name: file.name,
@ -487,11 +491,11 @@ uploadsController.bulkDelete = async (req, res) => {
return res.json({ success: false, description: 'No files specified.' })
}
const failedIds = await utils.bulkDeleteFilesByIds(ids, user)
if (failedIds.length < ids.length) {
const failedids = await utils.bulkDeleteFilesByIds(ids, user)
if (failedids.length < ids.length) {
return res.json({
success: true,
failedIds
failedids
})
}

View File

@ -131,7 +131,7 @@ utilsController.bulkDeleteFilesByIds = async (ids, user) => {
}
})
const failedIds = ids.filter(id => !files.find(file => file.id === id))
const failedids = ids.filter(id => !files.find(file => file.id === id))
// First, we delete all the physical files
await Promise.all(files.map(file => {
@ -139,37 +139,37 @@ utilsController.bulkDeleteFilesByIds = async (ids, user) => {
// ENOENT is missing file, for whatever reason, then just delete from db anyways
if (error.code !== 'ENOENT') {
console.log(error)
failedIds.push(file.id)
failedids.push(file.id)
}
})
}))
// Second, we filter out failed IDs
const albumIds = []
const updateDbIds = files.filter(file => !failedIds.includes(file.id))
const albumids = []
const updateDbIds = files.filter(file => !failedids.includes(file.id))
await Promise.all(updateDbIds.map(file => {
return db.table('files')
.where('id', file.id)
.del()
.then(() => {
if (file.albumid && !albumIds.includes(file.albumid)) {
albumIds.push(file.albumid)
if (file.albumid && !albumids.includes(file.albumid)) {
albumids.push(file.albumid)
}
})
.catch(error => {
console.error(error)
failedIds.push(file.id)
failedids.push(file.id)
})
}))
// Third, we update albums, if necessary
await Promise.all(albumIds.map(albumid => {
await Promise.all(albumids.map(albumid => {
return db.table('albums')
.where('id', albumid)
.update('editedAt', Math.floor(Date.now() / 1000))
}))
return failedIds
return failedids
}
module.exports = utilsController

View File

@ -17,7 +17,7 @@
<script type="text/javascript" src="libs/sweetalert/sweetalert.min.js?v=vvtL7Y3cjD"></script>
<script type="text/javascript" src="libs/axios/axios.min.js?v=vvtL7Y3cjD"></script>
<script type="text/javascript" src="libs/clipboard.js/clipboard.min.js?v=vvtL7Y3cjD"></script>
<script type="text/javascript" src="js/dashboard.js?v=XW5nYuTStf"></script>
<script type="text/javascript" src="js/dashboard.js?v=D6LvZYepOF"></script>
<!-- Open Graph tags -->
<meta property="og:type" content="website" />

View File

@ -17,7 +17,7 @@
<script type="text/javascript" src="libs/dropzone/dropzone.min.js?v=vvtL7Y3cjD"></script>
<script type="text/javascript" src="libs/axios/axios.min.js?v=vvtL7Y3cjD"></script>
<script type="text/javascript" src="libs/clipboard.js/clipboard.min.js?v=vvtL7Y3cjD"></script>
<script type="text/javascript" src="js/home.js?v=XW5nYuTStf"></script>
<script type="text/javascript" src="js/home.js?v=D6LvZYepOF"></script>
<!-- Open Graph tags -->
<meta property="og:type" content="website" />

View File

@ -504,9 +504,9 @@ panel.deleteSelectedFiles = async album => {
}
let deleted = count
if (bulkdelete.data.failedIds && bulkdelete.data.failedIds.length) {
deleted -= bulkdelete.data.failedIds.length
panel.selectedFiles = panel.selectedFiles.filter(id => bulkdelete.data.failedIds.includes(id))
if (bulkdelete.data.failedids && bulkdelete.data.failedids.length) {
deleted -= bulkdelete.data.failedids.length
panel.selectedFiles = panel.selectedFiles.filter(id => bulkdelete.data.failedids.includes(id))
} else {
panel.selectedFiles = []
}
@ -523,10 +523,10 @@ panel.addSelectedFilesToAlbum = async album => {
return swal('An error occurred!', 'You have not selected any files.', 'error')
}
const failedIds = await panel.addToAlbum(panel.selectedFiles, album)
if (!(failedIds instanceof Array)) { return } // TODO: Make it so that I don't have to do this
if (failedIds.length) {
panel.selectedFiles = panel.selectedFiles.filter(id => failedIds.includes(id))
const failedids = await panel.addToAlbum(panel.selectedFiles, album)
if (!(failedids instanceof Array)) { return } // TODO: Make it so that I don't have to do this
if (failedids.length) {
panel.selectedFiles = panel.selectedFiles.filter(id => failedids.includes(id))
} else {
panel.selectedFiles = []
}
@ -616,8 +616,8 @@ panel.addToAlbum = async (ids, album) => {
}
let added = ids.length
if (add.data.failedIds && add.data.failedIds.length) {
added -= add.data.failedIds.length
if (add.data.failedids && add.data.failedids.length) {
added -= add.data.failedids.length
}
const suffix = `file${ids.length === 1 ? '' : 's'}`
@ -627,7 +627,7 @@ panel.addToAlbum = async (ids, album) => {
swal('Woohoo!', `Successfully ${albumid < 0 ? 'removed' : 'added'} ${added} ${suffix} ${albumid < 0 ? 'from' : 'to'} the album.`, 'success')
panel.getUploads(album)
return add.data.failedIds
return add.data.failedids
}
panel.getAlbums = () => {

View File

@ -85,7 +85,7 @@ upload.prepareUpload = () => {
const select = document.getElementById('albumSelect')
select.addEventListener('change', () => {
upload.album = select.value
upload.album = parseInt(select.value)
})
axios.get('api/albums', { headers: { token: upload.token } })
@ -170,7 +170,8 @@ upload.prepareDropzone = () => {
original: file.name,
size: file.size,
type: file.type,
count: file.upload.totalChunkCount
count: file.upload.totalChunkCount,
albumid: upload.album
}
]
},
@ -205,6 +206,7 @@ upload.prepareDropzone = () => {
// Add the selected albumid, if an album is selected, as a header
upload.dropzone.on('sending', (file, xhr, formData) => {
if (file.upload.chunked) { return }
if (upload.album) { xhr.setRequestHeader('albumid', upload.album) }
})