作為本blog的需求,上傳圖片始終是要支援的。但是呢,久久未動,以為麻煩,儘管諸多文章顯示非常簡單。昨天晚上終於下定決心解決它。果然簡單異常,但是在本地測試成功之後發現部署到CloudFoundry卻不能正常運行,原來還有小細節沒有注意到。下面一一道來。
1. 準備工作
首先你要知道怎麼用NodeJs下面的Web架構Express,這是一個比較簡單、使用廣泛的架構,入門很簡單。本ramonblog就是用它搭建的。Express的View是用jade文法的,這個你也得懂一點。是不是學的東西有點多了?不用太理解,開始的時候都是抄的,抄得多也就懂了。
然後呢,我們就用可以準備我們的upload.jade了,這裡僅僅是包含了一個簡單的表單,裡面一個file input元素和一個submit元素。
div
form(method="post", enctype="multipart/form-data")
input(type="file", name="displayImage")
input(type="submit", name="submit", value="Submit")
2. 讓它工作吧
之所以Express底下上傳檔案非常簡單,是因為Express的bodyParser中介軟體會在解析request請求的時候,將“multipart/form-data”裡面的file input對應的內容自動處理儲存到預設的/tmp檔案夾下面,而你可以通過req.files來擷取所有的屬性,其內容大概如下:
{ displayImage:
{
size: 18925,
path: '/tmp/47662e4853761e4b30b6c3a329980dac',
name: '2.jpg',
type: 'image/jpeg',
lastModifiedDate: Wed, 18 Jul 2012 17:01:44 GMT,
_writeStream:
{ path: '/tmp/47662e4853761e4b30b6c3a329980dac',
fd: 36,
writable: false,
flags: 'w',
encoding: 'binary',
mode: 438,
bytesWritten: 18925,
busy: false,
_queue: [],
drainable: true },
length: [Getter],
filename: [Getter],
mime: [Getter]
}
}
}
注意其中的displayImage是我們在form中定義的file的name,req.files.displayImage的path表示在伺服器端的臨時地址,name表示上傳的原始檔案名稱,type則是檔案類型了。提交之後的處理則如下:
var fs = require('fs');
var path = require('path');
function(req, res) {
//你可能需要修改相關的newPath到你自己的地址
var filePath = req.files.displayImage.path;
var extName = path.extname(req.files.displayImage.name);
var imageUrl = "/upload/" + path.basename(filePath) + extName;
var newPath = __dirname + "/../public" + imageUrl;
//把圖片從臨時檔案夾複製到目的檔案夾,當然最好刪除臨時檔案
fs.readFile(filePath, function (err, data) {
if (err) {
res.send(err);
return;
}
fs.writeFile(newPath, data, function (err) {
if (!err) {
res.send({uploaded: true});
} else {
res.send(err);
}
});
});
}
注意,你可能需要自己修改newPath到你自己正確的地址。其次,如果想直接存取你上傳的圖片,需要把圖片放置在Express指定的public檔案夾下面,這樣可以直接通過連結訪問。
3. CloudFoundry上不能工作 www.2cto.com
很顯然在CF的伺服器上你不能寫檔案到 /tmp下面去。其實解決辦法也很簡單,就是把臨時檔案夾指定到你自己的應用下面去。譬如指定為應用下面的tmp檔案夾,需要做的就是在你的app.js中增加如下的i配置:
app.use(express.bodyParser({
uploadDir: __dirname + '/tmp'
}));
這裡要求的app.js就在應用的根目錄下,這樣__dirname就會是你的應用根目錄。之後你就可以在CF上執行上傳圖片了。
作者:llmlx