From 8cb549764fd1745c78efa3f1e446228d4ec5e5b1 Mon Sep 17 00:00:00 2001 From: 2knal Date: Mon, 24 Feb 2020 00:08:53 +0530 Subject: [PATCH] Upload directory of images We can now upload directory containing the images we want to upload. They'll be added to the server's `uploads/` directory. Closes #272 --- .../src/components/labeller/index.js | 4 +- .../src/components/project/images.js | 111 ++++++-- labellab-server/app.js | 4 +- .../controller/image/imageControls.js | 246 ++++++++++-------- labellab-server/models/image.js | 4 + 5 files changed, 236 insertions(+), 133 deletions(-) diff --git a/labellab-client/src/components/labeller/index.js b/labellab-client/src/components/labeller/index.js index 553a79218..fdfad5ffb 100644 --- a/labellab-client/src/components/labeller/index.js +++ b/labellab-client/src/components/labeller/index.js @@ -116,9 +116,11 @@ class LabelingLoader extends Component { labels={lab} labelData={(img && img.labelData) || {}} imageUrl={ + 'http://' + process.env.REACT_APP_HOST + + ':' + process.env.REACT_APP_SERVER_PORT + - `/static/uploads/${image.imageUrl}?${Date.now()}` + (image.directory.length > 0 ? `/static/uploads/${image.directory}/${image.imageUrl}?${Date.now()}` :`/static/uploads/${image.imageUrl}?${Date.now()}`) } demo={false} {...props} diff --git a/labellab-client/src/components/project/images.js b/labellab-client/src/components/project/images.js index 9bb047ed0..799a1b663 100644 --- a/labellab-client/src/components/project/images.js +++ b/labellab-client/src/components/project/images.js @@ -16,7 +16,11 @@ class ImagesIndex extends Component { imageNames: [], projectId: '', showform: false, - format: '' + format: '', + directoryName: '', + directoryImageNames: [], + directoryImageFormats: [], + directoryImages: [] } } handleImageChange = e => { @@ -38,21 +42,63 @@ class ImagesIndex extends Component { showform: !this.state.showform }) } + handleAddDirectory = e => { + e.preventDefault() + const directoryInput = document.getElementById("directory-embedpollfileinput") + + Array.from(directoryInput.files).forEach(file => { + const reader = new FileReader() + // Validating file type to be image + const directoryName = file.webkitRelativePath.split('/')[0] + if (file.type.startsWith('image')) { + reader.onloadend = () => { + this.setState({ + directoryName, + directoryImages: [...this.state.directoryImages, reader.result], + directoryImageNames: [...this.state.directoryImageNames, file.name], + directoryImageFormats: [...this.state.directoryImageFormats, file.type] + }) + } + reader.readAsDataURL(file) + } + }); + this.setState({ + showform: !this.state.showform + }) + } handleSubmit = e => { e.preventDefault() const { project, fetchProject, submitImage } = this.props - const { imageNames, images, format } = this.state - let data = { - imageNames: imageNames, - images: images, - projectId: project.projectId, - format: format + const { imageName, image, format } = this.state + const { directoryName, directoryImageNames, directoryImages, directoryImageFormats } = this.state + let data = {} + if (this.state.imageName) { + data = { + imageName, + image, + projectId: project.projectId, + format + } + } else if (this.state.directoryName) { + data = { + directoryName, + directoryImages, + directoryImageNames, + directoryImageFormats, + projectId: project.projectId + } } submitImage(data, () => { this.setState({ showform: false, - images: [], - imageNames: [] + image: '', + file: '', + format: '', + imageName: '', + directoryImageNames: [], + directoryImages: [], + directoryImageFormats: [], + directoryName: '' }) fetchProject(project.projectId) }) @@ -100,25 +146,37 @@ class ImagesIndex extends Component { Add Image - +
+ + +
{showform ? (
- {this.state.images.length == 1 && ( - - - - - )} - + + + + @@ -134,6 +192,7 @@ class ImagesIndex extends Component { ID + Directory Image Link @@ -209,10 +268,8 @@ const columnStyles = [ const Row = ({ image, projectId, style, onDelete, imageId }) => ( - - {imageId + 1} - {image.labelled ? : null} - + {imageId + 1} + { image.directory ? image.directory: null } ( process.env.REACT_APP_HOST + ':' + process.env.REACT_APP_SERVER_PORT + - `/static/uploads/${image.imageUrl}?${Date.now()}` + (image.directory.length > 0 ? `/static/uploads/${image.directory}/${image.imageUrl}?${Date.now()}` :`/static/uploads/${image.imageUrl}?${Date.now()}`) } > {image.imageName} diff --git a/labellab-server/app.js b/labellab-server/app.js index e91b2d44e..f97088c05 100644 --- a/labellab-server/app.js +++ b/labellab-server/app.js @@ -26,8 +26,8 @@ if (process.env.GITHUB_CLIENT_ID) { app.use(logger('dev')) app.use(cors()) -app.use(express.json({ limit: '10mb' })) -app.use(express.urlencoded({ extended: false, limit: '10mb' })) +app.use(express.json({ limit: '50mb' })) +app.use(express.urlencoded({ extended: true, limit: '50mb' })) app.use(cookieParser()) app.set('/views', path.join(__dirname, 'views')) app.engine('html', require('ejs').renderFile) diff --git a/labellab-server/controller/image/imageControls.js b/labellab-server/controller/image/imageControls.js index cf0939c14..fb76954d9 100644 --- a/labellab-server/controller/image/imageControls.js +++ b/labellab-server/controller/image/imageControls.js @@ -8,83 +8,123 @@ const Label = require('../../models/label') const ObjectID = require('mongodb').ObjectID exports.postImage = function(req, res) { - if ( - req && - req.body && - req.params && - req.params.projectId && - req.body.images && - req.body.projectId && - req.body.imageNames && - req.body.format - ) { - const { images, imageNames, format, projectId } = req.body - var firstImage = images[0] - for (var i = 0; i < images.length; i++) { - var image = images[i] - var imageName = imageNames[i] - let data = { - id: req.user.id, - image: image, - imageName: imageName, - format: format, - project: req.params.projectId - } - let baseImg = data.image.split(',')[1] - let binaryData = new Buffer(baseImg, 'base64') - var dimensions = sizeOfImage(binaryData) - let ext = data.format.split('/')[1] - let updateData = { imageUrl: `${data.id}${Date.now()}.${ext}` } - fs.writeFile( - `./public/uploads/${updateData.imageUrl}`, - binaryData, - async err => { - if (err) { - return res.status(400).send({ success: false, msg: err }) - } else { - const newImage = new Image({ - project: projectId, - imageUrl: updateData.imageUrl, - imageName: data.imageName, - width: dimensions.width, - height: dimensions.height - }) - newImage.save(function(err, image) { - if (err) { - return res - .status(400) - .send({ success: false, msg: 'Unable to Add Image' }) - } else if (image._id) { - Project.updateOne( - { _id: req.body.projectId }, - { $addToSet: { image: image._id } } - ).exec(function(err, project) { - if (err) { - return res.status(400).send({ - success: false, - msg: 'Cannot Append image', - error: err - }) - } - }) - } else { - return res.status(400).send({ - success: false, - msg: 'Image ID Not Found', - body: image - }) - } - }) - } - } - ) - } - return res.json({ - success: true, - msg: 'Images Successfully Posted', - body: firstImage - }) - } else res.status(400).send({ success: false, msg: 'Invalid Data' }) + + const dbImageSaveUtil = async (data, directoryName, updateData, dimensions, projectId, err) => { + if (err) { + return res.status(400).send({ success: false, msg: err }) + } else { + let newImage = { + project: projectId, + imageUrl: updateData.imageUrl, + imageName: data.imageName, + width: dimensions.width, + height: dimensions.height, + directory: directoryName ? directoryName: '' + } + newImage = new Image(newImage) + newImage.save(function(err, image) { + if (err) { + return res + .status(400) + .send({ success: false, msg: 'Unable to Add Image' }) + } else if (image._id) { + Project.updateOne( + { _id: req.body.projectId }, + { $addToSet: { image: image._id } } + ).exec(function(err, project) { + if (err) { + return res.status(400).send({ + success: false, + msg: 'Cannot Append image', + error: err + }) + } + }) + } else { + return res.status(400).send({ + success: false, + msg: 'Image ID Not Found', + body: image + }) + } + }) + } + } + + if ( + req && + req.body && + req.params && + req.params.projectId && + req.body.projectId && + ((req.body.image && + req.body.imageName && + req.body.format) || + (req.body.directoryName && + req.body.directoryImages && + req.body.directoryImageNames && + req.body.directoryImageFormats)) + ) { + const { image, imageName, format, projectId } = req.body + const { directoryName, directoryImages, directoryImageNames, directoryImageFormats } = req.body + if (imageName) { + const data = { + id: req.user.id, + image: image, + imageName: imageName, + format: format, + project: req.params.projectId + } + let baseImg = data.image.split(',')[1] + let binaryData = new Buffer(baseImg, 'base64') + var dimensions = sizeOfImage(binaryData) + let ext = data.format.split('/')[1] + let updateData = { imageUrl: `${data.id}${Date.now()}.${ext}` } + fs.writeFile( + `./public/uploads/${updateData.imageUrl}`, + binaryData, + async err => await dbImageSaveUtil(data, directoryName, updateData, dimensions, projectId, err) + ) + res.status(201).send({ + success: true, + msg: 'Posted successfully!' + }) + } else { + const STORE_URL = `./public/uploads/${directoryName}` + for (let i=0; i await dbImageSaveUtil(data, directoryName, updateData, dimensions, projectId, err) + ) + } catch (err) { + break + } + } + res.status(201).send({ + success: true, + msg: 'Posted successfully!' + }) + } + + } else res.status(400).send({ success: false, msg: 'Invalid Data' }) } exports.fetchImage = function(req, res) { @@ -118,32 +158,32 @@ exports.fetchImage = function(req, res) { } exports.fetchImageId = function(req, res) { - if (req && req.params && req.params.imageId) { - Image.findOne({ - _id: req.params.imageId - }) - .select('height width labelData imageName imageUrl createdAt') - .exec(function(err, image) { - if (err) { - return res.status(400).send({ - success: false, - msg: 'Unable to connect to database. Please try again.', - error: err - }) - } - if (!image) { - return res - .status(400) - .send({ success: false, msg: 'Image not found' }) - } else { - return res.json({ - success: true, - msg: 'Image Data Found', - body: image - }) - } - }) - } else res.status(400).send({ success: false, msg: 'Invalid Data' }) + if (req && req.params && req.params.imageId) { + Image.findOne({ + _id: req.params.imageId + }) + .select('height width labelData imageName imageUrl createdAt directory') + .exec(function(err, image) { + if (err) { + return res.status(400).send({ + success: false, + msg: 'Unable to connect to database. Please try again.', + error: err + }) + } + if (!image) { + return res + .status(400) + .send({ success: false, msg: 'Image not found' }) + } else { + return res.json({ + success: true, + msg: 'Image Data Found', + body: image + }) + } + }) + } else res.status(400).send({ success: false, msg: 'Invalid Data' }) } exports.updateLabels = function(req, res) { diff --git a/labellab-server/models/image.js b/labellab-server/models/image.js index 63bd933a3..d1055e32f 100644 --- a/labellab-server/models/image.js +++ b/labellab-server/models/image.js @@ -29,6 +29,10 @@ const ImageSchema = new mongoose.Schema({ createdAt: { type: Date, default: Date.now + }, + directory: { + type: String, + default: '' } })