阅读(2169) (18)

JavaScript文件与目录操作技巧

2016-08-12 11:33:10 更新

JavaScript设置表单上传时文件个数的方法


这是一个比较实用的功能,用JavaScript来设置表单上传文件时,根据需要生成上传表单,要几个生成几个,在网易邮箱、新浪邮箱的添加附件功能里都有这种功能,不过这一款没有删除表单的功能,如果输入的多了,只好重新来过啦

运行效果如下图所示:


具体代码如下:

<title>JavaScript设置表单上传时的文件个数</title>
<input type="button" name="button" value="添加附件" onclick="addInput()">
<input type="button" name="button" value="删除附件" onclick="deleteInput()">
<span id="upload"></span>
<script type="text/javascript">
 var attachname = "attach";
 var i=1;
  function addInput(){
  if(i>0){
   var attach = attachname + i ;
   if(createInput(attach))
    i=i+1;
  }
  } 
  function deleteInput(){
   if(i>1){
   i=i-1;
   if(!removeInput())
    i=i+1;
   }
  } 
  function createInput(nm){ 
  var aElement=document.createElement("input"); 
  aElement.name=nm;
  aElement.id=nm;
  aElement.type="file";
  aElement.size="50";
  //aElement.value="thanks"; 
  //aElement.onclick=Function("asdf()"); 
   if(document.getElementById("upload").appendChild(aElement) == null)
    return false;
   return true;
  } 
  function removeInput(nm){
   var aElement = document.getElementById("upload");
   if(aElement.removeChild(aElement.lastChild) == null)
   return false;
   return true; 
  } 
</script>




JavaScript File API文件上传预览


对于基于浏览器的应用而言,访问本地文件都是一件头疼的事情,通常我们能做的仅仅是使用<input type="file">标签来上传文件。实现过程是:选取文件的时候value 属性保存了用户指定的文件的名称,表单被提交的时候,浏览器会向服务器发送选中的文件的内容而不仅仅是发送文件名。再获取服务器返回的地址,然后做预览。
  

但是如果有一天我们要上传一个图片,传了图片后预览想换另一张图片,就又得先上传到服务器再预览。在网络比较慢的情况下,这样真的很折腾。
  

所以我们某些时候需要先预览再上传到服务器,特别是一些有剪切功能的需求,例如新浪微博的头像更换。但是目前能做的只能是借助插件开发或者使用flash,由于不同浏览器的技术实现不尽相同,为了让程序能够支持多浏览器,我们的程序就会变得十分复杂而难于维护。幸好现在有了File API。
  

通过监听change事件我们可得知用户选择的文件,并且添加了一个files集合,集合中将包含file对象,每个file对象对应着一个文件。并且都有以下只读属性name,size,type,lastModifiedDate.
以<input type="file" name="file">为例,监控onchange事打印它的file对象:


由此我们可得知用户选取的文件格式,文件名以及文件大小等等的一些信息。因此我们很容易就能为所选取的文件作验证判断是否符合我们定的一些要求。

除此之外File API还提供了FileReader类型读取文件中的数据。


FileReader类型实现的事一种异步文件读取机制,类似于XMLHttpRequest,但是它读的是文件系统而不是远程服务器。并且提供了几种读取方法:

  • readAsText(file,encoding):以纯文本形式读取文件,将读取到的文本保存在result属性中,第二个参数用于指定编码类型,可选。
  • readAsDataURL(file):读取文件以数据URL的形式保存在result属性中。
  • readAsBinaryString(file):读取文件并将一个字符串保存在result属性中。
  • readAsArrayBuffer(file):读取文件并将一个包含文件人容的ArrayBuffer保存在result属性中

通过以上方法分别读取同一张本地图片,并且把保存在result属性中的信息打印出来对比如下:


readAsText(file,encoding):


readAsDataURL(file):
通过以上对比我们发现这些读取文件的方法为灵活的处理文件数据提供了极大的方便。例如读取图像文件并且保存为数据url,可以做上传前的预览功能。
  

由于读取的过程是异步的,所以FileReader里面有几个事件分别处理不同的情况:progress(是否读取了新数据)、erro(是否发生了错误)、load(是否已经读完了整个文件)。
  

由于种种原因无法读取文件就会触发error事件,触发error事件的时会有一个属性code(错误码)保存在FileReader的error属性里面的一个对象中。
使用FileReader做上传预览的例子:


HTML:

<label class="item_label">上传照片:
 <span style="width: 100px; height: 100px;border:1px solid #ccc; display:inline-block"><img src="#" id="uploadPreview" style="width: 100%; height: 100%;"></span>
 <input type="file" name="file" id="postFile" style="width:74px;">
 <span id="error_text" style="display: none;">提示</span>
</label>
  
JavaScript:

document.getElementById('postFile').onchange = function() {
 var val = this.value;
 var upLoadType = '.jpg,.gif,.bmp,.png';//['.jpg','.gif','.bmp','.png']; //可上传的格式
 var fileExt = val.substr(val.lastIndexOf(".")).toLowerCase(); //从字符串中抽出最后一次出现.之后的字符,并且转换成小写
 var result = upLoadType.indexOf(fileExt); //查找后缀名是否符合条件,如果符合返回>=0,如果不符合则返回负数;
 _alertMsg = $('#error_text');
 var oFReader = new FileReader();
 if (this.files.length === 0) { return; }
 var oFile = this.files[0]; //如果只有一个文件则只需要访问这个FileList对象中的第一个元素.
   
 if (oFile.size / 1024 < 100) {
  _alertMsg.html("<font style='color:blue'>√</font>").show()
 };
 if (result < 0) {
  _alertMsg.html("请输入正确格式:" + upLoadType).show();
 } else{
  _alertMsg.html("<font style='color:blue'>√</font>").show();
 };
  
 oFReader.readAsDataURL(oFile); // 开始在后台进行读取操作。当图像文件的所有内容加载后,他们转换成一个data:URL,传递到onload回调函数中
 oFReader.onload = function (oFREvent) { //当读取操作成功完成时调用.
  document.getElementById("uploadPreview").src = oFREvent.target.result;
 };
};


效果以及返回的图片URL:




JavaScript获取当前运行脚本文件所在目录的方法


代码如下:


DirectoryUtility = {
  // function getCurrentDirectory: returns currentDirectory path 
  // with a trailing backslash.
  getCurrentDirectory : function ( ) {
    var scriptFullName = WScript.ScriptFullName;
    var scriptName = WScript.ScriptName;
    return scriptFullName.substr ( 0, scriptFullName.lastIndexOf ( scriptName ) );
  }
}
/* 用法 */
DirectoryUtility.getCurrentDirectory ( );




Javascript中使用A标签获取当前目录的绝对路径方法


一谈到路径相关的问题,大家都会往window.location上想,确实这个对象提供了相当多的路径信息,其中常用的就包括:

1.location.href:当前页面的完整URL
2.location.pathname:当前URL中的路径名
3.location.hash:当前URL中的锚点
4.location.search:当前URL中的查询参数

然而,location没有一个属性能直接获得当前目录(不含文件名)的绝对路径。通过Google我发现了一些错误的方法,比如说把URL通过“/”分离成数组,把数组的最后一项去掉以后再连接成字符串。但如果URL中没有指定文件名,结果就大错特错了。

根据以往编码的经验,a元素的href属性总是会返回绝对路径,也就是说它具有把相对路径转成绝对路径的能力。使用下面的代码尝试了一下,果然成了:


代码如下:

var a = document.createElement('a');
a.href = './';
alert(a.href);
a = null;

很不幸地,此方法在老旧的IE 6/7下无效,当执行alert(a.href)时,弹出的仍然是“./”。后来,我发现在Stackoverflow上也有人提出了这个问题,而解决方法也是很简单的,只要把a通过innerHTML注入就可以了:

代码如下:

var div = document.createElement('div');
div.innerHTML = '<a href="./"></a>";
alert(div.firstChild.href);
div = null;



javascript获取web应用根目录的方法

代码如下:

<script> 
function getRootPath(){ 
var strFullPath=window.document.location.href; 
var strPath=window.document.location.pathname; 
var pos=strFullPath.indexOf(strPath); 
var prePath=strFullPath.substring(0,pos); 
var postPath=strPath.substring(0,strPath.substr(1).indexOf(‘/')+1); 
return(prePath+postPath); 

var webpath=getRootPath(); //webpath就是目录路径变量 
</script> 



JavaScript获取当前运行脚本文件所在目录的方法

代码如下:

DirectoryUtility = {
  // function getCurrentDirectory: returns currentDirectory path 
  // with a trailing backslash.
  getCurrentDirectory : function ( ) {
    var scriptFullName = WScript.ScriptFullName;
    var scriptName = WScript.ScriptName;
    return scriptFullName.substr ( 0, scriptFullName.lastIndexOf ( scriptName ) );
  }
}
/* 用法 */
DirectoryUtility.getCurrentDirectory ( );