2017-04-12 49 views
1

我是初学者,当谈到nodeJS,AJAX请求和路由时。我在这里遵循教程nodejs, express example,并且一切都在服务器端工作。但是我不能为了我的生活而弄清楚如何将上传的文件(本例中是图像)显示回客户端。当我对位于seperate/uploads /目录中的文件提出请求时,我从服务器收到404响应。我假定这是一个路由的问题,但感到困惑如何创建明确的GET请求上传的文件NodeJS,Express,如何更新客户端来显示上传的文件

app.js

var express = require('express'); 
var app = express(); 
var bodyParser = require('body-parser'); 
var path = require('path'); 
var formidable = require('formidable'); 
var fs = require('fs'); 
app.use(express.static(path.join(__dirname, 'public'))); 
app.use(bodyParser.json()); 
app.use(bodyParser.urlencoded({ 
    extended: true 
})); 


//passport for login credentials 
var passport = require('passport'); 
var LocalStrategy = require('passport-local').Strategy; //here we implement the strategy that passport uses 

var crypto = require('crypto'); 
var sqlite3 = require('sqlite3'); 

var db = new sqlite3.Database('users.sqlite3'); 
var check; 
db.serialize(function() { 

    db.run("CREATE TABLE IF NOT EXISTS users (id INTEGER PRIMARY KEY AUTOINCREMENT, username TEXT, password TEXT, salt TEXT)"); 
    console.log('user table created'); 
    db.run("DELETE FROM users"); //clear table on run for debug 
    var stmt = db.prepare("INSERT INTO users VALUES (?,?,?,?)"); 
    stmt.run('15', 'tg', 'tg', "333"); 
    stmt.finalize(); 

    db.each("SELECT username, password, id, salt FROM users", function(err, row) { 
     console.log(row.username + ": " + row.password + ": " + row.id + ': ' + row.salt); 
    }); 
}); 

//db.close(); 


function hashPassword(password, salt) { 
    console.log('password hashing'); 
    var hash = crypto.createHash('sha256'); 
    hash.update(password); 
    hash.update(salt); 
    return hash.digest('hex'); 
} 

passport.use(new LocalStrategy(function(username, password, done) { 
    console.log('using local strat for passport'); 
    db.get('SELECT salt FROM users WHERE username = ?', username, function(err, row) { 
    if (!row) return done(null, false); 
    var hash = hashPassword(password, row.salt); 
    console.log('done hashing'); 
    db.get('SELECT username, id FROM users WHERE username = ? AND password = ?', username, hash, function(err, row) { 
     if (!row){ 
     console.log('failure'); 
     return done(null, false); 
     } 
     console.log('success'); 
     return done(null, row); 
    }); 
    }); 
})); 

passport.serializeUser(function(user, done) { 
    console.log('serializing'); 
    return done(null, user.id); 
}); 

passport.deserializeUser(function(id, done) { 
    console.log('deserializing') 
    db.get('SELECT id, username FROM users WHERE id = ?', id, function(err, row) { 
    if (!row) return done(null, false); 
    return done(null, row); 
    }); 
}); 

///end user authentication 

//on access to site, serve the user the login page 
app.get('/', function(req, res){ 
    res.sendFile(path.join(__dirname, 'views/home.html')); 

}); 

//providing routing access for success/failure on login attempt 
app.post('/login', 
    passport.authenticate('local', { successRedirect: '/home', 
            failureRedirect: '/fail' })); 

app.get('/fail', function(req,res){ 
    res.sendFile(path.join(__dirname, 'views/error.html')); 
}); 

app.get('/home', function(req,res){ 
    res.sendFile(path.join(__dirname, 'views/home.html')); 
}); 

app.get('/login', function(req,res){ 
    res.sendFile(path.join(__dirname, 'views/login.html')); 
    console.log('login unsuccessful'); 
}); 

app.get('/home', function(request, response) { 
     response.render('views/home'); 
}); 

app.get('/upload' , function(req, res){ 
    res.sendFile(__dirname + '/uploads'); 
}); 

app.post('/upload', function(req, res){ 

    // create an incoming form object 
    var form = new formidable.IncomingForm(); 

    // specify that we want to allow the user to upload multiple files in a single request 
    form.multiples = true; 

    // store all uploads in the /uploads directory 
    form.uploadDir = path.join(__dirname, '/uploads'); 

    // every time a file has been uploaded successfully, 
    // rename it to it's orignal name 
    form.on('file', function(field, file) { 
    fs.rename(file.path, path.join(form.uploadDir, file.name)); 
    }); 

    // log any errors that occur 
    form.on('error', function(err) { 
    console.log('An error has occured: \n' + err); 
    }); 

    // once all the files have been uploaded, send a response to the client 
    form.on('end', function() { 
    res.end('success'); 
    }); 

    // parse the incoming request containing the form data 
    form.parse(req); 

}); 

var server = app.listen(3000, function(){ 
    console.log('Server listening on port 3000'); 
}); 

upload.js

'use strict' 

$('.upload-btn').on('click', function(){ 
    $('#upload-input').click(); 
    $('.progress-bar').text('0%'); 
    $('.progress-bar').width('0%'); 
}); 

$('#upload-input').on('change', function(){ 

    var files = $(this).get(0).files; 

    if (files.length > 0){ 
    // create a FormData object which will be sent as the data payload in the 
    // AJAX request 
    var formData = new FormData(); 

    // loop through all the selected files and add them to the formData object 
    for (var i = 0; i < files.length; i++) { 
     var file = files[i]; 

     // add the files to formData object for the data payload 
     formData.append('uploads[]', file, file.name); 
    } 

    $.ajax({ 
     url: '/upload', 
     type: 'POST', 
     data: formData, 
     processData: false, 
     contentType: false, 
     success: function(data){ 
     console.log('upload success'); 
     }, 
     xhr: function() { 
     // create an XMLHttpRequest 
     var xhr = new XMLHttpRequest(); 

     // listen to the 'progress' event 
     xhr.upload.addEventListener('progress', function(evt) { 

      if (evt.lengthComputable) { 
      // calculate the percentage of upload completed 
      var percentComplete = evt.loaded/evt.total; 
      percentComplete = parseInt(percentComplete * 100); 

      // update the Bootstrap progress bar with the new percentage 
      $('.progress-bar').text(percentComplete + '%'); 
      $('.progress-bar').width(percentComplete + '%'); 

      // once the upload reaches 100%, set the progress bar text to done 
      if (percentComplete === 100) { 
       $('.progress-bar').html('Done'); 
       console.log(formData); 
       showUploadedItem(file.name); 
      } 


      } 


     }, false); 

     return xhr; 
     } 
    }); 

    } 
}); 


function showUploadedItem (source) { 
     var list = document.getElementById("image-list"), 
     li = document.createElement("li"), 
     img = document.createElement("img"); 
     img.src = source; 
     li.appendChild(img); 
     list.appendChild(li); 
} 
+0

'File'对象默认没有'.path'属性。 – guest271314

回答

0

因此,经过一段时间的挖掘,我发现你必须明确要求express可以将静态文件服务器添加到客户端,这是通过添加:

app.use(express.static('your_uploads_directory')); 

显然,其他一切都是按照我的教程和教程的实施正确设置的。

0

首先,在阅读您的文章时,您似乎想要下载的文件放在/uploads这是您的项目根目录中的一个文件夹。在第7行提供的app.js文件中,您有以下代码。

app.use(express.static(path.join(__dirname, 'public'))); 

此行确保所有请求发现,按照此公共文件夹中的文件夹结构被发现,并提供该文件夹中的文件,因此,例如,当公共文件夹包含以下文件:/public/stylesheets/foo.css所有通话从客户端/stylesheets/foo.css将被捕获并提供此文件。

更多解释可以在这里找到express documentation

因此,对于你在/uploads文件夹文件工作,你可以考虑两种选择,将文件/文件夹中的文件夹/public或更改代码,以提供在/uploads文件夹的静态链接文件。

第一个选项非常简单,第二个选项需要以下行。

app.use(express.static(path.join(__dirname, 'uploads'))); 

请记住,当您添加此第二行中,将这些线路的问题,例如奥德这意味着随后该文件夹中的文件结构中的所有请求都会被捕获和文件将被退回。然而,如果你有一个app.use,它也有相反的作用,它与这些静态链接之一中的文件具有完全相同的链接,该静态链接位于静态调用之前/之上,静态调用将不会到达。您可以避免这种情况,例如当您希望在发送文件之前发生某些事情时,因为这与提供所谓的middleware链接的问题无关。

相关问题