FileBox is a virtual container for packing a file data into it for future read, and easily transport between servers with the least payload, no mater than where it is (local path, remote url, or cloud storage).
Currently the FileBox supports almost all kinds of the data input/output methods/formats:
File Type | Pack Method | Unpack Method | Description |
---|---|---|---|
Local File | fromFile() |
toFile() |
Local file in file system |
Remote URL | fromUrl() |
toUrl() (TBW) |
Remote file in a HTTP/HTTPS URL |
Buffer | fromBuffer() |
toBuffer() |
JavaScript Buffer |
Stream | fromStream() |
toStream() |
JavaScript Stream |
Base64 | fromBase64() |
toBase64() |
Base64 data |
DataURL | fromDataURL() |
toDataURL() |
DataURL data |
QRCode | fromQRCode() |
toQRCode() |
QR Code Image Decode/Encode |
JSON | fromJSON() |
toJSON() |
Serialize/Deserialize FileBox |
The following example demos:
- Save URL to File
- Convert Buffer to Stream
- Pack from Base64 then Unpack to DataURL
import { FileBox } from 'file-box'
/**
* 1. Save URL to File
*/
const fileBox1 = FileBox.fromUrl(
'https://huan.github.io/file-box/images/file-box-logo.jpg',
'logo.jpg',
)
fileBox1.toFile('/tmp/file-box-logo.jpg')
/**
* 2. Convert Buffer to Stream
*/
import fs from 'fs'
const fileBox2 = FileBox.fromBuffer(
Buffer.from('world'),
'hello.txt',
)
const writeStream = fs.createWriteStream('/tmp/hello.txt')
fileBox2.pipe(writeStream)
/**
* 3. Pack Base64, Unpack to DataURL
*/
const fileBox3 = FileBox.fromBase64('d29ybGQK', 'hello.txt')
fileBox3.toDataURL()
.then(console.log)
// Output: data:text/plain;base64,d29ybGQK
Alias: fromLocal()
const fileBox = FileBox.fromLocal('/tmp/test.txt')
Alias: fromRemote()
const fileBox = FileBox.fromUrl(
'https://huan.github.io/file-box/images/file-box-logo.jpg',
'logo.jpg',
)
const fileBox = FileBox.fromStream(res, '/tmp/download.zip')
const fileBox = FileBox.fromBuffer(buf, '/tmp/download.zip')
Decoded a base64 encoded file data.
const fileBox = FileBox.fromBase64('d29ybGQK', 'hello.txt')
fileBox.toFile()
Decoded a DataURL data.
const fileBox = FileBox.fromDataURL('data:text/plain;base64,d29ybGQK', 'hello.txt')
fileBox.toFile()
Restore a FileBox.toJSON()
text string back to a FileBox instance.
const restoredFileBox = FileBox.fromJSON(jsonText)
Get a FileBox instance that represent a QR Code value.
const fileBox = FileBox.fromQRCode('https://github.com')
fileBox.toFile('qrcode.png')
Save file to current work path(cwd) of the local file system with the default name
.
if name
specified with a full path, then will use the speficied file name instead.
const fileBox = FileBox.fromRemote(
'https://huan.github.io/file-box/images/file-box-logo.jpg',
)
await fileBox.toFile('/tmp/logo.jpg')
Pipe to a writable stream.
const fileBox = FileBox.fromRemote(
'https://huan.github.io/file-box/images/file-box-logo.jpg',
)
const writableStream = fs.createWritable('/tmp/logo.jpg')
fileBox.pipe(writableStream)
Get the base64 data of file.
const fileBox = FileBox.fromRemote(
'https://huan.github.io/file-box/images/file-box-logo.jpg',
)
const base64Text = await fileBox.toBase64()
console.log(base64Text) // Output: the base64 encoded data of the file
Get the JSON.stringify
-ed text.
Not Implement Yet: Working In Progress...
const fileBox = FileBox.fromRemote(
'https://huan.github.io/file-box/images/file-box-logo.jpg',
)
const jsonText1 = fileBox.toJSON()
const jsonText2 = JSON.stringify(fileBox)
assert(jsonText1 === jsonText2)
console.log(jsonText1) // Output: the stringified data of the fileBox
const restoredFileBox = fileBox.fromJSON(jsonText1)
restoredFileBox.toFile('/tmp/file-box-logo.jpg')
Get the DataURL of the file.
const fileBox = FileBox.fromFile('tests/fixtures/hello.txt')
const dataUrl = await fileBox.toDataURL()
console.log(dataUrl) // Output: data:text/plain;base64,d29ybGQK'
Get the Buffer of the file.
const fileBox = FileBox.fromFile('tests/fixtures/hello.txt')
const buffer = await fileBox.toBuffer()
console.log(buffer.toString()) // Output: world
Decode the QR Code value from the file.
const fileBox = FileBox.fromFile('qrcode.jpg')
const qrCodeValue = await fileBox.toQRCode()
console.log(`QR Code decoded value is: "${qrCodeValue}"`)
// Output: QR Code decoded value is: "https://github.com"
Encode a FileBox instance to JSON string so that we can transfer the FileBox on the wire.
const fileBox = FileBox.fromBase64('RmlsZUJveEJhc2U2NAo=')
const jsonText = JSON.stringify(fileBox)
// the above code equals to the following line of code:
// const jsonText = fileBox.toJSON()
// we will get the serialized data for this FileBox:
console.log(jsonText)
// Output: {"name":"qrcode.png","metadata":{},"boxType":1,"base64":"RmlsZUJveEJhc2U2NAo="}
// restore our fleBox:
// const newFileBox = FileBox.fromJSON(jsonText)
Because we want to enable the JSON.stringify(fileBox)
, which will call fileBox.toJSON()
, so the toJSON()
can not be async
, which means we can only support limited FileBoxType(s):
- FileBoxType.Base64
- FileBoxType.Url
- FileBoxType.QRCode
For other types like FileBoxType.File
, FileBoxType.Buffer
, FileBoxType.Stream
, etc, we need to transform them to FileBoxType.Base64
before we call toJSON
:
const fileBoxLazy = FileBox.fromFile('./test.txt')
const base64 = await fileBoxLazy.toBase64()
const fileBox = FleBox.fromBase64(base64, 'test.txt')
// fileBox will be serializable because it do not need async operations
const jsonText = JSON.stringify(fileBox)
console.log(jsonText)
File name of the file in the box
const fileBox = FileBox.fromRemote(
'https://huan.github.io/file-box/images/file-box-logo.jpg',
)
console.log(fileBox.name) // Output: file-box-logo.jpg
Metadata for the file in the box. This value can only be assigned once, and will be immutable afterwards, all following assign or modify actions on metadata
will throw errors
const fileBox = FileBox.fromRemote(
'https://huan.github.io/file-box/images/file-box-logo.jpg',
)
fileBox.metadata = {
author : 'huan',
githubRepo : 'https://github.com/huan/file-box',
}
console.log(fileBox.metadata) // Output: { author: 'huan', githubRepo: 'https://github.com/huan/file-box' }
fileBox.metadata.author = 'Tank' // Will throw exception
Version of the FileBox
Serialize FileBox metadata to JSON.
To be implemented.
Update the necessary internal data and make everything ready for use.
Sync the filename with the HTTP Response Header
HTTP Header Example:
Content-Disposition: attachment; filename="filename.ext"
Return the type of the current FileBox instance.
The currently supported types are defined at file-box-type.ts as the following demonstrated:
enum FileBoxType {
Unknown = 0,
Base64 = 1,
Url = 2,
QRCode = 3,
Buffer = 4,
File = 5,
Stream = 6,
}
- Present A File by Abstracting It's Meta Information that supports Reading & toJSON() API.
- Follow DOM File/BLOB Interface
- Present a file that could be: Local, Remote, Stream
- Lazy load
- Serializable
- Can be Transfered from server to server, server to browser.
Node.js Documentation > URL Strings and URL Objects
┌─────────────────────────────────────────────────────────────────────────────────────────────┐
│ href │
├──────────┬──┬─────────────────────┬─────────────────────┬───────────────────────────┬───────┤
│ protocol │ │ auth │ host │ path │ hash │
│ │ │ ├──────────────┬──────┼──────────┬────────────────┤ │
│ │ │ │ hostname │ port │ pathname │ search │ │
│ │ │ │ │ │ ├─┬──────────────┤ │
│ │ │ │ │ │ │ │ query │ │
" https: // user : pass @ sub.host.com : 8080 /p/a/t/h ? query=string #hash "
│ │ │ │ │ hostname │ port │ │ │ │
│ │ │ │ ├──────────────┴──────┤ │ │ │
│ protocol │ │ username │ password │ host │ │ │ │
├──────────┴──┼──────────┴──────────┼─────────────────────┤ │ │ │
│ origin │ │ origin │ pathname │ search │ hash │
├─────────────┴─────────────────────┴─────────────────────┴──────────┴────────────────┴───────┤
│ href │
└─────────────────────────────────────────────────────────────────────────────────────────────┘
Node.js Documentation > path.parse(path)
┌─────────────────────┬────────────┐
│ dir │ base │
├──────┬ ├──────┬─────┤
│ root │ │ name │ ext │
" / home/user/dir / file .txt "
└──────┴──────────────┴──────┴─────┘
- Add
fileBox.type()
to return theFileBoxType
of a FileBox. (wechaty/wechaty#1918) - Change
Readable
tostream.Readable
for better compatibility. (Jun 27, 2020) - Add
chunkerTransformStream
totoStream
(#44)
Add support to JSON.stringify()
(#25):
FileBox.fromJSON()
- Static method for deserializationfileBox.toJSON()
- Instance method for serialization
- Add support to QR Code:
FileBox.fromQRCode()
andFileBox.toQRCode()
- Start using @chatie/tsconfig
- Add two new factory methods:
fromBase64()
,fromDataURL()
- Add
toBuffer()
,toBase64()
andtoDataURL()
to get the Buffer and BASE64 encoded file data - Add
metadata
property to store additional information. (#3)
- Add
headers
option forfromRemote()
method
Initial version.
- File API - W3C Working Draft, 26 October 2017
- MIME Sniffing - Living Standard — Last Updated 20 April 2018
- Using files from web applications
- Web technology for developers > Web APIs > File
- Web technology for developers > Web APIs > Blob
- Web technology for developers > Web APIs > FileReader
- A simple HTTP Request & Response Service.
- Hurl.it — Make HTTP Requests
This module is inspired by https://github.com/gulpjs/vinyl and DefinitelyTyped/DefinitelyTyped#12368 when I need a virtual File module for my Chatie project.
Huan LI (李卓桓), Microsoft AI MVP, zixia@zixia.net
- Docs released under Creative Commons
- Code released under the Apache-2.0 License
- Code & Docs © 2018 Huan LI <zixia@zixia.net>