大家都知道,web端如果实现文件上传通常的做法是利用input 标签实现文件域,最近在用electron做了一个客户端,我发现在electron下可以使用nodejs的fs模块来实现上传,特此分享下
通常的做法:
<form id="frm" method="post" enctype="multipart/form-data" action="/upload.do"> <input type="file" name="files[]" id="file_input" /> </form>
下面是用electron做的一个测试页面,这个页面很简单,只有一个上传按钮:
<div class="uploadBtn" onclick="UploadUtil.test()" style="background:unset;margin-right: 30px; border: 1px solid #ddd;text-align:center;padding-right: 20px;"> 上传文件 </div><!-- 上传 -->
electron引用node模块,可以用window.Electron.require('模块名'),这里用到两个模块:fs和mime,用fs读取文件然后再封装成File对象再利用ajax上传,上传成功后会在控制台打印“上传成功”。
File对象是Blob对象进一步封装,具体介绍请点这里:https://developer.mozilla.org/en-US/docs/Web/API/File
以上是,File对象的构造方法,第一个就是我们要传进去的blob对象构成的数组,第二参数是文件名,第三个参数是指定Blob属性,因为第一个参数传的就是blob对象,因此可以忽略
读取文件主要用到fs的两个api: readFile 和 createReadStream,前者是读取一个完整的文件到内存中,后者是建立文件流的方式读取,如果要上传大附件用后面的方法比较好,关于这两个方法具体的介绍我就不详述了,毕竟官网的介绍已经很详细了
你可以点下面的链接看官方文档:https://nodejs.org/api/fs.html
关于ajax上传相信做web开发的同学已经很熟悉用法了,有的File对象就可以直接构造FormData。
var formdata = new FormData(); formdata.append('enctype', 'multipart/form-data') formdata.append('Filedata', file);
下面我贴出完整的代码,命名空间是个好东西,多用用,
var UploadUtil = { fs: window.Electron.require('fs'), mime: window.Electron.require('mime'), test: function(){ var path = "C:\\Users\\elvis\\Downloads\\404错误.log"; var uploadUri = "/upload.do"; this.readAndUpload(path, uploadUri); }, // 读取并上传文件 readAndUpload: function(path, uploadUri){ var _self=this; _self.getFileStats(path, function(err, stats){ if(err) return; // 读取文件 --begin var readStream = _self.fs.createReadStream(path); var blobParts; readStream.on('open', function(fd){ blobParts = new Array(); console.log("Read \'"+path+"\' open"); }); readStream.on('data', function(data){ var blob = new Blob([data], {type: stats.type}); blobParts.push(blob); }); readStream.on('end', function(){ console.log("Read \'"+path+"\' end"); ajaxUpload(blobParts, stats); }); readStream.on('close', function(){ console.log("Read \'"+path+"\' close"); }); readStream.on('error', function(err){ console.info('[!ERR!] Read \''+path+'\' failed!'); // 读取过程中出错了,清空数据 blobParts.splice(0, blobParts.length); }); // 读取文件 --end }); function ajaxUpload(blobParts, stats) { if(!blobParts || blobParts.length <= 0) return; var xhr = new XMLHttpRequest(); xhr.open("POST", uploadUri, true); // 封装file对象 var file = new File(blobParts, stats.name); file.path = stats.path; var formdata = new FormData(); formdata.append('enctype', 'multipart/form-data') formdata.append('Filedata', file); xhr.onload = function (evt) { console.log("上传完成"); } xhr.send(formdata); } }, // 读取文件信息 getFileStats:function(path, callback){ var _self=this; _self.fs.stat(path, function(err, stats){ if(typeof callback != 'function') return; if(err) callback(err); else{ var index = path.lastIndexOf('\\'); var len = path.length; var filename = index != -1? path.substring(index+1, len):path; var mimetype = _self.mime.lookup(path) callback(null, {size:stats.size, name:filename, path:path, type:mimetype}); } }); } };
点击上传按钮:打开调试控制台,文件已经成功上传了