Pessoal, estou fazendo um projeto bem semelhante ao alurapic, mas com cadastro de pessoas. E durante o cadastro, a pessoa pode incluir uma foto dela.
Para isso, estou usando o ngFileUpload (https://github.com/danialfarid/ng-file-upload) e o Multer. Com isso, já consigo fazer o upload da imagem no diretório especificado (no caso, "uploads"), juntamente com os demais dados, que estão sendo gravados no MongoDB.
Porém, não estou conseguindo gravar o nome da imagem (o filename) juntamente com os demais dados do form no Mongo. Meu código está assim:
Trecho HTML do form com o input file:
<form novalidate name="formulario" class="row" ng-submit="submeter()">
<label class="btn-bs-file btn btn-primary">
Selecione a imagem
<input type="file" ngf-select ng-model="worker.file" name="file" ngf-pattern="'image/*'" accept="image/*" ngf-max-size="20MB" file-model="myFile"/>
</label>
<label>Image Preview</label>
<div class="imgArea">
<img style="width:150px;" ngf-thumbnail="worker.file || '/imagens/thumb.png'" ng-model="worker.file"/>
</div>
<button type="submit" class="btn btn-primary" ng-disabled= "formulario.$invalid">
Save
</button>
</form>
mydirective.js (para impedir que haja redirect quando dar submit):
.directive('fileModel', ['$parse', function ($parse) {
return {
restrict: 'A',
link: function(scope, element, attrs) {
var model = $parse(attrs.fileModel);
var modelSetter = model.assign;
element.bind('change', function(){
scope.$apply(function(){
modelSetter(scope, element[0].files[0]);
});
});
}
};
}]);
worker-controller.js:
$scope.submeter = function() {
if ($scope.formulario.$valid) {
cadastroDeWorkers.cadastrar($scope.worker)
.then(function(dados) {
$scope.mensagem = dados.mensagem;
if (dados.inclusao) $scope.worker = {};
})
.catch(function(erro) {
$scope.mensagem = erro.mensagem;
});
}
var file = $scope.myFile;
var uploadUrl = "/upload";
var fd = new FormData();
fd.append('file', file);
$http.post(uploadUrl,fd, {
transformRequest: angular.identity,
headers: {'Content-Type': undefined}
})
.success(function(){
console.log("success!!");
})
.error(function(){
console.log("error!!");
});
};
express.js (e a tentativa de inserir o filename no Mongo):
var express = require('express');
var app = express();
var consign = require('consign');
var bodyParser = require('body-parser');
var fs = require('fs');
var multer = require('multer');
app.use(function(req, res, next) { //allow cross origin requests
res.setHeader("Access-Control-Allow-Methods", "POST, PUT, OPTIONS, DELETE, GET");
res.header("Access-Control-Allow-Origin", "http://localhost");
res.header("Access-Control-Allow-Headers", "Origin, X-Requested-With, Content-Type, Accept");
next();
});
app.use(express.static('./public'));
app.use(bodyParser.json());
var storage = multer.diskStorage({
destination: function (req, url, cb) {
cb(null, './uploads/')
},
filename: function (req, url, cb) {
var datetimestamp = Date.now();
cb(null, url.fieldname + '-' + datetimestamp + '.' + url.originalname.split('.')[url.originalname.split('.').length -1]);
}
});
var upload = multer({ //multer settings
storage: storage
}).single('file');
/** API path that will upload the files */
app.post('/upload', function(req, res, next) {
//from this point I tried to insert filename into MongoDB
upload(req,res,function(err){
if(err){
res.json({error_code:1,err_desc:err});
return;
}
res.json({error_code:0,err_desc:null});
console.log(req.file);
console.log('TEST: ' + req.file.filename);
fs.readFile(req.file.path, function (err, data) {
var newPath = "./uploads/" + req.file.filename;
fs.writeFile(newPath, data, function (err) {
res.send("hi");
});
console.log(newPath);
});
});
});
module.exports = app;
E por fim, o model worker.js (somente o trecho relevante):
var mongoose = require('mongoose');
var schema = mongoose.Schema({
(other fields from form)...
file: {
data: Buffer,
contentType: String,
required: false
},
...
//Se eu tentar usar apenas type: String no file, ele exibe um erro tentando inserir a imagem como base64
});
mongoose.model('Worker', schema);
O erro exibido no console é:
{ fieldname: 'file',
originalname: '1.jpg',
encoding: '7bit',
mimetype: 'image/jpeg',
destination: './uploads/',
filename: 'file-1493730955783.jpg',
path: 'uploads\\file-1493730955783.jpg',
size: 15205 }
TEST: file-1493730955783.jpg
./uploads/file-1493730955783.jpg
_http_outgoing.js:356
throw new Error('Can\'t set headers after they are sent.');
^
Error: Can't set headers after they are sent.
at ServerResponse.OutgoingMessage.setHeader (_http_outgoing.js:356:11)
at ServerResponse.header
(C:\wamp\www\workbr\node_modules\express\lib\response.js:725:10)
at ServerResponse.send
(C:\wamp\www\workbr\node_modules\express\lib\response.js:170:12)
at C:\wamp\www\workbr\config\express.js:49:21
at FSReqWrap.oncomplete (fs.js:123:15)
npm ERR! Windows_NT 10.0.14393
npm ERR! argv "C:\\Program Files\\nodejs\\node.exe" "C:\\Program
Files\\nodejs\\node_modules\\npm\\bin\\npm-cli.js" "start"
npm ERR! node v6.9.5
npm ERR! npm v3.10.10
npm ERR! code ELIFECYCLE
npm ERR! workbr@1.0.0 start: `node server.js`
npm ERR! Exit status 1
npm ERR!
npm ERR! Failed at the workbr@1.0.0 start script 'node server.js'.
npm ERR! Make sure you have the latest version of node.js and npm installed.
npm ERR! If you do, this is most likely a problem with the workbr package,
npm ERR! not with npm itself.
npm ERR! Tell the author that this fails on your system:
npm ERR! node server.js
npm ERR! You can get information on how to open an issue for this project
with:
npm ERR! npm bugs workbr
npm ERR! Or if that isn't available, you can get their info via:
npm ERR! npm owner ls workbr
npm ERR! There is likely additional logging output above.
npm ERR! Please include the following file with any support request:
npm ERR! C:\wamp\www\workbr\npm-debug.log
Para quem quiser dar uma olhada, o projeto está no GitHub
Qual o erro no meu código e como posso ajustar? Agradeço muito!