Skip to content
This repository was archived by the owner on Mar 10, 2020. It is now read-only.

Commit 4f5bd62

Browse files
committed
feat: add support for File DOM API to files-regular
1 parent 0b8803f commit 4f5bd62

File tree

7 files changed

+60
-75
lines changed

7 files changed

+60
-75
lines changed

examples/upload-file-via-browser/.gitignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,3 +2,4 @@ node_modules
22
npm-debug.log
33
.DS_Store
44
dist
5+
yarn.lock

examples/upload-file-via-browser/package.json

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -16,8 +16,6 @@
1616
"@babel/preset-react": "^7.0.0",
1717
"eslint": "^5.16.0",
1818
"eslint-plugin-react": "^7.11.1",
19-
"ipfs-http-client": "../../",
20-
"pull-file-reader": "~1.0.2",
2119
"react": "~16.6.3",
2220
"react-dom": "~16.6.3",
2321
"webpack": "~4.30.0",

examples/upload-file-via-browser/src/App.js

Lines changed: 5 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -2,16 +2,13 @@
22
const React = require('react')
33
const ipfsClient = require('../../../src')
44

5-
// create a stream from a file, which enables uploads of big files without allocating memory twice
6-
const fileReaderPullStream = require('pull-file-reader')
7-
85
class App extends React.Component {
96
constructor () {
107
super()
118
this.state = {
129
added_file_hash: null
1310
}
14-
this.ipfs = ipfsClient('localhost', '50895')
11+
this.ipfs = ipfsClient('localhost', '58041')
1512

1613
// bind methods
1714
this.captureFile = this.captureFile.bind(this)
@@ -33,7 +30,7 @@ class App extends React.Component {
3330
// Add file to IPFS and return a CID
3431
saveToIpfs (files) {
3532
let ipfsId
36-
this.ipfs.add([...files][0], { progress: (prog) => console.log(`received: ${prog}`) })
33+
this.ipfs.add([...files], { progress: (prog) => console.log(`received: ${prog}`) })
3734
.then((response) => {
3835
console.log(response)
3936
ipfsId = response[0].hash
@@ -46,12 +43,12 @@ class App extends React.Component {
4643

4744
// Example #2
4845
// Add file to IPFS and wrap it in a directory to keep the original filename
49-
saveToIpfsWithFilename (file) {
46+
saveToIpfsWithFilename (files) {
47+
const file = [...files][0]
5048
let ipfsId
51-
const fileStream = fileReaderPullStream(file)
5249
const fileDetails = {
5350
path: file.name,
54-
content: fileStream
51+
content: file
5552
}
5653
const options = {
5754
wrapWithDirectory: true,

package.json

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -35,9 +35,11 @@
3535
"err-code": "^1.1.2",
3636
"flatmap": "0.0.3",
3737
"glob": "^7.1.3",
38+
"ipfs": "^0.35.0",
3839
"ipfs-block": "~0.8.0",
3940
"ipld-dag-cbor": "~0.13.1",
4041
"ipld-dag-pb": "~0.15.3",
42+
"ipfs-utils": "github:hugomrdias/js-ipfs-utils#master",
4143
"is-ipfs": "~0.6.0",
4244
"is-pull-stream": "0.0.0",
4345
"is-stream": "^1.1.0",
@@ -80,7 +82,7 @@
8082
"chai": "^4.2.0",
8183
"cross-env": "^5.2.0",
8284
"dirty-chai": "^2.0.1",
83-
"go-ipfs-dep": "~0.4.19",
85+
"go-ipfs-dep": "0.4.19",
8486
"interface-ipfs-core": "~0.99.0",
8587
"ipfsd-ctl": "~0.42.0",
8688
"nock": "^10.0.2",

src/files-regular/add.js

Lines changed: 6 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -2,12 +2,11 @@
22

33
const promisify = require('promisify-es6')
44
const ConcatStream = require('concat-stream')
5-
const kindOf = require('kind-of')
65
const once = require('once')
7-
const isStream = require('is-stream')
8-
const isSource = require('is-pull-stream').isSource
6+
const { isSource } = require('is-pull-stream')
97
const FileResultStreamConverter = require('../utils/file-result-stream-converter')
108
const SendFilesStream = require('../utils/send-files-stream')
9+
const validateAddInput = require('ipfs-utils/src/files/add-input-validation')
1110

1211
module.exports = (send) => {
1312
const createAddStream = SendFilesStream(send, 'add')
@@ -24,23 +23,10 @@ module.exports = (send) => {
2423
}
2524
options.converter = FileResultStreamConverter
2625

27-
// Buffer, pull stream or Node.js stream
28-
const isBufferOrStream = obj => Buffer.isBuffer(obj) || isStream.readable(obj) || isSource(obj)
29-
// An object like { content?, path? }, where content isBufferOrStream and path isString
30-
const isContentObject = obj => {
31-
if (typeof obj !== 'object') return false
32-
// path is optional if content is present
33-
if (obj.content) return isBufferOrStream(obj.content)
34-
// path must be a non-empty string if no content
35-
return Boolean(obj.path) && typeof obj.path === 'string'
36-
}
37-
// An input atom: a buffer, stream or content object
38-
const isInput = obj => isBufferOrStream(obj) || isContentObject(obj) || kindOf(_files) === 'file'
39-
// All is ok if data isInput or data is an array of isInput
40-
const ok = isInput(_files) || (Array.isArray(_files) && _files.every(isInput))
41-
42-
if (!ok) {
43-
return callback(new Error('invalid input: expected buffer, readable stream, pull stream, object or array of objects'))
26+
try {
27+
validateAddInput(_files)
28+
} catch (err) {
29+
return callback(err)
4430
}
4531

4632
const files = [].concat(_files)

src/utils/multipart.js

Lines changed: 0 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -77,12 +77,7 @@ class Multipart extends Transform {
7777
return callback() // early
7878
}
7979

80-
if (isSource(content)) {
81-
content = toStream.readable(content)
82-
}
83-
8480
// From now on we assume content is a stream
85-
8681
content.once('error', this.emit.bind(this, 'error'))
8782

8883
content.once('end', () => {

src/utils/prepare-file.js

Lines changed: 45 additions & 39 deletions
Original file line numberDiff line numberDiff line change
@@ -2,11 +2,14 @@
22

33
const isNode = require('detect-node')
44
const flatmap = require('flatmap')
5-
const { Readable } = require('stream')
5+
const { Readable } = require('readable-stream')
66
const kindOf = require('kind-of')
7+
const { isSource } = require('is-pull-stream')
8+
const isStream = require('is-stream')
9+
const pullToStream = require('pull-to-stream')
10+
const { supportsFileReader } = require('ipfs-utils/src/supports')
11+
const streamFromFileReader = require('ipfs-utils/src/streams/stream-from-filereader')
712

8-
// eslint-disable-next-line no-undef
9-
const supportsFileReader = FileReader in self
1013
function loadPaths (opts, file) {
1114
const path = require('path')
1215
const fs = require('fs')
@@ -77,38 +80,36 @@ function loadPaths (opts, file) {
7780
}
7881
}
7982

80-
function streamFromFileReader (file) {
81-
class FileStream extends Readable {
82-
constructor (file, options = {}) {
83-
super(options)
84-
this.offset = 0
85-
this.chunkSize = 1024 * 1024
86-
this.fileReader = new self.FileReader(file)
87-
this.fileReader.onloadend = (event) => {
88-
const data = event.target.result
89-
if (data.byteLength === 0) {
90-
this.push(null)
91-
}
92-
this.push(new Uint8Array(data))
83+
function contentToStream (content) {
84+
if (supportsFileReader && kindOf(content) === 'file') {
85+
return streamFromFileReader(content)
86+
}
87+
88+
if (kindOf(content) === 'buffer') {
89+
return new Readable({
90+
read () {
91+
this.push(content)
92+
this.push(null)
9393
}
94-
this.fileReader.onerror = (err) => this.emit('error', err)
95-
}
94+
})
95+
}
9696

97-
_read (size) {
98-
const end = this.offset + this.chunkSize
99-
const slice = file.slice(this.offset, end)
100-
this.fileReader.readAsArrayBuffer(slice)
101-
this.offset = end
102-
}
97+
if (isSource(content)) {
98+
return pullToStream.readable(content)
10399
}
104100

105-
return new FileStream(file)
101+
if (isStream.readable(content)) {
102+
return content
103+
}
104+
105+
throw new Error(`Input not supported. Expected Buffer|ReadableStream|PullStream|File got ${kindOf(content)}. Check the documentation for more info https://github.com/ipfs/interface-js-ipfs-core/blob/master/SPEC/FILES.md#add`)
106106
}
107107

108108
function prepareFile (file, opts) {
109109
let files = [].concat(file)
110110

111111
return flatmap(files, (file) => {
112+
// add from fs with file path
112113
if (typeof file === 'string') {
113114
if (!isNode) {
114115
throw new Error('Can only add file paths in node')
@@ -117,29 +118,34 @@ function prepareFile (file, opts) {
117118
return loadPaths(opts, file)
118119
}
119120

120-
if (file.path && !file.content) {
121-
file.dir = true
122-
return file
123-
}
121+
// add with object syntax { path : <string> , content: <Buffer|ReadableStream|PullStream|File }
122+
if (kindOf(file) === 'object') {
123+
// treat as an empty directory when path is a string and content undefined
124+
if (file.path && kindOf(file.path) === 'string' && !file.content) {
125+
file.dir = true
126+
return file
127+
}
124128

125-
if (file.content || file.dir) {
126-
return file
127-
}
129+
// just return when directory
130+
if (file.dir) {
131+
return file
132+
}
128133

129-
if (supportsFileReader && kindOf(file) === 'file') {
130-
return {
131-
path: '',
132-
symlink: false,
133-
dir: false,
134-
content: streamFromFileReader(file, opts)
134+
if (file.content) {
135+
return {
136+
path: file.path || '',
137+
symlink: false,
138+
dir: false,
139+
content: contentToStream(file.content)
140+
}
135141
}
136142
}
137143

138144
return {
139145
path: '',
140146
symlink: false,
141147
dir: false,
142-
content: file
148+
content: contentToStream(file)
143149
}
144150
})
145151
}

0 commit comments

Comments
 (0)