2015-01-05 17 views
13

Używam Multer do przesyłania zdjęć w Express 4. Jednak wszystkie przykłady pokazują, że Multer jest zdefiniowany w pliku ekspresowym jako Middleware. Chciałbym zdefiniować niektóre zachowania Multera w moim routingu aplikacji. czy to możliwe? Końcowy wynik, którego potrzebuję, to funkcja rozpoznawania przez moją trasę, kiedy przesyłanie zostanie zakończone, zanim wyśle ​​odpowiedź serwera do przeglądarki, aby obraz mógł być wyświetlony użytkownikowi (w tej chwili wyświetlany jest tylko częściowo wyświetlany obraz, ponieważ plik jeszcze się nie zakończył).Użyj Multer w Express Route? (Używając MEANJS)

AKTUALNE, pracując KOD

express.js

// Require Multer as module dependency. 
var multer = require('multer'); 

// Using Multer for file uploads. 
app.use(multer({ 
    dest: './public/profile/img/', 
    limits: { 
     fieldNameSize: 50, 
     files: 1, 
     fields: 5, 
     fileSize: 1024 * 1024 
    }, 
    rename: function(fieldname, filename) { 
     return filename; 
    }, 
    onFileUploadStart: function(file) { 
     if(file.mimetype !== 'image/jpg' && file.mimetype !== 'image/jpeg' && file.mimetype !== 'image/png') { 
      return false; 
     } 
    } 
})); 

server_routes.js

app.route('/users/image').post(server_controller_file.imageUpload); 

server_controller_file.js

exports.imageUpload = function(req, res) { 
// Check to make sure req.files contains a file, mimetypes match, etc., then send appropriate server response. 
}; 

Idealnie mój plik server_controller_file.js zawierałby pewne kontrole, aby upewnić się, że plik został zakończony, np. (Uwaga: jest to hipotetyczna/pożądane, a nie rzeczywisty kod roboczy) ...

var multer = require('multer'); 
exports.imageUpload = function(req, res) { 
    multer({ 
     onFileUploadComplete: function(file) { 
      res.send(); 
     } 
    }); 
} 

Ponownie, teraz charakter asynchroniczny węzła powoduje przeglądarkę myśleć zakończeniu wysyłania tak szybko, jak to odbiera pomyślna odpowiedź, więc gdy aktualizuję adres URL do wyświetlania obrazu, wyświetla się on tylko częściowo. Dzięki za pomoc!

+0

Czy można uzyskać 'plik.path' w funkcji onFileUploadComplete? –

+0

Ponieważ 'multer' działa jako Middleware, myślę, że nie działałby on w twoim pliku_controlera_serwera. Nie wiesz kiedy zakończył się przesyłanie pliku. Zobacz ten przykład: http: //codeforgeek.com/2014/11/file-uploads-using-node-js/ –

+0

@RyanYiada Mogę uzyskać dostęp do pliku.ścieżka w funkcji onFileUploadComplete, ale nadal nie komunikuje się z routerem. Artykuł, z którym się łączyłeś, był dobry - zawiera zmienną "done", która dotyczy zarówno oprogramowania pośredniego, jak i routera, ale ponieważ moje oprogramowanie pośrednie i router znajdują się w oddzielnych plikach, moje zmienne oprogramowania pośredniego są poza zasięgiem routera. – aikorei

Odpowiedz

7

OK, ja właściwie tylko skończyło się zapisu danych surowych. Jeśli ustawisz inMemory na true, przesyła nieprzetworzone dane do pliku req.files.file.buffer. Oto ostateczny, roztwór roboczy:

express.js

// Using Multer for file uploads. 
app.use(multer({ 
    dest: './public/profile/img/', 
    limits: { 
     fieldNameSize: 50, 
     files: 1, 
     fields: 5, 
     fileSize: 1024 * 1024 
    }, 
    rename: function(fieldname, filename) { 
     return filename; 
    }, 
    onFileUploadStart: function(file) { 
     console.log('Starting file upload process.'); 
     if(file.mimetype !== 'image/jpg' && file.mimetype !== 'image/jpeg' && file.mimetype !== 'image/png') { 
      return false; 
     } 
    }, 
    inMemory: true //This is important. It's what populates the buffer. 
})); 

server_controller_file.js

exports.imageUpload = function(req, res) { 
    var file = req.files.file, 
     path = './public/profile/img/'; 

    // Logic for handling missing file, wrong mimetype, no buffer, etc. 

    var buffer = file.buffer, //Note: buffer only populates if you set inMemory: true. 
     fileName = file.name; 
    var stream = fs.createWriteStream(path + fileName); 
    stream.write(buffer); 
    stream.on('error', function(err) { 
     console.log('Could not write file to memory.'); 
     res.status(400).send({ 
      message: 'Problem saving the file. Please try again.' 
     }); 
    }); 
    stream.on('finish', function() { 
     console.log('File saved successfully.'); 
     var data = { 
      message: 'File saved successfully.' 
     }; 
     res.jsonp(data); 
    }); 
    stream.end(); 
    console.log('Stream ended.'); 
}; 
2

znajdę przykład dla busboy:

exports.upload = function (req, res, next) { 
    req.busboy.on('file', function (fieldname, file, filename, encoding, mimetype) { 
     // .... 
    }); 

    req.pipe(req.busboy); 
}; 

multer jest również zamontowanie busboy:

req.pipe(busboy); 

https://github.com/expressjs/multer/blob/master/index.js#206

+0

Czy mówisz, że robienie tego, co chcę zrobić, nie będzie działać z Multer? I zamiast tego powinienem użyć Busboy? – aikorei

+0

Nie było dla mnie jasne, dopóki nie spojrzałem pod maską, ale multer jest po prostu busboyem opakowanym i zaimplementowanym jako middleware. Musiałem wpasować się w zdarzenia busboya na trasie, więc po prostu użyłem busboya bezpośrednio. – eephillip

+0

@aikorei as eephillip mówi, że multer to po prostu busboy wrapper.multer zwróci busboy. –

17

Właściwie można robić, co chcesz z inną metodą:

var express = require('express'); 
 
var multer = require('multer'); 
 
var upload = multer({ dest: './uploads/'}); 
 
var app = express(); 
 

 
app.get('/', function(req, res){ 
 
    res.send('hello world'); 
 
}); 
 

 
// accept one file where the name of the form field is named photho 
 
app.post('/', upload.single('photho'), function(req, res){ 
 
    console.log(req.body); // form fields 
 
    console.log(req.file); // form files 
 
    res.status(204).end(); 
 
}); 
 

 
app.listen(3000);

+2

To jest lepsze podejście niż w przypadku rozwiązania oznaczonego jako odpowiedź. optymalizuje oprogramowanie pośrednie na trasie. Jeśli połączysz wiele programów pośredniczących ze sobą, zobaczysz, że ekspresowe strumienie używają, ale nie działa to w pełni z oprogramowaniem pośredniczącym. Zdarzenia nie są przesyłane strumieniowo między oprogramowaniem pośredniczącym. Jeśli użyjesz dwóch wyrazistych middleware w łańcuchu, a każdy spróbuje przechwycić wszystkie zdarzenia strumieniowe i wywoła następne(), gdy wszystkie zdarzenia zostaną zakończone, drugie oprogramowanie pośrednie nie będzie już otrzymywać wymaganych zdarzeń. W takim przypadku musisz zoptymalizować oprogramowanie pośrednie na trasie. – SharpCoder

+0

Po prostu krótkie pytanie, dlaczego jest ono zawarte w [], jest podobne do definiowania łańcucha zamiast używania następnej funkcji? – Snymax

+1

Twoja odpowiedź nie zadziała, jeśli nazwa folderu docelowego będzie zależała od parametrów w punkcie odbioru, jak to zrobisz? –