Skip to content

Commit a102144

Browse files
committed
add readFile method
1 parent ba14ccb commit a102144

File tree

6 files changed

+131
-9
lines changed

6 files changed

+131
-9
lines changed

README.md

Lines changed: 11 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -8,16 +8,17 @@
88
A simple implementation for browser to switch string between buffer
99
> Author:Alan Chen
1010
11-
> Version: 0.0.1
11+
> Version: 0.1.0
1212
13-
> Date: 2019/05/07
13+
> Date: 2019/06/05
1414
1515
> 浏览器端js在字符串和ArrayBuffer之间转换的插件
1616
1717
## Feature
1818
* 模仿nodejs的两个api,from表示转换字符串到ArrayBuffer,toString表示转换ArrayBuffer到指定编码格式的字符串。
1919
* 完全基于浏览器端的api,不支持nodejs。
2020
* 自带浏览器端下载文件的功能,模拟nodejs的fs模块的writeFile。
21+
* 封装浏览器端上传文件功能,模拟nodejs的fs模块的readFile,不需要手写input标签,局限性更低,可以通过任何方式来触发系统dialog。
2122
* 由于ArrayBuffer、Blob以及FileReadr的使用,所以目前PC端只兼容IE10+,移动端浏览器未测试。
2223

2324
## Installation
@@ -33,21 +34,28 @@ A simple implementation for browser to switch string between buffer
3334
* encode `[String]`,可选,转换后的字符串编码格式,有utf8、base64和dataURL三种可选,默认为utf8
3435
* MIME `[String]`,可选,仅当编码格式为dataURL生效,决定转换后数据的文件类型,默认为text/plain,txt文本
3536
* charset `[String]`,可选,仅当编码格式为dataURL生效,决定转换后数据的编码类型,默认为utf8编码
36-
3. writeFile `[function(Object)]`,写入数据到本地文件,一个参数,参数是一个对象,如下:
37+
3. readFile `[function(Object)]`,通过打开系统dialog读取本地文件数据,返回一个Promise,reslove文件数据,一个参数,参数是一个对象,如下:
38+
* accept `[Array]`,可选,允许用户上传任何类型的文件,但不能完全限制,数组项可以是MIME信息,也可以是文件后缀名,还可以是`image/*`这种,默认允许所有类型
39+
* multiple `[Boolean]`,是否支持多选,默认为false不支持,如果支持,可以通过键盘Shift或Control来多选
40+
* encode `[String]`,文件的编码格式,utf8、base64和binary字符串其中之一,默认为base64
41+
4. writeFile `[function(Object)]`,写入数据到本地文件,返回一个Promise,一个参数,参数是一个对象,如下:
3742
* filename `[String]`,可选,文件名,可以带后缀名,如果带后缀名,则以后缀名为主,不带则取MIME信息。若为空,则默认为浏览器命名文件,chrome会命名为'下载'
3843
* dataPath `[String]`,当data为空时必选,同源的文件url路径,如果不为空,则只会下载此同源服务器路径的文件,而忽略data
3944
* data `[String | Object | Blob | ArrayBuffer]`,当dataPath为空时必选,写入的数据
4045
* MIME `[String]`,可选,仅当filename不带后缀名时生效,决定转换后数据的文件类型,默认为text/plain,txt文本。filename如果带上后缀名,则会覆盖MIME
4146
* charset `[String]`,可选,文件的编码格式,默认为utf8
4247
## Example
4348
* [buffer转换例子](./example/bufferAndString.js)
49+
* [读取文件例子](./example/uploadFile.js)
4450
* [下载文件例子](./example/download.js)
4551

4652
## Attention
4753
1. 由于string和ArrayBuffer之间的转换依赖于FileReader,所以导致form和toString方法只能返回一个Promise,可以搭配Async函数来获取返回值。
4854
2. 因为FileReader的存在,让浏览器端js操作buffer转码越来越方便,所以我并没有手动通过unicde值来实现(我实现了一个插件不借助FileReader来转换)。
4955
3. 通过插件转换后的ArrayBuffer均遵循utf8编码规范,所以ASCII字符(英文字母、数字和一些符号)都只占1个字节,汉字占3个字节,这和nodejs里的buffer实现完全一致。所以前端可以直接把ArrayBuffer通过流的形式传给后台,解析起来很容易。但是需要区分的是js本身存储字符串是遵循的utf16规范。
5056
4. 插件借助FileReader只能操作buffer转码,如果需要操作buffer内存空间数据,则只能通过TypedArray或者DataView实现,nodejs里则完全可以通过buffer模块实现,这一点区别需要注意。
57+
5. 插件实例的所有方法均会返回Promise,所以都建议使用async函数。
58+
6. 读取文件由于浏览器安全考虑,所以只能通过用户手动上传,所以无法直接跟nodejs的readFile一致。读取文件方法因为不需要传入input标签,所以你可以在任何时候触发,你可以手动实现各种各样的上传功能。
5159

5260
## license
5361
* Anti 996(996.ICU)

config/lib.config.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@
55
module.exports = {
66
libraryName: '@alanchenchen/browserbuffer', // npm包名,首字母不允许大写,支持驼峰和短杆写法
77
bundleName: 'BrowserBuffer', // 打包后文件名,也是UMD script直接引入挂在windows对象的key名
8-
version: '0.0.1', // 版本号
8+
version: '0.1.0', // 版本号
99
description: 'A simple implementation for browser to switch string between buffer', // 包描述
1010
keywords: ['BrowserBuffer', 'browser', 'buffer', 'download', 'ArrayBuffer'], // 关键词
1111
author: 'Alan Chen', // 作者

example/uploadFile.js

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
const BrowserBuffer = require('../src/index')
2+
const browserBuffer = new BrowserBuffer()
3+
4+
const fn = async () => {
5+
/**
6+
* @example 上传单个文件
7+
*/
8+
const data1 = await browserBuffer.readFile()
9+
10+
/**
11+
* @example 上传多个文件
12+
*/
13+
const data2 = await browserBuffer.readFile({
14+
multiple: true
15+
})
16+
17+
/**
18+
* @example 允许用户上传指定格式文件,但是不能完全限制,因为用户可以选择上传所有格式文件
19+
*/
20+
const data3 = await browserBuffer.readFile({
21+
accept: ['image/*', '.md']
22+
})
23+
24+
/**
25+
* @example 上传文件,获取文件的二进制数据(binary),因为默认获取的数据为base64格式
26+
*/
27+
const data4 = await browserBuffer.readFile({
28+
encode: 'binary'
29+
})
30+
}
31+
32+
fn()

package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "@alanchenchen/browserbuffer",
3-
"version": "0.0.1",
3+
"version": "0.1.0",
44
"author": "Alan Chen",
55
"description": "A simple implementation for browser to switch string between buffer",
66
"main": "dist/BrowserBuffer.js",

src/index.js

Lines changed: 85 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,13 @@
11
/**
22
* @description 插件的入口模块。webpack的entry
33
*/
4-
module.exports = class BrowserBuffer {
4+
/**!
5+
* @name ApiModule
6+
* @author Alan chen
7+
* @since 2019/05/07
8+
* @license 996.ICU
9+
*/
10+
module.exports = class BrowserBuffer {
511
constructor() {
612
this._init()
713
this.version = require('../package.json').version
@@ -15,6 +21,8 @@ module.exports = class BrowserBuffer {
1521
*/
1622
_init() {
1723
this._downloadElement = document.createElement('a')
24+
this._uploadElement = document.createElement('input')
25+
this._uploadElement.type = 'file'
1826
}
1927

2028
/**
@@ -70,6 +78,78 @@ module.exports = class BrowserBuffer {
7078
this._downloadElement.click()
7179
}
7280

81+
/**
82+
* 通过打开系统dialog读取本地文件数据
83+
*
84+
* @param {Object} opt
85+
* @param {Array} opt.accept 允许用户上传任何类型的文件,但不能完全限制,数组项可以是MIME信息,也可以是文件后缀名,还可以是image/*这种,默认允许所有类型
86+
* @param {Boolean} opt.multiple 是否支持多选,默认不支持,如果支持,可以通过键盘Shift或Control来多选
87+
* @param {String} opt.encode 文件的编码格式,utf8、base64和binary字符串其中之一,默认为base64
88+
* @returns {Promise} reslove一个数组,数组包含每个文件的数据对象,catch一个错误对象
89+
*/
90+
readFile({
91+
accept=['*'],
92+
multiple=false,
93+
encode='base64'
94+
} = {}) {
95+
this._uploadElement.accept = accept.join(',')
96+
this._uploadElement.multiple = multiple
97+
98+
const readOneFile = (file, encode='base64') => {
99+
return new Promise((resolve, reject) => {
100+
const reader = new FileReader()
101+
let fn = null
102+
switch (encode) {
103+
case 'utf8':
104+
fn = 'readAsText'
105+
break
106+
case 'base64':
107+
fn = 'readAsDataURL'
108+
break
109+
case 'binary':
110+
fn = 'readAsArrayBuffer'
111+
break
112+
default:
113+
fn = 'readAsDataURL'
114+
}
115+
reader[fn](file)
116+
reader.onload = () => {
117+
let result = reader.result
118+
if(encode == 'base64') {
119+
result = reader.result.split('base64,')[1]
120+
}
121+
resolve(result)
122+
}
123+
reader.onerror = () => {
124+
reader.abort()
125+
reject('some erros occured')
126+
}
127+
})
128+
}
129+
130+
return new Promise((resolve, reject) => {
131+
this._uploadElement.onchange = async (e) => {
132+
let fileData = []
133+
let fileslist = this._uploadElement.files || e.path[0].files
134+
try {
135+
for(let key of Object.keys(fileslist)) {
136+
fileData[key] = {}
137+
fileData[key].name = fileslist[key].name
138+
fileData[key].type = fileslist[key].type
139+
fileData[key].size = fileslist[key].size
140+
fileData[key].lastModified = fileslist[key].lastModified
141+
fileData[key].lastModifiedDate = fileslist[key].lastModifiedDate
142+
fileData[key].data = await readOneFile(fileslist[key], encode)
143+
}
144+
resolve(fileData)
145+
} catch (error) {
146+
reject(error)
147+
}
148+
}
149+
this._uploadElement.click()
150+
})
151+
}
152+
73153
/**
74154
* 写入数据到本地文件
75155
*
@@ -79,8 +159,9 @@ module.exports = class BrowserBuffer {
79159
* @param {String | Object | Blob | ArrayBuffer} opt.data 写入的数据
80160
* @param {String} opt.MIME 仅当filename不带后缀名时生效,决定转换后数据的文件类型,默认为text/plain,txt文本。filename如果带上后缀名,则会覆盖MIME。
81161
* @param {String} opt.charset 文件的编码格式,默认为utf8
162+
* @returns {Promise} 因为是async函数,所以返回一个promise
82163
*/
83-
writeFile({
164+
async writeFile({
84165
filename='',
85166
dataPath='',
86167
data,
@@ -107,7 +188,8 @@ module.exports = class BrowserBuffer {
107188
else {
108189
throw new Error('data must be string or object or Blob or ArrayBuffer')
109190
}
110-
this._saveBuffer(buf, filename, charset)
191+
192+
await this._saveBuffer(buf, filename, charset)
111193
}
112194
}
113195

test/module.test.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,6 @@ const assert = require('assert')
66
describe('normal module', function() {
77
it('module version should be 0.0.1', function() {
88
const v = require('../package.json').version
9-
assert.equal(v, '0.0.1')
9+
assert.equal(v, '0.1.0')
1010
})
1111
})

0 commit comments

Comments
 (0)