我在Google Chrome Web Store
上发布了一个案例hahaOCR
,该扩展程序可以帮助用户识别出图片中的文字信息,并以文本形式显示,大家可以在chrome
网上应用商店中找到我发布的应用程序,如图所示:
图1 - hahaOCR
<br/>
该扩展程序支持用户通过文件上传按钮上传图片,请看演示效果:
图2 - 测试图片
<br/>
图3 - 测试效果
接下来,我们将在本文中详细讲解该案例所涉及的文件(图片)处理模块。
参考资料
1. FileReader概述
该对象允许Web
应用程序异步读取存储在用户计算机上的文件(或原始数据缓冲区)的内容,使用File
或Blob
对象指定要读取的文件或数据。其中File
对象可以是来自用户在一个<input/>
元素上选择文件后返回的FileList
对象,也可以是来自拖拽操作生成的DataTransfer
对象,还可以是来自一个HTMLCanvasElement
上执行 mozGetAsFile()
方法后返回的结果;Blob
对象表示一个不可变、原始数据的类文件对象,它的数据可以按文本或二进制的格式进行读取,也可以转换成 ReadableStream
来用于数据操作,Blob
表示的不一定是JavaScript
原生格式的数据,File
接口基于Blob
,继承了Blob
的功能并将其扩展使其支持用户系统上的文件。
2. FileReader属性
为了更加直观的解释FileReader
的三个属性,我们来看一段简单的代码:
<input type="file" id="file" onchange="readFile(this.files[0])">
window.readFile = (file) => {
console.log(file)
console.log(file.type)
var reader = new FileReader()
console.log(reader)
}
上述代码中,我们定义了一个文件上传按钮,我们只对用户上传的第一个文件进行处理,当用户完成上传操作之后,我们来看一下控制台输出的信息:
图4 - FileReader属性
我们在上述代码中指定了三个console
,第一个console
输出了用户所上传文件的相关信息;第二个console
输出了用户所上传文件的type
;第三个console
输出了FileReader
实例的相关信息,请看解释:
- FileReader.error(只读属性)
该属性表示在读取文件时发生的错误,图1中显示error
值为null
,表示在读取用户所上传文件时没有出错。
- FileReader.readyState(只读属性)
该属性表示FileReader
状态的数字,请看取值:
常量名 | 值 | 描述 |
---|---|---|
EMPTY | 0 | 还没有加载任何数据 |
LOADING | 1 | 数据正在被加载 |
DONE | 2 | 已完成全部的读取请求 |
图1中显示readyState
值为0
,因为我们并没有加载任何数据,尽管我们完成了图片的上传,但我们并没有指定任何方法来读取该图片文件。
- FileReader.result(只读属性)
该属性表示文件的内容,仅在读取操作完成之后才有效,数据的格式取决于使用哪个方法来启动读取操作,图1中result
值为null
,因为我们并没有指定读取当前所上传文件的方法,接下来,我们通过FileReader.readAsDataURL()
方法来读取一下该图片,请看代码:
window.readFile = (file) => {
var reader = new FileReader()
console.log(reader)
reader.readAsDataURL(file)
reader.onload = (res) => {
console.log(res)
}
}
请看控制台信息:
图5 - readAsDataURL方法
上述代码中,我们通过FileReader.readDataAsURL()
方法读取用户所上传的图片文件,当读取完成后,其result
属性中将包含一个data:URL
格式的Base64
字符串以表示所读取文件的内容,关于读取用户所上传文件的更多方法,请参考第三小节。
3. FileReader方法
接下来,我们来看一下FileReader
接口的几个方法:
方法 | 描述 |
---|---|
FileReader.abort() | 终止读取操作,在返回时,该属性的值为DONE |
FileReader.readAsArrayBuffer() | 开始读取指定的Blob 中的内容,一旦完成,result 属性中保存的是被读取文件的ArrayBuffer 数据对象 |
FileReader.readAsBinaryString() | 开始读取指定的Blob 中的内容,一旦完成,result 属性中将包含所读取文件的原始二进制数据 |
FileReader.readAsDataURL() | 开始读取指定的Blob 中的内容,一旦完成,result 属性中将包含一个data:URL 格式的Base64 字符串以表示所读取文件的内容 |
FileReader.readAsText() | 开始读取指定的Blob 中的内容,一旦完成,result 属性中将包含一个字符串以表示所读取的文件内容 |
如上表所示,对于不同的文件我们可以采取不同的方法来完成读取操作,接下来,我们通过FileReader.readAsText()
方法来读取一个文本,请看代码:
图6 - 文本内容
window.readFile = (file) => {
var reader = new FileReader()
console.log(reader)
reader.readAsText(file)
reader.onload = (res) => {
console.log(res)
}
}
请看演示效果:
图7 - readAsText方法
4. FileReader事件
我们继续来看FileReader
接口的几个事件处理方法:
方法 | 描述 |
---|---|
FileReader.onabort() | 处理abort 事件,该事件在读取操作被中断时触发 |
FileReader.onerror() | 处理error 事件,该事件在读取操作发生错误时触发 |
FileReader.onload | 处理load 事件,该事件在读取操作完成时触发 |
FileReader.onloadstart | 处理loadstart 事件,该事件在读取操作开始时触发 |
FileReader.onloadend | 处理loadend 事件,该事件在读取操作结束时(成功或失败)触发 |
FileReader.onprogress | 处理progress 事件,该事件在读取Blob 时触发 |
如上表所示,我们可以在用户上传文件的不同阶段指定不同的处理逻辑,请看代码:
<div class="example">
<div class="file-select">
<label for="avatar">Choose a profile picture:</label>
<input type="file"
id="avatar" name="avatar"
accept="image/png, image/jpeg">
</div>
<img src="" class="preview" height="200" alt="Image preview...">
<div class="event-log">
<label>Event log:</label>
<textarea readonly class="event-log-contents" rows="20" cols="50"></textarea>
</div>
</div>
上述代码中,我们定义了一个文件上传按钮,具体来说是图片上传按钮;接着我们还定义了一个<img/>
标签,其src
属性值为空;最后,我们定义了一个文本输入框,用来显示不同事件处理程序读取图片文件的相关信息。
const fileInput = document.querySelector('input[type="file"]');
const preview = document.querySelector('img.preview');
const eventLog = document.querySelector('.event-log-contents');
const reader = new FileReader();
function handleEvent(event) {
console.log(event)
eventLog.textContent = eventLog.textContent + `${event.type}: ${event.loaded} bytes transferred\n`;
if (event.type === "load") {
preview.src = reader.result;
}
}
function addListeners(reader) {
reader.addEventListener('loadstart', handleEvent);
reader.addEventListener('load', handleEvent);
reader.addEventListener('loadend', handleEvent);
reader.addEventListener('progress', handleEvent);
reader.addEventListener('error', handleEvent);
reader.addEventListener('abort', handleEvent);
}
function handleSelected(e) {
eventLog.textContent = '';
const selectedFile = fileInput.files[0];
if (selectedFile) {
addListeners(reader);
reader.readAsDataURL(selectedFile);
}
}
fileInput.addEventListener('change', handleSelected);
上述代码中,我们仅对用户上传的第一个图片文件进行处理(通过readAsDataURL
方法读取);我们还通过EventTarget.addEventListener
方法将FileReader
指定的6种监听器(事件处理程序)注册到reader
上;最后当触发load
事件时,将读取成功之后的内容,即data:URL
格式的Base64
字符串赋值给空<img/>
标签的src
属性,并最终显示在页面中,请看演示效果:
图8 - FileReader事件处理程序演示
5. 案例实战
最后,我们来看一下本文最开始提到的hahaOCR
案例中的文件处理模块,实现该逻辑功能的思路其实很简单:用户通过按钮或拖拽操作上传图片,上传成功之后调用接口将图片中的文字信息显示在<textarea/>
中,接下来,我们来看一下实现该功能的代码:
//此处是手动选择文件
$('#input').change(function() {
event.preventDefault();
var filesToUpload = document.getElementById('input').files;
var img_file = [];
for (var i = 0; i < filesToUpload.length; i++) {
var file = filesToUpload[i];
if (/image\/\w+/.test(file.type) && file != "undefined") {
img_file.push(file);
}
}
var reader = new FileReader();
var AllowImgFileSize = 2100000; //上传图片最大值(单位字节)( 2 M = 2097152 B )超过2M上传失败
var imgUrlBase64;
if (img_file) {
//将文件以Data URL形式读入页面
imgUrlBase64 = reader.readAsDataURL(file);
reader.onload = function (e) {
if (AllowImgFileSize != 0 && AllowImgFileSize < reader.result.length) {
alert( '上传失败,请上传不大于2M的图片!');
return;
}else{
$.ajax({
type: 'post',
url: '***', //这里是数据请求接口
dataType: 'json',
data: {
"showapi_appid": '***', //这里需要改成自己的appid
"showapi_sign": '***', //这里需要改成自己的应用的密钥secret
"base64":reader.result,
},
error: function(XmlHttpRequest, textStatus, errorThrown) {
alert("操作失败!");
},
success: function(result) {
var res = result.showapi_res_body.texts[0];
console.log(res)
$("#exampleFormControlTextarea1").val(res)
}
});
}
}
}
hahaOCR.prototype.getImageFile(img_file, filesToUpload.length);
});
上述代码中,我们限定了用户所上传图片文件的大小,并在文件上传成功时调用接口来对所上传的图片文件进行识别,识别成功之后,将图片中文字信息显示在<textarea/>
中。
6. 文章最后
以上就是本文的所有内容,小伙伴们学会了嘛?快去实践一下吧!更多详情请关注我的更多开源作品:
1. 微信公众号(hahaCoder)
图9 - 微信公众号
<br/>
2. 微信小程序(hahaAI)
图10 - 微信小程序
<br/>
3. Github
链接地址:https://github.com/TURBO1002