本文实例讲述了node.js express框架实现文件上传与下载功能。分享给大家供大家参考,具体如下:
背景
昨天吉视传媒的客户对IPS信息发布系统又提了一个新需求,就是发布端发送消息时需要支持附件的上传,而接收端可以对发布端上传的附件进行下载;接收端回复消息时也需要支持上传附件,发布端可以对所有接收端上传的附件进行打包下载。
功能实现
前台使用webUploader插件即可,这是百度开发的一款文件上传组件,具体使用查看它的API即可。这个项目之前开发的时候前台使用了angular.js。
$scope.fileName = ""; //创建上传附件的对象 var $list = $("#thelist"); var uploader = WebUploader.create({ // 选完文件后,是否自动上传。 auto: false, // swf文件路径 swf: '../../../lib/webUploader/Uploader.swf', // 文件接收服务端。 server: '/publishUploadFile', // 内部根据当前运行是创建,可能是input元素,也可能是flash. pick : { id : '#filePicker', //只能选择一个文件上传 multiple: false }, // pick :'#filePicker', method: 'POST', }); uploader.on('fileQueued', function (file) { $scope.fileName = file.name; $list.html(""); $list.html(file.name); });
当用户选择文件的时候我创建了文件上传的对象,而在用户真正发送消息的时候我添加了相应的参数并将附件真正的上传上去,符合我这个项目的业务逻辑。
if($scope.fileName){ //添加参数 uploader.options.formData.fileId = fileId; uploader.options.formData.fileName = $scope.fileName; uploader.upload(); }
路由就不详细说明了,主要注意的是下载的接口我都是使用的get请求,这样前台在请求的时候直接新打开一个窗口拼接了相应的参数就能下载文件了。下面贴一下action层的代码:
//发布端上传附件 exports.publishUploadFile = function (req, res) { messageMng.publishUploadFile(req, function (err, datas) { res.json(datas); }); }; //下载发布端上传的附件 exports.exportPublishFile = function (req, res) { messageMng.exportPublishFile(req, function (err, datas) { if (err) { res.set({ "Content-Disposition": "attachment;filename=" + encodeURI("error.txt") }); res.write(err.message); res.end(); } else { res.download(datas.path, encodeURI(datas.name)); } }); }; //接收端上传附件 exports.uploadFile = function (req, res) { messageMng.uploadFile(req, function (err, datas) { res.json(datas); }); }; //发布端导出附件 exports.exportFile = function (req, res) { messageMng.exportFile(req, function (err, datas) { if (err) { res.set({ "Content-Disposition": "attachment;filename=" + encodeURI("error.txt") }); res.write(err.message); res.end(); } else { //第一种方式 下载完的zip解压报错 // res.download(datas.path, datas.name + ".zip"); //第二种方式 // var path="D:/maven介绍.ppt"; var f = fs.createReadStream(datas.path); res.writeHead(200, { 'Content-Type': 'application/force-download', 'Content-Disposition': 'attachment; filename='+ encodeURI(datas.name) + '.zip' }); f.pipe(res); } }); };
这里着重说一下下载zip时使用download下载完的压缩包解压会报错,使用第二种方法完美解决。
然后是service层的代码:
/** * 发布端上传附件 * @param req * @param fn */ MessageManager.prototype.publishUploadFile = function (req, fn) { try { //消息ID var fileId = req.body.fileId; var file = req.file; //文件上传的目录 var uploadFolder = path.join(__dirname, '../../upload/publishUploadFile/' + fileId); //判断文件夹是否存在 不存在则创建 toolUtil.mkdirSync(uploadFolder); //将上传的文件从临时目录拷贝到指定的目录下 var fileReadStream = fs.createReadStream(file.path); var fileWriteStream = fs.createWriteStream(uploadFolder + "/" + file.originalname); fileReadStream.pipe(fileWriteStream); fileWriteStream.on('close', function () { // 删除临时目录下面的文件 toolUtil.emptyDir(file.destination); }); fn(null, {"data": "", "message": "上传成功", "error_code": 200}); } catch (e) { fn(e, {"data": "", "message": "上传失败", "error_code": e.message}); } }; /** * 下载发布端上传的附件 * @param req * @param fn */ MessageManager.prototype.exportPublishFile = function (req, fn) { try { //附件ID var id = req.query.id; //附件名称或标题 var name = req.query.name; if (id && name) { //名称过长的话,截取前25个字符 if (name.length > 25) { name = name.substr(0, 24); } //将要压缩得文件夹路径 var filePath = path.join(__dirname, '../../upload/publishUploadFile/' + id + '/' + name); if (!fs.existsSync(filePath)) { fn(new Error("没有附件!"), null); } else { fn(null, {"name": name, "path": filePath}); } } else { fn(new Error("id或name不能为空"), null); } } catch (e) { fn(new Error(e.message), null); } }; /** * 接收端上传附件 * @param req * @param fn */ MessageManager.prototype.uploadFile = function (req, fn) { try { //消息ID var msgId = req.body.msgId; //消息发送的时间 var msgSendTime = req.body.msgSendTime.slice(0, 10); //消息的标题 var title = req.body.title; var replyId = req.body.replyId; var replyName = req.body.replyName; var file = req.file; //文件上传的目录 var uploadFolder = path.join(__dirname, '../../upload/messages/' + msgId + '/' + replyName); //判断文件夹是否存在 不存在则创建 toolUtil.mkdirSync(uploadFolder); //组装文件的名称 原名称+消息发送时间 var index = file.originalname.lastIndexOf("."); var fileName = file.originalname.substr(0, index) + '-' + msgSendTime + ""; var suffix = file.originalname.substr(index, file.originalname.length - 1); //将上传的文件从临时目录拷贝到指定的目录下 var fileReadStream = fs.createReadStream(file.path); var fileWriteStream = fs.createWriteStream(uploadFolder + "/" + fileName + "." + suffix); fileReadStream.pipe(fileWriteStream); fileWriteStream.on('close', function () { //删除临时目录下面的文件 toolUtil.emptyDir(file.destination); }); fn(null, {"data": "", "message": "上传成功", "error_code": 200}); } catch (e) { fn(e, {"data": "", "message": "上传失败", "error_code": e.message}); } }; /** * 导出消息的附件文件 * @param req * @param fn */ MessageManager.prototype.exportFile = function (req, fn) { try { //消息ID var id = req.query.id; //消息名称或标题 var name = req.query.name; if (id && name) { //名称过长的话,截取前25个字符 if (name.length > 25) { name = name.substr(0, 24); } //将要压缩得文件夹路径 var messagePath = path.join(__dirname, '../../upload/messages/' + id); if (!fs.existsSync(messagePath)) { fn(new Error("没有附件!"), null); } else { //生成得临时zip文件目录 var zipPath = path.join(__dirname, '../../upload/temp.zip'); var archive = archiver('zip', { // Sets the compression level. zlib: {level: 9} }); //创建临时zip文件 var output = fs.createWriteStream(zipPath); archive.pipe(output); //设置需要压缩得文件夹目录 以及替换得名称 archive.directory(messagePath, name); archive.finalize(); archive.on('end', function (err) { fn(null, {"name": name, "path": zipPath}); }); archive.on('error', function (err) { fn(new Error("压缩文件异常"), null); }); } } else { fn(new Error("id或name不能为空"), null); } } catch (e) { fn(new Error(e.message), null); } };
最后是提出的公共方法toolUtil的代码,这个单独做为一个js文件维护。
const path = require('path'); const fs = require('fs'); /** * 创建目录 * @param dirpath */ exports.mkdirSync = function (dirpath){ if (!fs.existsSync(dirpath)) { var pathtmp; dirpath.split(path.sep).forEach(function(dirname) { if (pathtmp) { pathtmp = path.join(pathtmp, dirname); } else { pathtmp = dirname; } if (!fs.existsSync(pathtmp)) { fs.mkdirSync(pathtmp); } }); } }; //删除所有的文件(将所有文件夹置空) exports.emptyDir = function(dirpath){ var self = this; //读取该文件夹 var files = fs.readdirSync(dirpath); files.forEach(function(file){ var filePath = dirpath + '/' + file; var stats = fs.statSync(filePath); if(stats.isDirectory()){ self.emptyDir(filePath); }else{ fs.unlinkSync(filePath); } }); };
希望本文所述对大家node.js程序设计有所帮助。
本文向大家介绍JavaWeb实现文件上传下载功能实例详解,包括了JavaWeb实现文件上传下载功能实例详解的使用技巧和注意事项,需要的朋友参考一下 在Web应用系统开发中,文件上传和下载功能是非常常用的功能,今天来讲一下JavaWeb中的文件上传和下载功能的实现。 文件上传概述 1、文件上传的作用 例如网络硬盘!就是用来上传下载文件的。 在智联招聘上填写一个完整的简历还需要上传照片呢。 2、文件上
本文向大家介绍C#实现文件上传与下载功能实例,包括了C#实现文件上传与下载功能实例的使用技巧和注意事项,需要的朋友参考一下 最近学习了 C#实现文件上传与下载,现在分享给大家。 1、C#文件上传 创建MyUpload.htm页面,用于测试 创建UploadFile.aspx文件,在UploadFile.aspx.cs键入如下代码: 2 、C#文件下载 创建DownloadFile.aspx,在Do
本文向大家介绍java Struts2框架下实现文件上传功能,包括了java Struts2框架下实现文件上传功能的使用技巧和注意事项,需要的朋友参考一下 本文实例为大家分享了Struts2框架实现文件上传的方法,供大家参考,具体内容如下 struts2的配置过程 (1)在项目中加入jar包 (2)web.xml中filter(过滤器)的配置 (3)struts.xml配置文件的编写
本文向大家介绍JavaWeb实现文件上传与下载实例详解,包括了JavaWeb实现文件上传与下载实例详解的使用技巧和注意事项,需要的朋友参考一下 在Web应用程序开发中,文件上传与下载功能是非常常用的功能,下面通过本文给大家介绍JavaWeb实现文件上传与下载实例详解。 对于文件上传,浏览器在上传的过程中是将文件以流的形式提交到服务器端的,如果直接使用Servlet获取上传文件的输入流然后再解析里
本文向大家介绍javaweb实现文件上传与下载功能,包括了javaweb实现文件上传与下载功能的使用技巧和注意事项,需要的朋友参考一下 本文实例为大家分享了javaweb文件的上传与下载,供大家参考,具体内容如下 一、文件上传 要实现Web开发的上传功能,通常需要完成两步操作:一是在Web页面中添加上传输入项;二是在Servlet中读取上传文件的数据,并保存到本地硬盘中。 上传大多数情况是通过表单
本文向大家介绍Spring框架实现文件上传功能,包括了Spring框架实现文件上传功能的使用技巧和注意事项,需要的朋友参考一下 在Java中实现文件的上传有多种方式,如smartUpload或是使用Strus2,本文与大家分享使用Spring框架中的MultipartFile类来实例文件的上传。 不啰嗦了,直接上干货。先是编写了一个实现文件上传的类FileUploadingUtil,此类中定义了两
本文向大家介绍FasfDFS整合Java实现文件上传下载功能实例详解,包括了FasfDFS整合Java实现文件上传下载功能实例详解的使用技巧和注意事项,需要的朋友参考一下 在上篇文章给大家介绍了FastDFS安装和配置整合Nginx-1.13.3的方法,大家可以点击查看下。 今天使用Java代码实现文件的上传和下载。对此作者提供了Java API支持,下载fastdfs-client-java将源
本文向大家介绍spring mvc实现文件上传与下载功能,包括了spring mvc实现文件上传与下载功能的使用技巧和注意事项,需要的朋友参考一下 本文实例为大家分享了spring mvc实现文件上传与下载功能的具体代码,供大家参考,具体内容如下 文件上传 在pom.xml中引入spring mvc以及commons-fileupload的相关jar 在springmvc.xml中加入文件上传的相