js图片怎么看文字

作者:赵帅强

https://segmentfault.com/a/1190000018143902

web开发中,如果你想让用户下载或者导出一个文件,应该怎么做呢?

传统的做法是在后端存储或者即时生成一个文件来提供下载功能,这样的优势是可以做权限控制、数据二次处理,但缺点是需要额外发起请求、增大服务端压力、下载速度慢。

但随着HTML5的标准发布,我们已经能够做到只前端来下载各种文件了。

后端响应式下载

在常规的HTTP应答中,Content-Disposition消息头指示回复的内容该以何种形式展示,是以内联的形式(即网页或者页面的一部分),还是以附件的形式下载并保存到本地。

HTTP场景中,第一个参数或者是inline(默认值,表示回复中的消息体会以页面的一部分或者整个页面的形式展示),或者是attachment(意味着消息体应该被下载到本地;大多数浏览器会呈现一个“保存为”的对话框,将filename的值预填为下载后的文件名)。

我们在后端响应头中只要设置该头部信息,即可下载为文件,而不是请求并展示:

Content-Type:text/html;charset=utf-8

Content-Disposition:attachment;filename="cool.html"

但需要注意的是,如果想要用这种方式下载文件,不能使用AJAX的方式,而是应该新建一个<a>标签,模拟点击下载。原因为处于安全性考虑,Java无法与磁盘进行交互,因此AJAX得到的内容将被保留在内存中,而不是磁盘上。

location ~.(jpg|jpeg|png|bmp|ico|gif|swf)$ {

add_header Content-Disposition 'attachment; filename="cool.html"';

}

和后端一样的原理,只不过头部信息通过Nginx统一添加。

前端下载: <a>标签的 download属性

此属性指示浏览器下载URL而不是导航到它,因此将提示用户将其保存为本地文件。如果属性有一个值,那么它将作为下载的文件名使用。此属性对允许的值没有限制,但是/和会被转换为下划线。

  1. 此属性仅适用于同源 URLs。
  2. 尽管HTTP URL需要位于同一源中,但是可以使用 blob: URLs 和 data: URLs ,以方便用户下载 Java 方式生成的内容(例如使用在线绘图的Web应用创建的照片)。

常规的<a>标签,用于链接的跳转,如新的页面,那么如果我们给<a>标签加上download属性,就能很简单的让用户保存新的html页面。

<a download="PHP实现并发请求.html"href="https://segmentfault.com/a/1190000016343861">PHP实现并发请求</a>

生成并下载字符串文件

首先我们需要了解一个特殊的数据格式:Blob

Blob数据

Blob(Binary Large Object,二进制类型的大对象),表示一个不可变的原始数据的类文件对象,我们上传文件时常用的File对象就继承于Blob,并进行了扩展用于支持用户系统上的文件。

我们只能通过Blob()构造函数来创建一个新的Blob对象:

Blob(blobParts[, options])

// 创建一个json类型的Blob对象,支持传入同类型数据的一个数组

vardebug ={hello:"world"};

varblob =newBlob([JSON.stringify(debug,null,2)],

{type :'application/json'});

// 此时blob的值

// Blob(22) {size: 22, type: 'application/json'}

Blob对象存在两个只读属性:

size: Blob 对象中所包含数据的大小(字节)。

type: 一个字符串,表明该Blob对象所包含数据的MIME类型。如果类型未知,则该值为空字符串。

URL对象和下载字符串文件

URL接口是一个用来创建 URLs的对象,包含两个静态方法:

objectURL = URL.createObjectURL(blob)

创建一个 URL(DOMString),包含一个唯一的blob链接(该链接协议为以blob:,后跟唯一标识浏览器中的对象的掩码)。这个 URL 的生命周期和创建它的窗口中的 document 绑定。

URL.revokeObjectURL(objectURL)

销毁之前使用URL.createObjectURL()方法创建的URL实例。浏览器会在文档退出的时候自动释放它们,但是为了获得最佳性能和内存使用状况,你应该在安全的时机主动释放掉它们。

varurl =URL.createObjectURL(blob);

// 此时url的值,跟document绑定,所以每个页面创建的字符串均不同

// blob:https://developer.mozilla.org/defe53c2-2882-43c6-b275-db2a57959789

此时,我们在页面中创建一个新<a>标签,点击即可下载我们想要的文件:

<a href="blob:https://developer.mozilla.org/58702010-433d-4097-990f-e483d84cd02a"download="file.json">下载文件链接</a>

FileReader读取 Blob数据

想要读取Blob数据的唯一方法是FileReader

FileReader对象允许Web应用程序异步读取存储在用户计算机上的文件(或原始数据缓冲区)的内容,使用 FileBlob对象指定要读取的文件或数据。

其中File对象可以是来自用户在一个<input>元素上选择文件后返回的FileList对象,也可以来自拖放操作生成的 DataTransfer对象,还可以是来自在一个HTMLCanvasElement上执行mozGetAsFile()方法后返回结果。

该对象包含3个属性:

FileReader.error

一个DOMException,表示在读取文件时发生的错误 。

FileReader.readyState

表示FileReader状态的数字。取值如下:

常量名 值 描述

EMPTY 0 还没有加载任何数据.

LOADING 1 数据正在被加载.

DONE 2 已完成全部的读取请求.

FileReader.result

文件的内容。该属性仅在读取操作完成后才有效,数据的格式取决于使用哪个方法来启动读取操作。

包含6个事件处理:onabort,,,start,end,onprogress,这些不再详细说明,因为 FileReader继承自EventTarget,所以所有这些事件也可以通过addEventListener方法使用。

包含5个方法:

FileReader.abort()

中止读取操作。在返回时,readyState属性为DONE。

FileReader.readAsArrayBuffer()

开始读取指定的 Blob中的内容, 一旦完成, result 属性中保存的将是被读取文件的 ArrayBuffer 数据对象.

FileReader.readAsBinaryString()

开始读取指定的Blob中的内容。一旦完成,result属性中将包含所读取文件的原始二进制数据。

FileReader.readAsDataURL()

开始读取指定的Blob中的内容。一旦完成,result属性中将包含一个data: URL格式的字符串以表示所读取文件的内容。

FileReader.readAsText()

开始读取指定的Blob中的内容。一旦完成,result属性中将包含一个字符串以表示所读取的文件内容。

因此我们可以直接读取Blob对象的数据:

varreader =newFileReader();

reader.addEventListener("loadend",function(){

console.log(reader.result);

});

reader.readAsDataURL(blob);

// 此时result的值

// data:application/json;base64,ewogICJoZWxsbyI6ICJ3b3JsZCIKfQ==

reader.readAsText(blob);

// 此时result的值

// {

// "hello": "world"

// }

下载图片

除了下载手动生成的字符串或对象,我们还能提供下载图片的功能,一方面能用于支持Canvas绘图的保存功能,一方面能提供批量下载图片等高级功能。

除了浏览器自带的右键保存,我们还可以这么做来下载图片:

// 通过src获取图片的blob对象

funwww.58yuanyou.comctiongetImageBlob(url,cb){

varxhr =new();

xhr.open("get",url,true);

xhr.responseType ="blob";

xhr. =function(){

if(this.status ==200){

cb(this.response);

}

};

xhr.send();

}

letreader =newFileReader();

reader.addEventListener("loadend",function(){

console.log(reader.result);

});

getImageBlob('https://cdn.segmentfault.com/v-5c4ec07f/global/img/user-64.png',function(blob){

// 读取来看下下载的内容

reader.readAsDataURL(blob);

// 最终生成的字符串

// data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAADAAA...

// 生成下载用的URL对象

leturl =URL.createObjectURL(blob);

letaDom =aDom =document.('a');

aDom.href =url;

aDom.download ='download.json';

aDom.text ='下载文件';

document.getElementsByTagName('body')[0].(aDom);

aDom.click();

});

下载 excel文件等

如果你明白了下载的原理,那么所有的内容都能够理解,只不过是转换成对应的格式而已,当然,复杂格式的文档不需要你自己去配//www.58yuanyou.com置,可以引入第三方库,在excel文档方面我选择用 tableExport库(https://tableexport.v5.travismclarke.com/#java):

// 引入CDN文件

'https://cdn.bootcss.com/xlsx/0.14.1/xlsx.core.min.js',

'https://cdn.bootcss.com/FileSaver.js/2014-11-29/FileSaver.min.js',

'https://cdn.bootcss.com/TableExport/5.2.0/js/tableexport.min.js'

// 绑定下载事件,这个是我自己的场景下代码,可能不适合大家,具体的参考官方文档

consttableDom =$('#table');

$('.table-exportBtn',tableDom).on('click',function(){

consttableExport =tableDom.tableExport({

formats:['xlsx','txt'],

filename:'表格下载',

exportButtons:false

});

consttype =$(this).data().type;

constexportData =tableExport.getExportData()[tableDom[0].id][type];

const{data,mimeType,filename,fileExtension,merges,RTL,sheetname}=exportData;

// 源码里才能看到完整参数,官方文档没有写全,导致下载的文件格式错误

tableExport.export2file(data,mimeType,filename,fileExtension,merges,RTL,sheetname);

});

默认的方法会自动生成下载按钮,但如果你想自定义下载功能,参考 exportButtons: false 设置(https://tableexport.v3.travismclarke.com/examples/exportButtons.html) 一节,但这个文档有问题,export2file参数不完整,导致下载的xlsx文件一直格式错误,通过查看源码,需要写全参数才可以,上面的示例里已经写出。

tableExport库源码

我们可以看下tableExport导出文件的核心代码,其导出为excel格式比较复杂,由xlsx.core.min.js来完成:

/**

* Exports and downloads the file

* @memberof TableExport.prototype

* @param data {String}

* @param mime {String} mime type

* @param name {String} filename

* @param extension {String} file extension

* @param merges {Object[]}

* @param RTL {Boolean}

*/

export2file:function(data,mime,name,extension,merges,RTL,sheetname){

varformat =extension.slice(1);

data =this.getRawData(data,extension,name,merges,RTL,sheetname);

if(_isMobile &&(format ===_FORMAT.CSV ||format ===_FORMAT.TXT)){

// 拼凑指定格式的data:类型 URI

vardataURI ="data:"+mime +";"+this.charset +","+data;

this.downloadDataURI(dataURI,name,extension);

}else{

// TODO: error and fallback when `saveAs` not available

saveAs(newBlob([data],{type:mime +";"+this.charset }),name +extension,true);

}

},

// 先创建<a>标签,然后提供href和download属性,并模拟点击

downloadDataURI:function(dataURI,name,extension){

varencodedUri =encodeURI(datavjJfVggtlqURI);

varlink =document.("a");

link.setAttribute("href",encodedUri);

link.setAttribute("download",name +extension);

document.body.(link);

link.click();

},

xlsx文件导出导出

还没有仔细研究,感兴趣的可以查看其js-xlsx Github项目(https://github.com/SheetJS/js-xlsx/blob/master/README.md)

第三方库

上面我们主要讲了下载背后的原理,你可以自己封装,也可以使用现成的第三方库,如 download.js(https://github.com/rndme/download) ,这个能提供大部分常用数据的下载;但如果你是要下载表格数据为excel格式,还是推荐 tableExport.js(https://tableexport.v5.travismclarke.com/#java) 及其依赖组件。

参考资料

  1. MDN-a: (https://developer.mozilla.org/zh-CN/docs/Web/HTML/Element/a)
  2. MDN-blob: (https://developer.mozilla.org/zh-CN/docs/Web/API/Blob)
  3. 掘金-细说Web API中的Blob:(https://juejin.im/post/59e35d0e6fb9a045030f1f35)
  4. MDN-URL: (https://developer.mozilla.org/zh-CN/docs/Web/API/URL)
  5. MDN-FileReader: (https://developer.mozilla.org/zh-CN/docs/Web/API/FileReader)
  6. 博客园-js 获取图片url的Blob值并预览:(https://www.cnblogs.com/tujia/www.58yuanyou.comp/6483255.html)
  7. tableExport文档:(https://tableexport.v5.travismclarke.com/#java)
  8. 感谢 @Oliveryoung 提供的其他解决方案
  9. MDN-Content-原由网Disposition: (https://developer.mozilla.org/zh-CN/docs/Web/HTTP/Headers/Content-Disposition)
  10. Ajax请求无法下载文件的原因: (https://blog.csdn.net/w405722907/article/details/77366843)
  11. Github-download.js:(https://github.com/rndme/download)

内容版权声明:除非注明原创否则皆为转载,再次转载请注明出处。

文章标题: js图片怎么看文字

文章地址: www.58yuanyou.com/jiqiao/324128.html

相关推荐