Code Copied

js读取本地文件(支持中文)

1. 需求说明

在一些Web Page中,复杂的表单输入用户会觉得很繁琐,而用户输入的数据来源往往来源于其本地存储的一些文件,而不是从大脑中凭空创造出来的。
那么问题就来了:能否提供一个方式,让Web Page直接读取本地存储的文件,然后根据一定规则将文件内容填充到Web Page的表单中呢?

根据问题的内容可以得出以下2点功能要求:

  • Web Page能够从本地读取文件
  • 文件不需要上传到服务器(Ajax文件上传并显示数据不符合该要求)

下面我们将进行一些试验来实现该功能。

2. 文件准备

准备一个文本文件,文件内容如下,包含数字、字母、特殊字符和汉字。

SNAGHTMLff4f6c

试验方式:读取该文件的内容,并以alert()的方式输出到页面。

3. ActiveXObject读取本地文件

查找了一些js对象,发现在HTML 4下只有ActiveXObject能够做这样的操作,代码如下:

<html>
	<meta charset="UTF-8">
	<head>
		<script type="text/javascript">
			function ReadLocalFile()
			{
				// 从File控件里面读取文件路径
				var url= document.getElementById('local_file').value;
				 
				 
				// 声明一个 FileSystemObject 的实例
				var fileSysObj = new ActiveXObject("Scripting.FileSystemObject");
				 
				// 声明一个 textStream 对象 用来打开文件
				var inputTextStream = fileSysObj.OpenTextFile(url,1,true);
				 
				var str = "";
				while(!inputTextStream.AtEndOfStream)
				{
			       str += inputTextStream.ReadLine() + "\r\n";
				}
				alert(str);
				 
				//关闭文件流
				inputTextStream.Close();
			 
			}
		</script>
	</head>
	<body>
		<form method="post" action="">
			<input type="file" id="local_file" name="local_file"/>
			<input type="button" value="读取文件���容" onclick="ReadLocalFile()">
		</form>
	</body>
</html>

测试1:在1台拥有管理员权限的机器上,使用IE 11进行测试,测试结果OK。

image

在点击Yes按钮后,可以正常读取到文件。

image

测试2:在1台拥有非管理员权限的机器上,使用IE 11进行测试,测试结果NG。

image

由于ActiveXObject只在IE上才有效,所以其他浏览器就不需要再测试了。

经过上面的测试,这种方式显然不符合我们的要求,ActiveXObject读取本地文件有以下几个缺点:

  • 只能支持IE浏览器ActiveXObject
  • 每次运行还需要用户进行一次额外的确认操作
  • 必须拥有系统管理员权限才能读取到文件

4. HTML 5读取本地文件

虽然ActiveXObject不行,但是我你们有HTML 5,它提供了FileReader对象,FileReader对象提供了一些方法可以将本地文件读取到内存中。

方法名 参数 描述
abort none 中断读取
readAsBinaryString file 将文件读取为二进制码
readAsDataURL file 将文件读取为 DataURL
readAsText file, [encoding] 将文件读取为文本

readAsText:该方法有两个参数,其中第二个参数是文本的编码方式,默认值为 UTF-8。这个方法非常容易理解,将文件以文本方式读取,读取的结果即是这个文本文件中的内容。
readAsBinaryString:该方法将文件读取为二进制字符串,通常我们将它传送到后端,后端可以通过这段字符串存储文件。
readAsDataURL:这是例子程序中用到的方法,该方法将文件读取为一段以 data: 开头的字符串,这段字符串的实质就是 Data URL,Data URL是一种将小文件直接嵌入文档的方案。这里的小文件通常是指图像与 html 等格式的文件。

下面的代码使用FileReader的readAsDataURL方法读取本地文件:

<!DOCTYPE html>
<html>
<head>
    <title></title>
    <script type="text/javascript" src="jquery-1.10.2.min.js"></script>
    <script type="text/javascript" src="base64.js"></script>
    <script type="text/javascript">
        /*
         * @description: read local text file via the html5 FileReader
         **/

        function getFileContent(fileInput, callback) {
            if (fileInput.files && fileInput.files.length > 0 && fileInput.files[0].size > 0) {
                var file = fileInput.files[0];
                if (window.FileReader) {
                    var reader = new FileReader();

                    reader.onloadend = function(evt) {
                        if (evt.target.readyState == FileReader.DONE) {

                            callback(evt.target.result.split(',')[1]);
                        }
                    }

                    reader.readAsDataURL(file);
                }
            }
        }



        $(function() {
            $('#b1').click(function() {
                // please do not use $('f1') to get the file dom element, otherwise, you'll get a js error.
                getFileContent(document.getElementById('f1'), function(str) {

                    alert(decode64(str));
                });
            });
        });
    </script>
</head>
<body>
    <input type="file" id="f1" />
    <input type="button" id="b1" value="read" />
</body>
</html>

使用readAsDataURL方法读取文件时,文件的内容被转成Base64编码的格式,所以在读完内容后我们还需要再进行一次Base64解码。

IE 11下的测试:

image

Chrome 37下的测试:

SNAGHTML11b11c1

注意:这个例子用于读取文件的文本内容,我们用FileReader的readAsText()方法会更直接一些,不需要做decode处理。当使用readAsDataURL()方法读取中文文字后,再进行decode处理可能会造成乱码,本文提供的js解决了这个问题。

5. 总结和下载

  • ActiveXObject只能在拥有管理员权限的PC下读取本地文件。
  • FileReader读取本地文件时需要进行Base64解码,并且需要浏览器支持HTML 5。
  • 实现开篇需求建议使用HTML 5的FileReader对象。

源代码下载链接:http://blog.64cm.com/source/Html5/read_local_file.zip