Reputation: 619
I want to add two collections with one action. First one is file using multer and gridfs-stream and second is just literal with properties based on file. That what I achieved: 1)literal based on file and 2)file uploaded. In 1)(literal) this fileID property is just the same as _id of 2)(file) and src in 1) is just filename from 2) concatenated with some path. And here I have to problems. First is that this literal should have more properties, but I have problem with adding them. Here's the model(I think that there's isn't any problem, but it contain all props needed):
const mongoose = require('mongoose');
const Schema = mongoose.Schema;
// Create Schema
const FileSchema = new Schema({
fileID: {
type: Schema.Types.ObjectId
},
src: {
type: String,
},
altText: {
type: String,
},
caption: {
type: String,
},
});
module.exports = File = mongoose.model('file', FileSchema);
The most important GET/POST routes(and also DELETE routes for second problem):
router.get('/', (req, res) => {
File.find()
.sort({ date: -1 })
.then(files => res.json(files))
});
// @route POST /upload
// @desc Uploads file to DB
router.post('/', upload.single('file'), auth, (req, res) => {
const newFile = new File({
fileID: req.file.id,
src: 'api/files/image/' + req.file.filename,
altText: 'No image',
caption: req.body.caption
})
newFile.save()
});
// @route GET /files
// @desc Display all files in JSON
router.get('/', (req, res) => {
File.find()
.sort({ date: -1 })
.then(files => res.json(files))
});
// @route GET /files/:filename
// @desc Display single file object
router.get('/:filename', (req, res) => {
gfs.files.findOne({ filename: req.params.filename }, (err, file) => {
// Check if file
if (!file || file.length === 0) {
return res.status(404).json({
err: 'No file exists'
});
}
// File exists
return res.json(file);
});
});
// @route DELETE /files/:id
// @desc Delete file
router.delete('/:id', auth, (req, res) => {
gfs.remove({ _id: req.params.id, root: 'files' }, (err, gridStore) => {
if (err) {
return res.status(404).json({ err: err });
}
});
File.findById(req.body.fileID)
.then(file => file.remove().then(() => res.json({ success: true })))
.catch(err => res.status(404).json({ success: false }));
});
and my React component most important fragments:
const SliderModal = ({ isAuthenticated, addFile }) => {
const [modal, setModal] = useState(false);
const [file, setFile] = useState([]);
const [slideData, setSlideData] = useState({
fileID: '',
src: '',
altText: '',
caption: '',
})
const toggle = () => {
setModal(!modal);
};
const onChange = e => {
setFile(e.target.files[0]);
setSlideData({
...slideData,
[e.target.name]: e.target.value
});
};
const onSubmit = e => {
e.preventDefault();
const newFile = new FormData();
newFile.append('file', file);
// const { src, altText, caption, fileID } = slideData;
// const newSlide = {
// fileID,
// src,
// altText,
// caption
// }
// Add file via addItem action
addFile(newFile);
// addFile(newSlide);
// Close modal
toggle();
}
and next part(with use of reactstrap):
<Form onSubmit={onSubmit}>
<FormGroup>
{/* <Label for="caption">Caption</Label>
<Input
type="text"
name="caption"
id="caption"
placeholder="Caption"
className="mb-3"
onChange={onChange}
/> */}
<Label for="file">File</Label>
<Input
type="file"
name="name"
id="file"
placeholder="Add file"
onChange={onChange}
/>
<Button
color="dark"
style={{ marginTop: '2rem' }}
block>
Add File
</Button>
</FormGroup>
</Form>
in which, when I uncomment I have the text input in my modal in which, when I wrote anything I'm getting error:Error while inputting text The second problem is connected with deleting files. At this moment I'm able to delete only one of items(literal or file) from database. Here's DELETE route again: // @route DELETE /files/:id // @desc Delete file router.delete('/:id', auth, (req, res) => { gfs.remove({ _id: req.params.id, root: 'files' }, (err, gridStore) => { if (err) { return res.status(404).json({ err: err }); } }); File.findById(req.body.fileID) .then(file => file.remove().then(() => res.json({ success: true }))) .catch(err => res.status(404).json({ success: false })); });
Okay, I see that File.findById isn't good function, but the problem is that I want to delete them simultaneously. That's why in this literal I concluded that fileID property, but I'm really confused about it and can't find a solution. My idea was to search by this fileID property both and then delete them. Here's react function to delete only file(don't look at that is authenticated, that's just that I can delete file only when I'm logged in my app):
{files.map(({ fileID}) => (
< CSSTransition key={fileID} timeout={500} classNames="fade" >
<ListGroupItem>
{isAuthenticated ?
<Button
className="remove-btn"
color="danger"
size="sm"
onClick={onDeleteClick.bind(this, fileID)}
>×
</Button> : null}
</ListGroupItem>
</CSSTransition>
))}
Upvotes: 0
Views: 282
Reputation: 619
Ok, I just want to delete two objects with one click.
router.delete('/:id', auth, (req, res) => {
gfs.remove({ _id: req.params.id, root: 'files' }, (err, gridStore) => {
if (err) {
return res.status(404).json({ err: err });
}
})
File.findOne(req.body.fileID)
.then(file => file.remove().then(() => res.json({ success: true })))
.catch(err => res.status(404).json({ success: false }));
});
Unfortanelly this one delete two objects, but not compatible. This 'File' object have fileID property, which are the same as id in gfs. My will is to delete two objects with the id == fileID.
Upvotes: 0