Node.js后端文件上传、文件接收保存及文件下载实现

直接给下Node.js后端两种文件上传方式、后端服务接收保存文件,以及后端文件下载的具体代码实现。​


一、Node.js后端文件上传

这边注意下,如果出现以下错误

Error: socket hang up

检查下上传的后端接口是不是用https,之后修改下引入的http对象为
https


1)使用FormData上传文件

var FormData = require('form-data')
//如果后端用的是https,这边引入的是http就会报socket hang up异常。
var http = require('https');
//调用示例:
let form = new FormData();
var uploadLoadFilePath = "../../test.zip"
form.append("filename", fs.createReadStream(uploadLoadFilePath))
uploadRequest("test.cn", "8080" '/api/upload/file', form, 'POST').then(function (result) {
}).catch(function (err) {
})

/**
 * 上传文件或者请求数据都可以用这个方法处理
 */
function uploadRequest(host, port, path, body, method){
  return new Promise(function (resolve, reject) {
    var option = {
      hostname: host,
      port: port,
      path: path,
      method: method ? method : 'GET',
      headers: {}
    };
    var data = null;
    if (body) {
      if (body instanceof FormData) {
        option.method = 'POST';
        option.headers = body.getHeaders()
        data = body
      } else {
        if (typeof(body) == 'string') {
          data = body
        } else {
          data = JSON.stringify(body)
        }
        option.method = 'POST';
        option.headers["Content-Length"] = Buffer.byteLength(data, 'utf8');
        option.headers["Content-Type"] = 'application/json';
      }
    }
    if (method) {
      option.method = method;
    }
    var req = http.request(option, function (res) {
      var body = '';
      res.on('data', function (chunk) {
        body += chunk;
      });
      res.on('end', function () {
        console.log("coverage coverageRequest request body:%s", body)
        resolve(JSON.parse(body));
      })
    });
    req.on('error', function (e) {
      console.log("coverage coverageRequest request error:%s", e)
      reject(e)
    });
    if (data instanceof FormData) {
      data.pipe(req)
    } else {
      if (data != null) {
        req.write(data);
      }
      req.end();
    }
  });
}


2)自定义boundary参数上传文件

// 示例调用
let body = {
"testType": testType,
"flag": 'full_test'
}
var savePath = "../../test.zip"
uploadFiles("test.cn", '/api/upload/file', "8080",
[{urlKey: 'testData', urlValue: JSON.stringify(body)}],
[{urlKey: 'file', urlValue: savePath}]).then(function (result) {
console.log("uploadFile result:%s", result)
}).catch(function (err) {
console.log("uploadFile err:%s", err)
})
/**
* 文件上传
*/
function uploadFiles(host, path, port, fileDataInfo, fileKeyValue) {
var options = {
hostname: host,
port: port?port:80,
path: path,
method: 'POST'
}
return new Promise(function(resolve, reject) {
var req = http.request(options, function(res) {
var data = ''
res.on("data", function(chunk) {
data += chunk;
})
res.on('end', () => {
try{
resolve(data)
}catch (err){
reject(err)
}
})
}).on("error", function (err) {
reject(err)
})
var boundaryKey = Math.random().toString(16);
var enddata = '\r\n----' + boundaryKey + '--';
var dataLength = 0;
var dataArr = new Array();
for (var i = 0; i < fileDataInfo.length; i++) {
var dataInfo = "\r\n----" + boundaryKey + "\r\n" + "Content-Disposition: form-data; name=\"" + fileDataInfo[i].urlKey + "\"\r\n\r\n" + fileDataInfo[i].urlValue;
var dataBinary = new Buffer(dataInfo, "utf-8");
dataLength += dataBinary.length;
dataArr.push({
dataInfo: dataInfo
});
}
var files = new Array();
for (var i = 0; i < fileKeyValue.length; i++) {
var content = "\r\n----" + boundaryKey + "\r\n" + "Content-Type: application/octet-stream\r\n" + "Content-Disposition: form-data; name=\"" + fileKeyValue[i].urlKey + "\"; filename=\"" + pathUtil.basename(fileKeyValue[i].urlValue) + "\"\r\n" + "Content-Transfer-Encoding: binary\r\n\r\n";
var contentBinary = new Buffer(content, 'utf-8');
files.push({
contentBinary: contentBinary,
filePath: fileKeyValue[i].urlValue
});
}
var contentLength = 0;
for (var i = 0; i < files.length; i++) {
var filePath = files[i].filePath;
if (fs.existsSync(filePath)) {
var stat = fs.statSync(filePath);
contentLength += stat.size;
} else {
contentLength += new Buffer("\r\n", 'utf-8').length;
}
contentLength += files[i].contentBinary.length;
}
req.setHeader('Content-Type', 'multipart/form-data; boundary=--' + boundaryKey);
req.setHeader('Content-Length', dataLength + contentLength + Buffer.byteLength(enddata));
// 将参数发出
for (var i = 0; i < dataArr.length; i++) {
req.write(dataArr[i].dataInfo)
//req.write('\r\n')
}
var fileindex = 0;
var doOneFile = function() {
req.write(files[fileindex].contentBinary);
var currentFilePath = files[fileindex].filePath;
if (fs.existsSync(currentFilePath)) {
var fileStream = fs.createReadStream(currentFilePath, {bufferSize: 4 * 1024});
fileStream.pipe(req, {end: false});
fileStream.on('end', function() {
fileindex++;
if (fileindex == files.length) {
req.end(enddata);
} else {
doOneFile();
}
});
} else {
req.write("\r\n");
fileindex++;
if (fileindex == files.length) {
req.end(enddata);
} else {
doOneFile();
}
}
};
if (fileindex == files.length) {
req.end(enddata);
} else {
doOneFile();
}
})
}


二、Node.js后端文件接收及保存

这边用formidable来解析获取文件名和服务端保存的文件路径。

var formidable = require('formidable')
var Promise = require('bluebird')
app.post('/api/upload/file', function (req, res) {
var form = new formidable.IncomingForm()
if (options.saveDir) {
form.uploadDir = options.saveDir
}
Promise.promisify(form.parse, form)(req)
.spread(function(fields, files) {
return Object.keys(files).map(function(field) {
var file = files[field]
//file.name字段获取文件名,file.path字段获取服务端保存的文件路径,这边可以把文件移动存储到你想要的位置
console.log(">>>>>>>fileName:%s, filePath:%s", file.name, file.path);
})
}).catch(function(err) {
res.status(500)
.json({
success: false
, error: 'ServerError'
})
})
});


三、Node.js后端文件下载

//示例调用
donwloadFile("test.cn", "80", "/test/test.zip", "/User/Download/temp/test.zip")
function downloadFile(host, port, path, downloadPath) {
  var writeStream = fs.createWriteStream(downloadPath);
  var option = {
    hostname: host,
    port: port,
    method: 'GET',
    path: path
  }
  var req = http.request(option, function (res) {
    if (res.statusCode == 200) {
      res.pipe(writeStream);
      res.on('data', (chunk) => {
      });
      res.on("end", function () {
      });
    } else {
    }
  });
  req.on("error", function (err) {
  });
  req.end();
}

如果后端服务用的是https,在做文件下载操作的时候端口用80就会报如下异常:

error:write EPROTO 140036986775360:error:140770FC:SSL routines:SSL23_GET_SERVER_HELLO:
unknown protocol:../deps/openssl/openssl/ssl/s23_clnt.c:827:

此时端口要改为443,即:

donwloadFile("test.cn", "443", "/test/test.zip", "/User/Download/temp/test.zip")

扩展阅读:


Node.js后端zip压缩文件保存和读取


JavaScript前后端JSON使用方法详解


转载请注明出处:陈文管的博客–  Node.js后端文件上传、文件接收保存及文件下载实现

扫码或搜索:
文呓

微信公众号 
扫一扫关注

陈文管的博客
我还没有学会写个人说明!
上一篇

口碑已炸!三大影帝飙戏,别再说港片没救

你也可能喜欢

评论已经被关闭。

插入图片