爆裂战士 發表於 2019-8-8 15:51:00

HTML5之fileReader异步读取文件及文件切片读取

<ul style="color: rgba(220, 20, 60, 1); font-size: 13px">
<li>fileReader的方法与事件</li>
<li>fileReade实现图片预加载</li>
<li>fileReade实现文件读取进度条</li>
<li>fileReade的与file.s实现文件切片读取</li>
</ul>
<h2 style="background-color: rgba(220, 20, 60, 1); border-radius: 5px">&nbsp;一、fileReader的方法与事件</h2>
<h4 style="color: rgba(220, 20, 60, 1)">1.方法</h4>
<ul style="color: rgba(51, 0, 0, 1)">
<li>FileReader.abort():终止读取操作。返回时,readyState属性为DONE。</li>
<li>FileReader.readAsArrayBuffer():将文件读取为ArrayBuffer数据对象。</li>
<li>FileReader.readAsBinaryString():将文件读取为二进制数据。</li>
<li>FileReader.readAsDataURL():将文件读取为DataURL编码(base64)==&gt;URL格式的字符串。</li>
<li>FileReader.readAsText():将文件读取为文本==》字符串表示的文件内容。</li>
</ul>
<h4 style="color: rgba(220, 20, 60, 1)">2.事件</h4>
<ul style="color: rgba(51, 0, 0, 1)">
<li>FileReader.onloadstart:读取开始时触发</li>
<li>FileReader.onprogress:读取中</li>
<li>FileReader.onloadend:读取完成触发,无论成功或失败</li>
<li>FileReader.onload:文件读取成功完成时触发</li>
<li>FileReader.onabort:中断时触发</li>
<li>FileReader.onerror:出错时触发</li>
</ul>
<h4 style="color: rgba(220, 20, 60, 1)">3.实现图片读取预览</h4>
<p>在Web FileReader API接口实现之前,图片预览的通常做法是先将图片上传至服务器,上传成功以后通过过触发ajax请求到刚刚上传的图片,然后加载到页面。这个过程中如果图片选择错误或者需要修改上传的图片,就需要重复上传和下载请求,并且还需要在服务器替换图片资源,会浪费大量的网络资源和服务器资源。现在通过FileReader实现本地图片读取预览,就可以在本地实现图片修改,节省服务器资源。</p>
<p>既然是HTML5的API就目前来说肯定存在兼容性问题,目前IE10开始支持FileReader,所以通过服务上传下载的图片预览方式还是有必要的,接下来的示例仅仅展示FileReader的图片读取预览代码:</p>
<div class="cnblogs_code">
<pre><span style="color: rgba(0, 128, 128, 1)"> 1</span> &lt;style&gt;
<span style="color: rgba(0, 128, 128, 1)"> 2</span> <span style="color: rgba(0, 0, 0, 1)">    .imgBox{
</span><span style="color: rgba(0, 128, 128, 1)"> 3</span> <span style="color: rgba(0, 0, 0, 1)">      display: flex;
</span><span style="color: rgba(0, 128, 128, 1)"> 4</span> <span style="color: rgba(0, 0, 0, 1)">      width: 300px;
</span><span style="color: rgba(0, 128, 128, 1)"> 5</span> <span style="color: rgba(0, 0, 0, 1)">      height: 300px;
</span><span style="color: rgba(0, 128, 128, 1)"> 6</span>         border: 1px solid #300<span style="color: rgba(0, 0, 0, 1)">;
</span><span style="color: rgba(0, 128, 128, 1)"> 7</span>         justify-<span style="color: rgba(0, 0, 0, 1)">content: center;
</span><span style="color: rgba(0, 128, 128, 1)"> 8</span>         align-<span style="color: rgba(0, 0, 0, 1)">items: center;
</span><span style="color: rgba(0, 128, 128, 1)"> 9</span> <span style="color: rgba(0, 0, 0, 1)">    }
</span><span style="color: rgba(0, 128, 128, 1)">10</span> &lt;/style&gt;
<span style="color: rgba(0, 128, 128, 1)">11</span> &lt;input type="file" name=""&gt;
<span style="color: rgba(0, 128, 128, 1)">12</span> &lt;div class="imgBox"&gt;&lt;/div&gt;
<span style="color: rgba(0, 128, 128, 1)">13</span> &lt;script&gt;
<span style="color: rgba(0, 128, 128, 1)">14</span>   <span style="color: rgba(0, 0, 255, 1)">var</span> imgBox = document.getElementsByClassName('imgBox');
</span><span style="color: rgba(0, 128, 128, 1)">15</span>   <span style="color: rgba(0, 0, 255, 1)">var</span> reader = <span style="color: rgba(0, 0, 255, 1)">new</span> FileReader(); <span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">创建文件读取对象</span>
<span style="color: rgba(0, 128, 128, 1)">16</span>   <span style="color: rgba(0, 0, 255, 1)">var</span> inp = document.getElementsByTagName('input'); <span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">获取文件源</span>
<span style="color: rgba(0, 128, 128, 1)">17</span>   inp.onchange = <span style="color: rgba(0, 0, 255, 1)">function</span>(){ <span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">input域发生改变后触发文件读取</span>
<span style="color: rgba(0, 128, 128, 1)">18</span>         reader.readAsDataURL(inp.files); <span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">使用文件读取对象读取图片为base64编码</span>
<span style="color: rgba(0, 128, 128, 1)">19</span> <span style="color: rgba(0, 0, 0, 1)">    }
</span><span style="color: rgba(0, 128, 128, 1)">20</span>   reader.onload = <span style="color: rgba(0, 0, 255, 1)">function</span>(e){ <span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">当图片读取成功后触发</span>
<span style="color: rgba(0, 128, 128, 1)">21</span>         <span style="color: rgba(0, 0, 255, 1)">var</span> img = <span style="color: rgba(0, 0, 255, 1)">new</span> Image(); <span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">创建img对象</span>
<span style="color: rgba(0, 128, 128, 1)">22</span>         img.src = e.target.result; <span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">给img对象添加缓存中的bese64位编码的图片数据(异步)</span>
<span style="color: rgba(0, 128, 128, 1)">23</span>         img.onload = <span style="color: rgba(0, 0, 255, 1)">function</span>(e){ <span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">图片数据加载完成以后</span>
<span style="color: rgba(0, 128, 128, 1)">24</span>             <span style="color: rgba(0, 0, 255, 1)">if</span>(<span style="color: rgba(0, 0, 255, 1)">this</span>.width &gt; <span style="color: rgba(0, 0, 255, 1)">this</span>.height){ <span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">当图片的宽度大于高度</span>
<span style="color: rgba(0, 128, 128, 1)">25</span>               img.style.width = '100%'; <span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">是:设置图片宽度100%,实现图片全部预览</span>
<span style="color: rgba(0, 128, 128, 1)">26</span>             }<span style="color: rgba(0, 0, 255, 1)">else</span><span style="color: rgba(0, 0, 0, 1)">{
</span><span style="color: rgba(0, 128, 128, 1)">27</span>               img.style.height = '100%';<span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">否:设置图片高度100%,实现图片全部预览</span>
<span style="color: rgba(0, 128, 128, 1)">28</span> <span style="color: rgba(0, 0, 0, 1)">            }
</span><span style="color: rgba(0, 128, 128, 1)">29</span>             imgBox.style.backgroundColor = '#000'<span style="color: rgba(0, 0, 0, 1)">;
</span><span style="color: rgba(0, 128, 128, 1)">30</span>             imgBox.innerHTML = <span style="color: rgba(0, 0, 255, 1)">null</span><span style="color: rgba(0, 0, 0, 1)">;
</span><span style="color: rgba(0, 128, 128, 1)">31</span> <span style="color: rgba(0, 0, 0, 1)">            imgBox.appendChild(img);
</span><span style="color: rgba(0, 128, 128, 1)">32</span> <span style="color: rgba(0, 0, 0, 1)">      }
</span><span style="color: rgba(0, 128, 128, 1)">33</span> <span style="color: rgba(0, 0, 0, 1)">    }
</span><span style="color: rgba(0, 128, 128, 1)">34</span> &lt;/script&gt;</pre>
</div>
<h4 style="color: rgba(220, 20, 60, 1)">4.实现文件加载进度条</h4>
<p>在FileReader.onprogress事件对象中有两个属性loaded和total,loaded表示当前文件读取大小,total表示文件整体大小,并且在读取时会持续触发更新最新读取状态的数据,根据FileReader.onprogress事件就可以实现文件加载进度条的动画效果了,但是由于FileReader是h5的API在IE中最低兼容到10版本,所以需要根据具体的项目和兼容性来设计交互。</p>
<div class="cnblogs_code">
<pre><span style="color: rgba(0, 128, 128, 1)"> 1</span> <span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">css</span>
<span style="color: rgba(0, 128, 128, 1)"> 2</span> <span style="color: rgba(0, 0, 0, 1)">.progress{
</span><span style="color: rgba(0, 128, 128, 1)"> 3</span> <span style="color: rgba(0, 0, 0, 1)">    position: relative;
</span><span style="color: rgba(0, 128, 128, 1)"> 4</span>   margin-<span style="color: rgba(0, 0, 0, 1)">top: 5px;
</span><span style="color: rgba(0, 128, 128, 1)"> 5</span> <span style="color: rgba(0, 0, 0, 1)">    width: 300px;
</span><span style="color: rgba(0, 128, 128, 1)"> 6</span> <span style="color: rgba(0, 0, 0, 1)">    height: 20px;
</span><span style="color: rgba(0, 128, 128, 1)"> 7</span>   border: 1px solid #300<span style="color: rgba(0, 0, 0, 1)">;
</span><span style="color: rgba(0, 128, 128, 1)"> 8</span> <span style="color: rgba(0, 0, 0, 1)">}
</span><span style="color: rgba(0, 128, 128, 1)"> 9</span> <span style="color: rgba(0, 0, 0, 1)">.progressText{
</span><span style="color: rgba(0, 128, 128, 1)">10</span>   display: inline-<span style="color: rgba(0, 0, 0, 1)">block;
</span><span style="color: rgba(0, 128, 128, 1)">11</span> <span style="color: rgba(0, 0, 0, 1)">    position: absolute;
</span><span style="color: rgba(0, 128, 128, 1)">12</span> <span style="color: rgba(0, 0, 0, 1)">    width: 300px;
</span><span style="color: rgba(0, 128, 128, 1)">13</span> <span style="color: rgba(0, 0, 0, 1)">    height: 20px;
</span><span style="color: rgba(0, 128, 128, 1)">14</span>   text-<span style="color: rgba(0, 0, 0, 1)">align: center;
</span><span style="color: rgba(0, 128, 128, 1)">15</span>   font-<span style="color: rgba(0, 0, 0, 1)">size: 10px;
</span><span style="color: rgba(0, 128, 128, 1)">16</span>   line-<span style="color: rgba(0, 0, 0, 1)">height: 20px;
</span><span style="color: rgba(0, 128, 128, 1)">17</span> <span style="color: rgba(0, 0, 0, 1)">}
</span><span style="color: rgba(0, 128, 128, 1)">18</span> <span style="color: rgba(0, 0, 0, 1)">.progressSpan{
</span><span style="color: rgba(0, 128, 128, 1)">19</span>   display: inline-<span style="color: rgba(0, 0, 0, 1)">block;
</span><span style="color: rgba(0, 128, 128, 1)">20</span>   <span style="color: rgba(0, 128, 0, 1)">/*</span><span style="color: rgba(0, 128, 0, 1)"> width: 200px; </span><span style="color: rgba(0, 128, 0, 1)">*/</span>
<span style="color: rgba(0, 128, 128, 1)">21</span> <span style="color: rgba(0, 0, 0, 1)">    height: 20px;
</span><span style="color: rgba(0, 128, 128, 1)">22</span>   background-<span style="color: rgba(0, 0, 0, 1)">color: #f0f;
</span><span style="color: rgba(0, 128, 128, 1)">23</span> <span style="color: rgba(0, 0, 0, 1)">}
</span><span style="color: rgba(0, 128, 128, 1)">24</span> <span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">html</span>
<span style="color: rgba(0, 128, 128, 1)">25</span> &lt;input type="file" name=""&gt;
<span style="color: rgba(0, 128, 128, 1)">26</span> &lt;!-- 文件加载进度条 --&gt;
<span style="color: rgba(0, 128, 128, 1)">27</span> &lt;div class="progress"&gt;
<span style="color: rgba(0, 128, 128, 1)">28</span>   &lt;span class="progressText"&gt;&lt;/span&gt;
<span style="color: rgba(0, 128, 128, 1)">29</span>   &lt;span class="progressSpan"&gt;&lt;/span&gt;
<span style="color: rgba(0, 128, 128, 1)">30</span> &lt;/div&gt;
<span style="color: rgba(0, 128, 128, 1)">31</span> <span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">js</span>
<span style="color: rgba(0, 128, 128, 1)">32</span> <span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">获取文件源(所有功能实现的公共代码区)</span>
<span style="color: rgba(0, 128, 128, 1)">33</span> <span style="color: rgba(0, 0, 255, 1)">var</span> inp = document.getElementsByTagName('input'); <span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">获取文件源</span>
<span style="color: rgba(0, 128, 128, 1)">34</span> <span style="color: rgba(0, 0, 255, 1)">var</span> reader = <span style="color: rgba(0, 0, 255, 1)">new</span> FileReader(); <span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">创建文件读取对象</span>
<span style="color: rgba(0, 128, 128, 1)">35</span> <span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> fileReader实现图片加载进度条</span>
<span style="color: rgba(0, 128, 128, 1)">36</span> <span style="color: rgba(0, 0, 255, 1)">var</span> progressSpanObj = document.getElementsByClassName('progressSpan');
</span><span style="color: rgba(0, 128, 128, 1)">37</span> <span style="color: rgba(0, 0, 255, 1)">var</span> progressTextObj = document.getElementsByClassName('progressText');
</span><span style="color: rgba(0, 128, 128, 1)">38</span> inp.onchange = <span style="color: rgba(0, 0, 255, 1)">function</span><span style="color: rgba(0, 0, 0, 1)">(){
</span><span style="color: rgba(0, 128, 128, 1)">39</span>   reader.readAsArrayBuffer(inp.files);
</span><span style="color: rgba(0, 128, 128, 1)">40</span> <span style="color: rgba(0, 0, 0, 1)">}
</span><span style="color: rgba(0, 128, 128, 1)">41</span> reader.onloadstart = <span style="color: rgba(0, 0, 255, 1)">function</span>(e){ <span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">开始读取文件时触发</span>
<span style="color: rgba(0, 128, 128, 1)">42</span>   progressTextObj.innerText = "正在读取文件(0%)..."<span style="color: rgba(0, 0, 0, 1)">;
</span><span style="color: rgba(0, 128, 128, 1)">43</span> <span style="color: rgba(0, 0, 0, 1)">}
</span><span style="color: rgba(0, 128, 128, 1)">44</span> reader.onprogress = <span style="color: rgba(0, 0, 255, 1)">function</span>(e){ <span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">读取进度事件</span>
<span style="color: rgba(0, 128, 128, 1)">45</span>   console.log(Math.round(e.loaded / e.total * 100<span style="color: rgba(0, 0, 0, 1)">));
</span><span style="color: rgba(0, 128, 128, 1)">46</span>   <span style="color: rgba(0, 0, 255, 1)">var</span> precent = Math.round(e.loaded / e.total * 100<span style="color: rgba(0, 0, 0, 1)">);
</span><span style="color: rgba(0, 128, 128, 1)">47</span>   progressSpanObj.style.width = precent / 100 * 300 + 'px'<span style="color: rgba(0, 0, 0, 1)">;
</span><span style="color: rgba(0, 128, 128, 1)">48</span>   progressTextObj.innerText = '正在读取文件(' + precent + '%)...'<span style="color: rgba(0, 0, 0, 1)">;
</span><span style="color: rgba(0, 128, 128, 1)">49</span> <span style="color: rgba(0, 0, 0, 1)">}
</span><span style="color: rgba(0, 128, 128, 1)">50</span> reader.onload = <span style="color: rgba(0, 0, 255, 1)">function</span><span style="color: rgba(0, 0, 0, 1)">(e){
</span><span style="color: rgba(0, 128, 128, 1)">51</span>   progressTextObj.innerText = '文件读取完成(100%)'<span style="color: rgba(0, 0, 0, 1)">;
</span><span style="color: rgba(0, 128, 128, 1)">52</span> <span style="color: rgba(0, 0, 0, 1)">}
</span><span style="color: rgba(0, 128, 128, 1)">53</span> reader.onerror = <span style="color: rgba(0, 0, 255, 1)">function</span><span style="color: rgba(0, 0, 0, 1)">(e){
</span><span style="color: rgba(0, 128, 128, 1)">54</span>   progressTextObj.innerText = "文件读取出错误(~0v0~)"<span style="color: rgba(0, 0, 0, 1)">;
</span><span style="color: rgba(0, 128, 128, 1)">55</span> }</pre>
</div>
<h2 style="background-color: rgba(220, 20, 60, 1); border-radius: 5px">&nbsp;二、fileReade的与file.slice实现文件切片读取</h2>
<p>&nbsp;通过input-type获取的文件对象上有这样几个数据:</p>
<div class="cnblogs_code">
<pre>inputDom.files;<span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">获取File对象(在onchange事件后获取)</span></pre>
</div>
<h4>File对象上的属性与方法:</h4>
<ul style="color: rgba(51, 0, 0, 1)">
<li>File():构造函数,返回一个新的文件对象</li>
<li>File.lastModified:返回所引用文件最后的修改日期,为自&nbsp;1970年1月1日0:00&nbsp;以来的毫秒数。没有已知的最后修改时间则会返回当前时间。</li>
<li>File.lastModifiedDate:返回当前File对象所引用文件最后修改事件的Date都西昂。</li>
<li>File.name:返回当前File对象所引用文件的名字。</li>
<li>File.size:返回文件的大小</li>
<li>File.webkitRelativePath:返回Filex相关的path或URL(这是个非标准属性,chrome上获取的是一个空字符串)</li>
<li>File.slice():文件对象上本身是没有方法的,slice方法同通过继承Blob对象上的slice方法实现的。</li>
</ul>
<p>File对象说明手册(MDN):https://developer.mozilla.org/zh-CN/docs/Web/API/File</p>
<p>File.slice()方法说明手册(MDN):https://developer.mozilla.org/zh-CN/docs/Web/API/Blob/slice</p>
<h4>File.slice实现文件切片读取:</h4>
<div class="cnblogs_code">
<pre><span style="color: rgba(0, 128, 128, 1)"> 1</span> &lt;!--样式同上面的进度条实例一样,这里就不添加了--&gt;
<span style="color: rgba(0, 128, 128, 1)"> 2</span> &lt;input type="file" name=""&gt;
<span style="color: rgba(0, 128, 128, 1)"> 3</span> &lt;!-- 文件加载进度条 --&gt;
<span style="color: rgba(0, 128, 128, 1)"> 4</span> &lt;div class="progress"&gt;
<span style="color: rgba(0, 128, 128, 1)"> 5</span>   &lt;span class="progressText"&gt;&lt;/span&gt;
<span style="color: rgba(0, 128, 128, 1)"> 6</span>   &lt;span class="progressSpan"&gt;&lt;/span&gt;
<span style="color: rgba(0, 128, 128, 1)"> 7</span> &lt;/div&gt;
<span style="color: rgba(0, 128, 128, 1)"> 8</span> <span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">获取文件源(所有功能实现的公共代码区)</span>
<span style="color: rgba(0, 128, 128, 1)"> 9</span> <span style="color: rgba(0, 0, 255, 1)">var</span> inp = document.getElementsByTagName('input'); <span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">获取文件源</span>
<span style="color: rgba(0, 128, 128, 1)">10</span> <span style="color: rgba(0, 0, 255, 1)">var</span> reader = <span style="color: rgba(0, 0, 255, 1)">new</span> FileReader(); <span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">创建文件读取对象</span>
<span style="color: rgba(0, 128, 128, 1)">11</span> <span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> fileReader实现图片加载进度条</span>
<span style="color: rgba(0, 128, 128, 1)">12</span> <span style="color: rgba(0, 0, 255, 1)">var</span> progressSpanObj = document.getElementsByClassName('progressSpan');
</span><span style="color: rgba(0, 128, 128, 1)">13</span> <span style="color: rgba(0, 0, 255, 1)">var</span> progressTextObj = document.getElementsByClassName('progressText');
</span><span style="color: rgba(0, 128, 128, 1)">14</span> <span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">file.slice(起始字节,终止字节)与FileReader实现文件切片读取</span>
<span style="color: rgba(0, 128, 128, 1)">15</span> <span style="color: rgba(0, 0, 255, 1)">function</span><span style="color: rgba(0, 0, 0, 1)"> PartFileReader(files,type,event){
</span><span style="color: rgba(0, 128, 128, 1)">16</span>   <span style="color: rgba(0, 0, 255, 1)">this</span>.files = files;<span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">inputObj.files</span>
<span style="color: rgba(0, 128, 128, 1)">17</span>   <span style="color: rgba(0, 0, 255, 1)">this</span>.type = type;<span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">配置FileReader读取文件的方法</span>
<span style="color: rgba(0, 128, 128, 1)">18</span>   <span style="color: rgba(0, 0, 255, 1)">this</span>.event = event;<span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">配置读取文件时需要触发的事件</span>
<span style="color: rgba(0, 128, 128, 1)">19</span>   <span style="color: rgba(0, 0, 255, 1)">this</span>.total = files.size;<span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">获取文件大小</span>
<span style="color: rgba(0, 128, 128, 1)">20</span>   <span style="color: rgba(0, 0, 255, 1)">this</span>.step = 1024 * 1024;<span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">1MB(单片大小/一兆)</span>
<span style="color: rgba(0, 128, 128, 1)">21</span>   <span style="color: rgba(0, 0, 255, 1)">this</span>.loaded = 0; <span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">文件当前读取进度</span>
<span style="color: rgba(0, 128, 128, 1)">22</span>   <span style="color: rgba(0, 0, 255, 1)">this</span>.reader = <span style="color: rgba(0, 0, 255, 1)">new</span> FileReader(); <span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">实际读取文件的FileReader对象实例</span>
<span style="color: rgba(0, 128, 128, 1)">23</span>   <span style="color: rgba(0, 0, 255, 1)">this</span>.abort = <span style="color: rgba(0, 0, 255, 1)">this</span>.reader.abort; <span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">中断文件读取(可以通过中断文件读取事件保留切片数据,实现下一次可以在原读取位置继续开始读取)</span>
<span style="color: rgba(0, 128, 128, 1)">24</span>   <span style="color: rgba(0, 0, 255, 1)">this</span>.readPartFile(<span style="color: rgba(0, 0, 255, 1)">this</span>.loaded); <span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">开启读取文件</span>
<span style="color: rgba(0, 128, 128, 1)">25</span>   <span style="color: rgba(0, 0, 255, 1)">this</span>.bindEvent();<span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">绑定FileReader文件读取</span>
<span style="color: rgba(0, 128, 128, 1)">26</span> <span style="color: rgba(0, 0, 0, 1)">}
</span><span style="color: rgba(0, 128, 128, 1)">27</span> <span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">给切片读取对象原型上添加FileReader获取读取类型,开启读取文件</span>
<span style="color: rgba(0, 128, 128, 1)">28</span> PartFileReader.prototype.readPartFile = <span style="color: rgba(0, 0, 255, 1)">function</span><span style="color: rgba(0, 0, 0, 1)">(start){
</span><span style="color: rgba(0, 128, 128, 1)">29</span>   <span style="color: rgba(0, 0, 255, 1)">if</span>(<span style="color: rgba(0, 0, 255, 1)">this</span><span style="color: rgba(0, 0, 0, 1)">.files.slice){
</span><span style="color: rgba(0, 128, 128, 1)">30</span>         <span style="color: rgba(0, 0, 255, 1)">var</span> file = <span style="color: rgba(0, 0, 255, 1)">this</span>.files.slice(start,<span style="color: rgba(0, 0, 255, 1)">this</span>.loaded + <span style="color: rgba(0, 0, 255, 1)">this</span><span style="color: rgba(0, 0, 0, 1)">.step);
</span><span style="color: rgba(0, 128, 128, 1)">31</span>         <span style="color: rgba(0, 0, 255, 1)">switch</span>(<span style="color: rgba(0, 0, 255, 1)">this</span><span style="color: rgba(0, 0, 0, 1)">.type){
</span><span style="color: rgba(0, 128, 128, 1)">32</span>             <span style="color: rgba(0, 0, 255, 1)">case</span> 'readAsBinaryString'<span style="color: rgba(0, 0, 0, 1)"> :
</span><span style="color: rgba(0, 128, 128, 1)">33</span>               <span style="color: rgba(0, 0, 255, 1)">this</span><span style="color: rgba(0, 0, 0, 1)">.reader.readAsBinaryString(file);
</span><span style="color: rgba(0, 128, 128, 1)">34</span>               <span style="color: rgba(0, 0, 255, 1)">break</span><span style="color: rgba(0, 0, 0, 1)">;
</span><span style="color: rgba(0, 128, 128, 1)">35</span>             <span style="color: rgba(0, 0, 255, 1)">case</span> 'readAsDataURL'<span style="color: rgba(0, 0, 0, 1)"> :
</span><span style="color: rgba(0, 128, 128, 1)">36</span>               <span style="color: rgba(0, 0, 255, 1)">this</span><span style="color: rgba(0, 0, 0, 1)">.reader.readAsDataURL(file);
</span><span style="color: rgba(0, 128, 128, 1)">37</span>               <span style="color: rgba(0, 0, 255, 1)">break</span><span style="color: rgba(0, 0, 0, 1)">;
</span><span style="color: rgba(0, 128, 128, 1)">38</span>             <span style="color: rgba(0, 0, 255, 1)">case</span> 'readAsArrayBuffer'<span style="color: rgba(0, 0, 0, 1)"> :
</span><span style="color: rgba(0, 128, 128, 1)">39</span>               <span style="color: rgba(0, 0, 255, 1)">this</span><span style="color: rgba(0, 0, 0, 1)">.reader.readAsArrayBuffer(file);
</span><span style="color: rgba(0, 128, 128, 1)">40</span>               <span style="color: rgba(0, 0, 255, 1)">break</span><span style="color: rgba(0, 0, 0, 1)">;
</span><span style="color: rgba(0, 128, 128, 1)">41</span>             <span style="color: rgba(0, 0, 255, 1)">case</span> 'readAsText'<span style="color: rgba(0, 0, 0, 1)"> :
</span><span style="color: rgba(0, 128, 128, 1)">42</span>               <span style="color: rgba(0, 0, 255, 1)">this</span><span style="color: rgba(0, 0, 0, 1)">.readAsText(file);
</span><span style="color: rgba(0, 128, 128, 1)">43</span>               <span style="color: rgba(0, 0, 255, 1)">break</span><span style="color: rgba(0, 0, 0, 1)">;
</span><span style="color: rgba(0, 128, 128, 1)">44</span> <span style="color: rgba(0, 0, 0, 1)">      }
</span><span style="color: rgba(0, 128, 128, 1)">45</span> <span style="color: rgba(0, 0, 0, 1)">    }
</span><span style="color: rgba(0, 128, 128, 1)">46</span> <span style="color: rgba(0, 0, 0, 1)">}
</span><span style="color: rgba(0, 128, 128, 1)">47</span> <span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">给切片读取对象原型上绑定FileReader对象事件</span>
<span style="color: rgba(0, 128, 128, 1)">48</span> PartFileReader.prototype.bindEvent = <span style="color: rgba(0, 0, 255, 1)">function</span><span style="color: rgba(0, 0, 0, 1)">(){
</span><span style="color: rgba(0, 128, 128, 1)">49</span>   <span style="color: rgba(0, 0, 255, 1)">var</span> self = <span style="color: rgba(0, 0, 255, 1)">this</span><span style="color: rgba(0, 0, 0, 1)">;
</span><span style="color: rgba(0, 128, 128, 1)">50</span>   <span style="color: rgba(0, 0, 255, 1)">this</span>.reader.onloadstart = <span style="color: rgba(0, 0, 255, 1)">function</span><span style="color: rgba(0, 0, 0, 1)">(e){
</span><span style="color: rgba(0, 128, 128, 1)">51</span>         self.event.loadStart &amp;&amp; self.event.loadStart.call(<span style="color: rgba(0, 0, 255, 1)">this</span><span style="color: rgba(0, 0, 0, 1)">,e);
</span><span style="color: rgba(0, 128, 128, 1)">52</span> <span style="color: rgba(0, 0, 0, 1)">    }
</span><span style="color: rgba(0, 128, 128, 1)">53</span>   <span style="color: rgba(0, 0, 255, 1)">this</span>.reader.onprogress = <span style="color: rgba(0, 0, 255, 1)">function</span><span style="color: rgba(0, 0, 0, 1)">(e){
</span><span style="color: rgba(0, 128, 128, 1)">54</span>         self.event.progress &amp;&amp; self.event.progress.call(<span style="color: rgba(0, 0, 255, 1)">this</span><span style="color: rgba(0, 0, 0, 1)">,e);
</span><span style="color: rgba(0, 128, 128, 1)">55</span> <span style="color: rgba(0, 0, 0, 1)">    }
</span><span style="color: rgba(0, 128, 128, 1)">56</span>   <span style="color: rgba(0, 0, 255, 1)">this</span>.reader.onload = <span style="color: rgba(0, 0, 255, 1)">function</span><span style="color: rgba(0, 0, 0, 1)">(e){
</span><span style="color: rgba(0, 128, 128, 1)">57</span>         <span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> 切片读取文件有别于非切片读取,切片读取的文件读取状态需要在每个切片读取成功后再刷新读取进度</span>
<span style="color: rgba(0, 128, 128, 1)">58</span>         self.loaded +=<span style="color: rgba(0, 0, 0, 1)"> e.loaded;
</span><span style="color: rgba(0, 128, 128, 1)">59</span>         self.event.load &amp;&amp; self.event.load.call(<span style="color: rgba(0, 0, 255, 1)">this</span><span style="color: rgba(0, 0, 0, 1)">,e,self.loaded,self.total);
</span><span style="color: rgba(0, 128, 128, 1)">60</span>         <span style="color: rgba(0, 0, 255, 1)">if</span>(self.loaded &lt;<span style="color: rgba(0, 0, 0, 1)"> self.total){
</span><span style="color: rgba(0, 128, 128, 1)">61</span> <span style="color: rgba(0, 0, 0, 1)">            self.readPartFile(self.loaded);
</span><span style="color: rgba(0, 128, 128, 1)">62</span> <span style="color: rgba(0, 0, 0, 1)">      }
</span><span style="color: rgba(0, 128, 128, 1)">63</span> <span style="color: rgba(0, 0, 0, 1)">    }
</span><span style="color: rgba(0, 128, 128, 1)">64</span>   <span style="color: rgba(0, 0, 255, 1)">this</span>.reader.onloadend = <span style="color: rgba(0, 0, 255, 1)">function</span><span style="color: rgba(0, 0, 0, 1)">(e){
</span><span style="color: rgba(0, 128, 128, 1)">65</span>         self.event.loadend &amp;&amp; self.event.loadend.call(<span style="color: rgba(0, 0, 255, 1)">this</span><span style="color: rgba(0, 0, 0, 1)">,e);
</span><span style="color: rgba(0, 128, 128, 1)">66</span> <span style="color: rgba(0, 0, 0, 1)">    }
</span><span style="color: rgba(0, 128, 128, 1)">67</span>   <span style="color: rgba(0, 0, 255, 1)">this</span>.reader.onabort = <span style="color: rgba(0, 0, 255, 1)">function</span><span style="color: rgba(0, 0, 0, 1)">(e){
</span><span style="color: rgba(0, 128, 128, 1)">68</span>         self.event.abort &amp;&amp; self.event.abort.call(<span style="color: rgba(0, 0, 255, 1)">this</span><span style="color: rgba(0, 0, 0, 1)">,e);
</span><span style="color: rgba(0, 128, 128, 1)">69</span> <span style="color: rgba(0, 0, 0, 1)">    }
</span><span style="color: rgba(0, 128, 128, 1)">70</span> <span style="color: rgba(0, 0, 0, 1)">}
</span><span style="color: rgba(0, 128, 128, 1)">71</span> <span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">调用文件切片读取对象,配置FileReader事件函数</span>
<span style="color: rgba(0, 128, 128, 1)">72</span> inp.onchange = <span style="color: rgba(0, 0, 255, 1)">function</span><span style="color: rgba(0, 0, 0, 1)">(){
</span><span style="color: rgba(0, 128, 128, 1)">73</span>   <span style="color: rgba(0, 0, 255, 1)">var</span> reader = <span style="color: rgba(0, 0, 255, 1)">new</span> PartFileReader(inp.files,'readAsArrayBuffer'<span style="color: rgba(0, 0, 0, 1)">,{
</span><span style="color: rgba(0, 128, 128, 1)">74</span>         loadStart:<span style="color: rgba(0, 0, 255, 1)">function</span><span style="color: rgba(0, 0, 0, 1)">(e){
</span><span style="color: rgba(0, 128, 128, 1)">75</span>             progressTextObj.innerText = "正在读取文件(0%)..."<span style="color: rgba(0, 0, 0, 1)">;
</span><span style="color: rgba(0, 128, 128, 1)">76</span> <span style="color: rgba(0, 0, 0, 1)">      },
</span><span style="color: rgba(0, 128, 128, 1)">77</span>         progress:<span style="color: rgba(0, 0, 255, 1)">function</span><span style="color: rgba(0, 0, 0, 1)">(e){},
</span><span style="color: rgba(0, 128, 128, 1)">78</span>         load:<span style="color: rgba(0, 0, 255, 1)">function</span><span style="color: rgba(0, 0, 0, 1)">(e,loaded,total){
</span><span style="color: rgba(0, 128, 128, 1)">79</span>             <span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> 如果在读取的基础上写上传的话在这里获取读取成功的文件切片</span>
<span style="color: rgba(0, 128, 128, 1)">80</span>             <span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> e.target.result //当前文件切片的数据</span>
<span style="color: rgba(0, 128, 128, 1)">81</span>             <span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> (但是千万别在这里直接写网络请求,本地读取的速度远远大于网络请求,直接请求一个文件就会在瞬间发起大量请求)</span>
<span style="color: rgba(0, 128, 128, 1)">82</span>             <span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> (最好的处理方式是将切片数据写入一个有序列表中,然后通过控制网络请求数量来实现)</span>
<span style="color: rgba(0, 128, 128, 1)">83</span>             <span style="color: rgba(0, 0, 255, 1)">var</span> precent = Math.round(loaded / total * 100<span style="color: rgba(0, 0, 0, 1)">);
</span><span style="color: rgba(0, 128, 128, 1)">84</span>             progressSpanObj.style.width = precent / 100 * 300 + 'px'<span style="color: rgba(0, 0, 0, 1)">;
</span><span style="color: rgba(0, 128, 128, 1)">85</span>             <span style="color: rgba(0, 0, 255, 1)">if</span>(precent &lt; 100<span style="color: rgba(0, 0, 0, 1)">){
</span><span style="color: rgba(0, 128, 128, 1)">86</span>               progressTextObj.innerText = '正在读取文件(' + precent + '%)...'<span style="color: rgba(0, 0, 0, 1)">;
</span><span style="color: rgba(0, 128, 128, 1)">87</span>             }<span style="color: rgba(0, 0, 255, 1)">else</span> <span style="color: rgba(0, 0, 255, 1)">if</span>(precent == 100<span style="color: rgba(0, 0, 0, 1)">){
</span><span style="color: rgba(0, 128, 128, 1)">88</span>               progressTextObj.innerText = '文件读取完成(100%)'<span style="color: rgba(0, 0, 0, 1)">;
</span><span style="color: rgba(0, 128, 128, 1)">89</span> <span style="color: rgba(0, 0, 0, 1)">            }
</span><span style="color: rgba(0, 128, 128, 1)">90</span> <span style="color: rgba(0, 0, 0, 1)">      },
</span><span style="color: rgba(0, 128, 128, 1)">91</span>         loadend:<span style="color: rgba(0, 0, 255, 1)">function</span><span style="color: rgba(0, 0, 0, 1)">(e){},
</span><span style="color: rgba(0, 128, 128, 1)">92</span>         abort:<span style="color: rgba(0, 0, 255, 1)">function</span><span style="color: rgba(0, 0, 0, 1)">(e){},
</span><span style="color: rgba(0, 128, 128, 1)">93</span>         error:<span style="color: rgba(0, 0, 255, 1)">function</span><span style="color: rgba(0, 0, 0, 1)">(e){
</span><span style="color: rgba(0, 128, 128, 1)">94</span>             progressTextObj.innerText = "文件读取出错误(~0v0~)"<span style="color: rgba(0, 0, 0, 1)">;
</span><span style="color: rgba(0, 128, 128, 1)">95</span> <span style="color: rgba(0, 0, 0, 1)">      }
</span><span style="color: rgba(0, 128, 128, 1)">96</span> <span style="color: rgba(0, 0, 0, 1)">    })
</span><span style="color: rgba(0, 128, 128, 1)">97</span> }</pre>
</div>
<p>&nbsp;</p>

</div>
<div id="MySignature" role="contentinfo">
    ——生命自会找到蓬勃之路。<br><br>
来源:https://www.cnblogs.com/ZheOneAndOnly/p/11298757.html
頁: [1]
查看完整版本: HTML5之fileReader异步读取文件及文件切片读取