2013-04-03 58 views
0

我一直在解決這個錯誤超過兩個星期了,並且找不到出錯的地方。我已經使用FineUploader來上傳多個文件。我有一個項目的集合,每個需要得到它自己的圖像。所以我將一個參數放在請求中,以確定圖像對應的項目。我也有圖片庫和徽標的上傳者。在Node.js中使用FineUploader上傳文件掛起了服務器

我手動觸發上傳並在服務器上獲取請求,然後設置req.on(data,function(){...})來上傳文件。這永遠不會被觸發。

這是我的代碼:

$(document).ready(function() { 
    window.onSubmit = function (uploaderName) { 
     return function (id, fileName) { 
      console.log("Setting parameters...") 
      window[uploaderName].setParams({ 
       farm: $('input[name=farm-name]').val() 
      }); 
     } 
    }; 

    window.logoUploader = new qq.FineUploader({ 
     element: $('#logo')[0], 
     request: { 
      endpoint: '/upload/farm/logo' 
     }, 
     autoUpload: false, 
     debug: true, 
     validation: { 
      allowedExtensions: ['jpeg', 'jpg', 'gif', 'png'], 
      sizeLimit: 1024000 // 50 kB = 50 * 1024 bytes 
     }, 
     text: { 
      uploadButton: '<i class="icon-plus icon-white"></i> Select Logo' 
     }, 
     callbacks: { 
      onSubmit: onSubmit("logoUploader") 
     } 
    }); 

    window.shareLogoUploader = []; 
    window.shareLogoUploader[0] = new qq.FineUploader({ 
    element: $('#share-logo-0')[0], 
    request: { 
     endpoint: '/upload/farm/share/gallery' 
    }, 
    autoUpload: false, 
    debug: true, 
    validation: { 
     allowedExtensions: ['jpeg', 'jpg', 'gif', 'png'], 
     sizeLimit: 1024000 // 50 kB = 50 * 1024 bytes 
    }, 
    text: { 
     uploadButton: '<i class="icon-plus icon-white"></i> Select Logo' 
    } 
    }); 

    window.galleryUploader = new qq.FineUploader({ 
     element: $('#gallery')[0], 
     request: { 
      endpoint: '/upload/farm/gallery/photo' 
     }, 
     autoUpload: false, 
     debug: true, 
     validation: { 
      allowedExtensions: ['jpeg', 'jpg', 'gif', 'png'], 
      sizeLimit: 2024000 // around 2mbs 
     }, 
     text: { 
      uploadButton: '<i class="icon-plus icon-white"></i> Pics' 
     }, 
     callbacks: { 
      onComplete: function (event, id, fileName, responseJSON) { 
       if (responseJSON.success) { 
        console.log(responseJSON, fileName); 
        $('#thumbnails').append('<img src="/uploads/' + fileName + '" width="256px"><input type="hidden" name="photos[]" value="' + fileName + '">'); 
       } 
      }, 
      onSubmit: onSubmit("galleryUploader") 
     } 
    }); 
}); 

// Shares 
var shares = []; 
var sharesGallery = []; 

$(function() { 
    $('section#shares button#add-share').click(function (e) { 
     e.preventDefault(); 

     var title = $('section#shares .control-group input[name=title]'); 
     var size = $('section#shares .control-group select[name=size]'); 
     var type = $('section#shares .control-group select[name=type]'); 
     var price = $('section#shares .control-group input[name=price]'); 
     var amount = $('section#shares .control-group input[name=amount]'); 
     var unit = $('section#shares .control-group select[name=unit]'); 
     var discount_3 = $('input[name=discount-3]').val(); 
     var discount_6 = $('input[name=discount-6]').val(); 
     var discount_12 = $('input[name=discount-12]').val(); 
     var errors = $('section#shares .control-group#errors'); 
     var delivery_period = $('section#shares .control-group input[name=delivery_period]'); 
     var delivery_period_es = $('section#shares .control-group input[name=delivery_period_es]'); 
     var billing_period = $('section#shares .control-group input[name=billing_period]'); 
     var billing_period_es = $('section#shares .control-group input[name=billing_period_es]'); 
     var logoUploader = window.shareLogoUploader[shares.length]; 
     var logoButtonId = "share-logo-" + shares.length; 

      shares.push({ 
       title: title.val(), 
       currency: $('select[name=currency]').children(':selected').val(), 
       size: size.children(':selected').val(), 
       type: type.children(':selected').val(), 
       price: price.val() * 100.0, 
       unit: unit.children(':selected').val(), 
       amount: amount.val(), 
       discounts: { 
        '3': [discount_3, price.val() * discount_3/100.0], 
        '6': [discount_6, price.val() * discount_6/100.0], 
        '12': [discount_12, price.val() * discount_12/100.0] 
       }, 
       delivery_period: delivery_period.val(), 
       delivery_period_es: delivery_period_es.val(), 
       billing_period: billing_period.val(), 
       billing_period_es: billing_period_es.val() 
      }); 

      var newLogoButtonId = "share-logo-" + shares.length; 

      sharesGallery.push({ 
       name: type.children(':selected').val() + "-" + size.children(':selected').val(), 
       logoUploader: logoUploader 
      }) 
     $("#" + logoButtonId).css('display', 'none'); 
     $("#" + logoButtonId).parent().append('<div id="' + newLogoButtonId + '"></div>'); 

     window.shareLogoUploader[shares.length] = new qq.FineUploader({ 
      element: $("#" + newLogoButtonId)[0], 
      request: { 
       endpoint: '/upload/farm/share/gallery' 
      }, 
      autoUpload: false, 
      debug: true, 
      validation: { 
       allowedExtensions: ['jpeg', 'jpg', 'gif', 'png'], 
       sizeLimit: 1024000 // 50 kB = 50 * 1024 bytes 
      }, 
      text: { 
       uploadButton: '<i class="icon-plus icon-white"></i> Select Logo' 
      } 
     }); 

     console.log(shares); 

     return; 
    } 
}); 

這正確地觸發上傳,我得到的服務器上的請求,這樣處理,那麼服務器掛在等待一個永遠不會到來,重新REQ數據。 on數據naver被觸發。這是服務器端代碼:

var fs = require('fs'), util = require('util'), uuid = require('node-uuid'); 

var uploadpath = __dirname + "/../public/uploads/"; 

var slugify = exports.slugify = function(value) { 
    return value.toLowerCase().replace(/-+/g, '').replace(/\s+/g, '-').replace(/[^a-z0-9-]/g, ''); 
}; 
// Route that takes the post upload request and sends the server response 
exports.upload = function(req, res) { 
    winston.info("Upload parameters", [req.route.params[0], req.query.farm]); 
    uploadpath = __dirname + "/../public/uploads/"; 
    if(!fs.existsSync(uploadpath)) { 
     fs.mkdirSync(uploadpath); 
    } 
    switch(req.route.params[0]) { 
     case 'farm/logo': 
      uploadpath += "../farms/" + slugify(req.query.farm); 
      if(!fs.existsSync(uploadpath)) { 
       fs.mkdirSync(uploadpath); 
      } 
      uploadpath += "/" + "logo." + req.header('x-file-name').split(".").pop(); 
      break; 

     case 'farm/gallery/photo': 
      uploadpath += "../farms/" + slugify(req.query.farm); 
      if(!fs.existsSync(uploadpath)) { 
       fs.mkdirSync(uploadpath); 
      } 
      uploadpath += "/gallery"; 
      if(!fs.existsSync(uploadpath)) { 
       fs.mkdirSync(uploadpath); 
      } 
      var fname = req.header('x-file-name'); 
      uploadpath += "/" + fname; 
      break; 

     case 'farm/share/gallery': 
      uploadpath += "../farms/" + slugify(req.query.farm); 
      if(!fs.existsSync(uploadpath)) { 
       fs.mkdirSync(uploadpath); 
      } 
      uploadpath += "/shares"; 
      if(!fs.existsSync(uploadpath)) { 
       fs.mkdirSync(uploadpath); 
      } 
      uploadpath += "/" + slugify(req.query.share); 
      if(!fs.existsSync(uploadpath)) { 
       fs.mkdirSync(uploadpath); 
      } 
      uploadpath += "/gallery"; 
      if(!fs.existsSync(uploadpath)) { 
       fs.mkdirSync(uploadpath); 
      } 
      var fname = req.header('x-file-name'); 
      uploadpath += "/" + fname; 
      break; 
     case 'courier/license': 
     case 'courier/registration': 
      uploadpath += "../couriers/" + slugify(req.query.courier); 
      if(!fs.existsSync(uploadpath)) { 
       fs.mkdirSync(uploadpath); 
      } 
      var fname = req.header('x-file-name'); 
      uploadpath += "/" + fname; 
      break; 

     default: 
      var fname = req.header('x-file-name'); 
      uploadpath += fname; 
      break; 
    } 

    winston.info("Uploading to ", uploadpath); 

    uploadFile(req, uploadpath, function(data) { 
     if(data.success) 
      res.send(JSON.stringify(data), { 
       'Content-Type' : 'text/plain' 
      }, 200); 
     else 
      res.send(JSON.stringify(data), { 
       'Content-Type' : 'text/plain' 
      }, 404); 
    }); 
} 
// Mainfunction to recieve and process the file upload data asynchronously 
var uploadFile = function(req, targetfile, callback) { 

    // Moves the uploaded file from temp directory to it's destination 
    // and calls the callback with the JSON-data that could be returned. 
    var moveToDestination = function(sourcefile, targetfile) { 
     moveFile(sourcefile, targetfile, function(err) { 
      if(!err) 
       callback({ 
        success : true 
       }); 
      else 
       callback({ 
        success : false, 
        error : err 
       }); 
     }); 
    }; 
    // Direct async xhr stream data upload, yeah baby. 
    if(req.xhr) { 

     // Be sure you can write to '/tmp/' 
     var tmpfile = '/tmp/' + uuid.v1(); 

     // Open a temporary writestream 
     var ws = fs.createWriteStream(tmpfile); 
     ws.on('error', function(err) { 
      console.log("uploadFile() - req.xhr - could not open writestream."); 
      callback({ 
       success : false, 
       error : "Sorry, could not open writestream." 
      }); 
     }); 
     ws.on('close', function(err) { 
      moveToDestination(tmpfile, targetfile); 
     }); 
     // Writing filedata into writestream 
     req.on('data', function(data) { 
      ws.write(data); 
     }); 
     req.on('end', function() { 
      ws.end(); 
     }); 
    } 

    // Old form-based upload 
    else { 
     moveToDestination(req.files.qqfile.path, targetfile); 
    } 
}; 
// Moves a file asynchronously over partition borders 
var moveFile = function(source, dest, callback) { 
    var is = fs.createReadStream(source) 

    is.on('error', function(err) { 
     console.log('moveFile() - Could not open readstream.', err); 
     callback('Sorry, could not open readstream.') 
    }); 
    is.on('end', function() { 
     fs.unlinkSync(source); 
     callback(); 
    }); 
    var os = fs.createWriteStream(dest); 
    os.on('error', function(err) { 
     console.log('moveFile() - Could not open writestream.', err); 
     callback('Sorry, could not open writestream.'); 
    }); 

    is.pipe(os); 
} 

有人點我在正確的方向來獲得文件上傳與文件中的每一束diferent參數?

預先感謝您。

回答

0

看起來您正在使用Node示例,或者可能是Fine Uploader Github項目的服務器目錄中Node節點示例的修改版本。該示例尚未更新爲處理多部分編碼的請求,Fine Uploader現在默認爲所有瀏覽器發送該請求。

我對Node沒有多少經驗,但是如果您使用的是Express,您似乎可以/應該只使用req.files來獲取與請求相關的文件。

我會在Widen/fine-uploader-server repo中打開一個案例來提醒我更新節點示例。

+0

謝謝您的回答。我在express.bodyParser中添加了uploadDir配置,但是當我檢查req.files時,對象是空的= /以任何方式將fine-uploader設置爲之前的行爲?它之前在工作。 – Nevtep

+0

'req.files'應該一定有與請求相關的文件。您的服務器端代碼很可能存在其他問題,或者Express配置不正確。我對節點沒有足夠的瞭解,無需閱讀就能提供建議。如果'req.files'不適合你,你需要深入一點你的代碼。雖然如果瀏覽器支持File API,您可以告訴Fine Uploader簡單地傳輸文件(舊的默認行爲),但無論如何,您都需要在IE9及更高版本中解析MPE請求。 –

+0

我也鏈接fineuploader是這樣的: //cdnjs.cloudflare.com/ajax/libs/file-uploader/3.1.1/fineuploader.min.js 我會深入到req.files的東西,讓你知道我發現了什麼。 感謝您的快速回復 – Nevtep

3

好吧,如果有人(像我)需要一個體面和簡單的例子,用他們的node.js/express應用程序來實現Fine Uploader - 我終於能夠得到它的工作。事實證明,我讓自己變得比所需要的要困難得多,Fine Uploader服務器的例子並沒有說明新版本的Express(這是[email protected])現在有多容易。

app.use(express.bodyParser({uploadDir: __dirname + '/uploads'})); 

app.get('/upload', localQuery, function(request, response) { 
    //This serves up our 
    response.render('index'); 

}); 

app.post('/uploadhander', function (request, response, next) { 

    var fileName = request.files.qqfile.name 
    var savePath = __dirname + '/process/'; 

    //after upload, rename the file, then respond to fineuploader to tell it of success 
    fs.rename(request.files.qqfile.path, savePath + fileName, function(err) { 
    if (err != null) { 
     response.send(JSON.stringify({success: false, error: err}), {'Content-Type': 'text/plain'}, 404); 
    } else { 
     response.send(JSON.stringify({success: true}), {'Content-Type': 'text/plain'}, 200); 
    } 
    }); 

}); 

這裏是玉模板/上傳,處理精細上傳選項的位(你的選擇顯然會有所不同):

div.span12 
    h4 Upload a show file 
    #jquery-wrapped-fine-uploader 
     script(type='text/javascript') 
     jQuery(document).ready(function() { 
      jQuery('#jquery-wrapped-fine-uploader').fineUploader({ 
      debug: false, 
      request: { 
       endpoint: '/uploadhander', 
       params: { 
       hostname: "#{locals.query.hostname}", 
       hostport: "#{locals.query.hostport}", 
       bucket: "#{locals.query.bucket}", 
       nid: "#{locals.query.nid}", 
       title: "#{locals.query.title}", 
       }, 
       chunking: { 
       enabled: true, 
       }, 
       resume: { 
       enabled: true, 
       }, 
      } 
      }); 
     }); 

我應該指出的是,我還沒有測試了恢復功能,但我可以驗證多個上傳正在處理,與已發佈的示例顯示的代碼少得多。希望這可以幫助別人!

+0

給任何觀察者的提示:@Logickal用改進的節點服務器端示例在Widen/fine-uploader-server上打開了一個pull請求。它現在是服務器端示例回購的一部分。謝謝@Logickal! –

0

它更實用,使用簡單multer與express.js 。我的服務器端代碼看起來象

var multer = require('multer'); 

var upload = multer({ 
    dest : path.join(__dirname , '../public/uploads/') 
}); 

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

    upload(req, res, function (err) { 

     if (err) 
      response.send(JSON.stringify({success: false, error: err}), {'Content-Type': 'text/plain'}, 404); 
     else 
      res.send(JSON.stringify({success: true}), {'Content-Type': 'text/plain'}, 200); 

    }); 


}); 

module.exports = router; 
相關問題