Node做中轉(zhuǎn)服務(wù)器轉(zhuǎn)發(fā)接口
由于項(xiàng)目在做前后端分離,牽扯跨域和夸協(xié)議問(wèn)題,臨時(shí)抱佛腳,選擇用nodejs做中轉(zhuǎn),我想應(yīng)該好多人都用它。但是做普通的表單轉(zhuǎn)發(fā)沒(méi)啥問(wèn)題,當(dāng)處理附件上傳轉(zhuǎn)發(fā)時(shí),各種蛋疼,已解決!
1.項(xiàng)目比較特殊,后臺(tái)擁有兩個(gè)平臺(tái),一個(gè)java一個(gè)donet,比較雞肋,具體什么原因就不解釋了。
2.當(dāng)做node轉(zhuǎn)發(fā)時(shí),剛開始沒(méi)有轉(zhuǎn)發(fā)文件的操作,就做的很簡(jiǎn)單,用戶傳過(guò)來(lái)啥就,攔截到,進(jìn)行轉(zhuǎn)發(fā),一切都很ok!
3.文件轉(zhuǎn)發(fā),就很麻煩。我的思路,將用戶上傳的文件存到node服務(wù)器。使用formidable 。
通過(guò)npm安裝:
npm install formidable@latest
使用它進(jìn)行文件轉(zhuǎn)存,保存到臨時(shí)目錄得到文件信息。
再通過(guò)文件包重組。進(jìn)行上傳。注意此處上傳必須遵循w3c上傳文件表單標(biāo)準(zhǔn),具體自己查資料。
其實(shí)思路很簡(jiǎn)單,但是實(shí)際操作起來(lái)還是挺麻煩,我中間也趟了好多坑,也是自己node不成熟,畢竟只是用來(lái)做中轉(zhuǎn)!
直接上代碼吧:看代碼還是清晰:
server.js,用于啟動(dòng)服務(wù)并轉(zhuǎn)發(fā)。
var http = require("http"); var url = require("url"); var fs = require('fs'); const querystring = require("querystring"); var path = require('path'); var formidable = require('formidable'), os = require('os'), util = require('util'); var config = require('./config').types; // var netServerUrlFlag = require('./config').netServerUrlFlag; var netServerhost = require('./config').netServerhost; var netServerport = require('./config').netServerport; var javaServerUrlFlag = require('./config').javaServerUrlFlag; var javaServerhost = require('./config').javaServerhost; var javaServerport = require('./config').javaServerport; var fileServerUrlFlag = require('./config').fileServerUrlFlag; var webapp = require('./config').webapp; var PORT = require('./config').webport; /** * 上傳文件 * @param files 經(jīng)過(guò)formidable處理過(guò)的文件 * @param req httpRequest對(duì)象 * @param postData 額外提交的數(shù)據(jù) */ function uploadFile(files, req, postData) { var boundaryKey = Math.random().toString(16); var endData = '\r\n----' + boundaryKey + '--'; var filesLength = 0, content; // 初始數(shù)據(jù),把post過(guò)來(lái)的數(shù)據(jù)都攜帶上去 content = (function (obj) { var rslt = []; Object.keys(obj).forEach(function (key) { arr = ['\r\n----' + boundaryKey + '\r\n']; arr.push('Content-Disposition: form-data; name="' + obj[key][0] + '"\r\n\r\n'); arr.push(obj[key][1]); rslt.push(arr.join('')); }); return rslt.join(''); })(postData); // 組裝數(shù)據(jù) Object.keys(files).forEach(function (key) { if (!files.hasOwnProperty(key)) { delete files.key; return; } content += '\r\n----' + boundaryKey + '\r\n' + 'Content-Type: application/octet-stream\r\n' + 'Content-Disposition: form-data; name="' + files[key][0] + '"; ' + 'filename="' + files[key][1].name + '"; \r\n' + 'Content-Transfer-Encoding: binary\r\n\r\n'; files[key].contentBinary = new Buffer(content, 'utf-8');; filesLength += files[key].contentBinary.length + fs.statSync(files[key][1].path).size; }); req.setHeader('Content-Type', 'multipart/form-data; boundary=--' + boundaryKey); req.setHeader('Content-Length', filesLength + Buffer.byteLength(endData)); // 執(zhí)行上傳 var allFiles = Object.keys(files); var fileNum = allFiles.length; var uploadedCount = 0; allFiles.forEach(function (key) { req.write(files[key].contentBinary); console.log("files[key].path:" + files[key][1].path); var fileStream = fs.createReadStream(files[key][1].path, { bufferSize: 4 * 1024 }); fileStream.on('end', function () { // 上傳成功一個(gè)文件之后,把臨時(shí)文件刪了 fs.unlink(files[key][1].path); uploadedCount++; if (uploadedCount == fileNum) { // 如果已經(jīng)是最后一個(gè)文件,那就正常結(jié)束 req.end(endData); } }); fileStream.pipe(req, { end: false }); }); } var server = http.createServer(function (request, response) { var clientUrl = request.url; var url_parts = url.parse(clientUrl); //解析路徑 var pathname = url_parts.pathname; var sreq = request; var sres = response; // .net 轉(zhuǎn)發(fā)請(qǐng)求 if (pathname.match(netServerUrlFlag) != null) { var clientUrl2 = clientUrl.replace("/" + netServerUrlFlag, ''); console.log(".net轉(zhuǎn)發(fā)請(qǐng)求......" + clientUrl2); var pramsJson = ''; sreq.on("data", function (data) { pramsJson += data; }).on("end", function () { var contenttype = request.headers['content-type']; if (contenttype == undefined || contenttype == null || contenttype == '') { var opt = { host: netServerhost, //跨域訪問(wèn)的主機(jī)ip port: netServerport, path: clientUrl2, method: request.method, headers: { 'Content-Length': Buffer.byteLength(pramsJson) } } } else { var opt = { host: netServerhost, //跨域訪問(wèn)的主機(jī)ip port: netServerport, path: clientUrl2, method: request.method, headers: { 'Content-Type': request.headers['content-type'], 'Content-Length': Buffer.byteLength(pramsJson) } } } console.log('method', opt.method); var body = ''; var req = http.request(opt, function (res) { res.on('data', function (data) { body += data; }).on('end', function () { response.write(body); response.end(); }); }).on('error', function (e) { response.end('內(nèi)部錯(cuò)誤,請(qǐng)聯(lián)系管理員!MSG:' + e); console.log("error: " + e.message); }) req.write(pramsJson); req.end(); }) } else // java 轉(zhuǎn)發(fā)請(qǐng)求 if (pathname.match(javaServerUrlFlag) != null) { response.setHeader("Content-type", "text/plain;charset=UTF-8"); var clientUrl2 = clientUrl.replace("/" + javaServerUrlFlag, ''); console.log(".java轉(zhuǎn)發(fā)請(qǐng)求......http://" + javaServerhost + ":" + javaServerport + "" + clientUrl2); var prams = ''; sreq.on("data", function (data) { prams += data; }).on("end", function () { console.log("client pramsJson>>>>>" + prams); const postData = prams; console.log("client pramsJson>>>>>" + postData); var contenttype = request.headers['content-type']; if (contenttype == undefined || contenttype == null || contenttype == '') { var opt = { host: javaServerhost, //跨域訪問(wèn)的主機(jī)ip port: javaServerport, path: "/hrrp" + clientUrl2, method: request.method, headers: { 'Content-Length': Buffer.byteLength(postData) } } } else { var opt = { host: javaServerhost, //跨域訪問(wèn)的主機(jī)ip port: javaServerport, path: "/hrrp" + clientUrl2, method: request.method, headers: { 'Content-Type': request.headers['content-type'], 'Content-Length': Buffer.byteLength(postData) } } } var body = ''; console.log('method', opt.method); var req = http.request(opt, function (res) { //console.log("response: " + res.statusCode); res.on('data', function (data) { body += data; }).on('end', function () { response.write(body); response.end(); //console.log("end:>>>>>>>" + body); }); }).on('error', function (e) { response.end('內(nèi)部錯(cuò)誤,請(qǐng)聯(lián)系管理員!MSG:' + e); console.log("error: " + e.message); }) req.write(postData); req.end(); }) } else if (pathname.match(fileServerUrlFlag) != null) { //文件攔截保存到本地 var form = new formidable.IncomingForm(), files = [], fields = []; form.uploadDir = os.tmpdir(); form.on('field', function (field, value) { console.log(field, value); fields.push([field, value]); }).on('file', function (field, file) { console.log(field, file); files.push([field, file]); }).on('end', function () { // var clientUrl2 = clientUrl.replace("/" + fileServerUrlFlag, ''); var opt = { host: netServerhost, //跨域訪問(wèn)的主機(jī)ip port: netServerport, path: clientUrl2, method: request.method } var body = ''; var req = http.request(opt, function (res) { res.on('data', function (data) { body += data; }).on('end', function () { response.write(body); response.end(); }); }).on('error', function (e) { response.end('內(nèi)部錯(cuò)誤,請(qǐng)聯(lián)系管理員!MSG:' + e); console.log("error: " + e.message); }) //文件上傳 uploadFile(files, req, fields); }); form.parse(sreq); } else { var realPath = path.join(webapp, pathname); //這里設(shè)置自己的文件名稱; var ext = path.extname(realPath); ext = ext ? ext.slice(1) : 'unknown'; fs.exists(realPath, function (exists) { //console.log("file is exists:"+exists+" file path: " + realPath + ""); if (!exists) { response.writeHead(404, { 'Content-Type': 'text/plain' }); response.write("This request URL " + pathname + " was not found on this server."); response.end(); } else { fs.readFile(realPath, "binary", function (err, file) { if (err) { response.writeHead(500, { 'Content-Type': 'text/plain' }); //response.end(err); response.end("內(nèi)部錯(cuò)誤,請(qǐng)聯(lián)系管理員"); } else { var contentType = config[ext] || "text/plain"; response.writeHead(200, { 'Content-Type': contentType }); response.write(file, "binary"); response.end(); } }); } }); } }); server.listen(PORT); console.log("Server runing at port: " + PORT + ".");
config.js,用于配置。
exports.types = { "css": "text/css", "gif": "image/gif", "html": "text/html", "htm": "text/html", "ico": "image/x-icon", "jpeg": "image/jpeg", "jpg": "image/jpeg", "js": "text/javascript", "json": "application/json", "pdf": "application/pdf", "png": "image/png", "svg": "image/svg+xml", "swf": "application/x-shockwave-flash", "tiff": "image/tiff", "txt": "text/plain", "wav": "audio/x-wav", "wma": "audio/x-ms-wma", "wmv": "video/x-ms-wmv", "xml": "text/xml" }; exports.netServerUrlFlag = "NETSERVER"; exports.netServerhost = ""; exports.netServerport = ""; exports.javaServerUrlFlag = "JAVASERVER"; exports.javaServerhost = ""; //轉(zhuǎn)發(fā)的地址 exports.javaServerport = "";//轉(zhuǎn)發(fā)的端口 exports.fileServerUrlFlag="FileUpload"; exports.webapp = "public";//項(xiàng)目目錄 exports.webport = "82"; //項(xiàng)目啟動(dòng)端口
總結(jié)
以上所述是小編給大家介紹的Node做中轉(zhuǎn)服務(wù)器轉(zhuǎn)發(fā)接口,希望對(duì)大家有所幫助,如果大家有任何疑問(wèn)請(qǐng)給我留言,小編會(huì)及時(shí)回復(fù)大家的。在此也非常感謝大家對(duì)腳本之家網(wǎng)站的支持!
相關(guān)文章
nodejs入門教程五:連接數(shù)據(jù)庫(kù)的方法分析
這篇文章主要介紹了nodejs入門教程之連接數(shù)據(jù)庫(kù)的方法,結(jié)合實(shí)例形式分析了nodejs連接數(shù)據(jù)庫(kù)的具體步驟與相關(guān)操作技巧,需要的朋友可以參考下2017-04-04nodejs文件實(shí)現(xiàn)打包成exe, 并設(shè)置開機(jī)自啟動(dòng)的方法詳解(沒(méi)有黑窗口)
這篇文章主要介紹了nodejs文件實(shí)現(xiàn)打包成exe, 并設(shè)置開機(jī)自啟動(dòng)的方法,結(jié)合實(shí)例形式分析了node.js使用pkg包實(shí)現(xiàn)生成exe可執(zhí)行文件的相關(guān)操作技巧,需要的朋友可以參考下2023-05-05對(duì)node.js中render和send的用法詳解
今天小編就為大家分享一篇對(duì)node.js中render和send的用法詳解,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過(guò)來(lái)看看吧2018-05-05nodejs實(shí)現(xiàn)范圍請(qǐng)求的實(shí)現(xiàn)代碼
這篇文章主要介紹了nodejs實(shí)現(xiàn)范圍請(qǐng)求的實(shí)現(xiàn)代碼,使服務(wù)器支持范圍請(qǐng)求,允許客戶端只請(qǐng)求文檔的一部分,非常具有實(shí)用價(jià)值,需要的朋友可以參考下2018-10-10node.js學(xué)習(xí)總結(jié)之調(diào)式代碼的方法
調(diào)式代碼很多時(shí)候類似于查案一樣,只是結(jié)果的重要程度不同,警察查案為的是人民安穩(wěn),而我們調(diào)式則是為了系統(tǒng)的安穩(wěn)。既然這樣我們就不要冤枉任何一段代碼和程序,以免他們受到不合理的懲罰。2014-06-06nodejs實(shí)現(xiàn)文件或文件夾上傳功能的代碼示例
在平常的工作中,經(jīng)常會(huì)遇到需要將本地項(xiàng)目文件同步到遠(yuǎn)端服務(wù)器的情況,所以每次遇到都需要考慮如何將文件上傳到服務(wù)器上,所以本文就給大家介紹一下nodejs實(shí)現(xiàn)文件或文件夾上傳功能,需要的朋友可以參考下2023-08-08Windows環(huán)境下npm install 報(bào)錯(cuò): operation not permitted, rename的解決
這篇文章主要介紹了Windows環(huán)境下npm install 報(bào)錯(cuò): operation not permitted, rename的解決方法,文中對(duì)解決的方法介紹的很詳細(xì),有需要的朋友們可以參考借鑒。2016-09-09