我正在向NodeJS服务器上传多个PDF
Ajax并保存MongoDB Book
文档的路径。
问题是当我第一次上传多个文件时,只有一个书籍路径被保存到MongoDB文档中,其他文件被正确上载,我可以在uploads
目录中查看,但没有得到保存到文档中。
我知道,这个问题与NodeJS中的异步进程有关。但我不知道如何解决这个问题。
以下是上传文件和保存MongoDB文档路径的代码。
var express = require('express')
var formidable = require('formidable')
var Book = require('../models/book')
var router = express.Router()
var path = require('path')
var uploadDir = path.join(__dirname, '/../uploads/')
var uploadDir2 = path.join(__dirname, '/..')
var imageDir = path.join(__dirname, '/../uploads/images/')
var exec = require('child_process').exec
router.post('/api/upload', function (req, res, next) {
var email = req.user.email
var form = new formidable.IncomingForm()
form.multiples = true
form.keepExtensions = true
form.uploadDir = uploadDir
form.parse(req, (err, fields, files) => {
if (err) return res.status(500).json({ error: err })
if (Array.isArray(files.userBooks)) {
files.userBooks.forEach(function (item, index) {
// bookPath.push(item.path.split('LibreRead')[1])
item = item.path.split('LibreRead')[1]
saveBooks(item)
getCover(item)
})
} else {
var item = files.userBooks.path.split('LibreRead')[1]
saveBooks(item)
getCover(item)
}
function saveBooks (bookPath) {
Book.find({email: req.user.email}, function (err, content) {
if (err) console.error(err)
var coverPath = '/uploads/images/' + bookPath.split('/uploads/').pop() + '-001-000.png'
var list = [{bookPath: bookPath, coverPath: coverPath}]
if (!content.length) {
var b = new Book({email: email, list: [list]})
return b.save(function (err, content) {
if (err) return console.log(err)
console.log(content)
})
} else {
content[0].list.push(list)
return content[0].save(function (err, content) {
if (err) return console.error(err)
console.log(content)
})
}
})
}
function getCover (bookPath) {
var cmd = 'pdfimages -p -png -f 1 -l 2 ' + uploadDir2 + bookPath + ' ' + imageDir + bookPath.split('/uploads/').pop()
return exec(cmd, function (err, stdout, stderr) {
if (err) return console.error(err)
console.log(stdout)
})
}
res.redirect('/')
})
form.on('fileBegin', function (name, file) {
const [fileName, fileExt] = file.name.split('.')
file.path = path.join(uploadDir, `${fileName}_${new Date().getTime()}.${fileExt}`)
})
})
module.exports = router
我认为forEach
循环是同步/阻塞,但仍然只保存了一个文件路径,其他文件路径不存在于MongoDB中
任何帮助对我都有用。谢谢!
答案 0 :(得分:0)
我认为是时间问题,因为您在响应重定向之前没有等待所有保存过程完成。
您可以使用Promise解决此问题(如果您的nodejs版本支持es6,或者npm安装bluebird)
router.post('/api/upload', function (req, res, next) {
var email = req.user.email
var form = new formidable.IncomingForm()
form.multiples = true
form.keepExtensions = true
form.uploadDir = uploadDir
form.parse(req, (err, fields, files) => {
if (err) return res.status(500).json({ error: err })
var promise;
if (Array.isArray(files.userBooks)) {
promise = Promise.all(files.userBooks.map(function (item, index) {
// bookPath.push(item.path.split('LibreRead')[1])
item = item.path.split('LibreRead')[1]
return saveAndReturnCover(item)
})).then(function(covers) {
// do something with the results if you want to
})
} else {
var item = files.userBooks.path.split('LibreRead')[1]
promise = saveAndReturnCover(item)
}
promise.then(function () {
res.redirect('/')
})
function saveAndReturnCover(item) {
return saveBooks(item).then(function () {
return getCover(item)
})
}
function saveBooks(bookPath) {
return new Promise(function (resolve, reject) {
Book.find({ email: req.user.email }, function (err, content) {
if (err) {
console.error(err)
return reject(err)
}
var coverPath = '/uploads/images/' + bookPath.split('/uploads/').pop() + '-001-000.png'
var list = [{ bookPath: bookPath, coverPath: coverPath }]
if (!content.length) {
var b = new Book({ email: email, list: [list] })
return b.save(function (err, content) { // no idea what .save will return
if (err) {
console.log(err)
return reject(err)
}
console.log(content)
resolve(content)
})
} else {
content[0].list.push(list)
return content[0].save(function (err, content) { // no idea what .save will return
if (err) {
console.error(err)
return reject(err)
}
console.log(content)
resolve(content)
})
}
})
})
}
function getCover(bookPath) {
return new Promise(function (resolve, reject) {
var cmd = 'pdfimages -p -png -f 1 -l 2 ' + uploadDir2 + bookPath + ' ' + imageDir + bookPath.split('/uploads/').pop()
return exec(cmd, function (err, stdout, stderr) {
if (err) {
console.error(err)
reject(err)
}
console.log(stdout)
resolve(stdout)
})
})
}
})
form.on('fileBegin', function (name, file) {
const [fileName, fileExt] = file.name.split('.')
file.path = path.join(uploadDir, `${fileName}_${new Date().getTime()}.${fileExt}`)
})
})