1
1
'use strict'
2
2
3
- const resources = require ( './../resources' )
4
- const mfs = require ( 'ipfs-mfs/http' )
5
3
const fs = require ( 'fs' )
6
4
const path = require ( 'path' )
7
5
const tempy = require ( 'tempy' )
6
+ const del = require ( 'del' )
7
+ const StreamConcat = require ( 'stream-concat' )
8
+ const boom = require ( 'boom' )
9
+ const glob = require ( 'fast-glob' )
8
10
const multipart = require ( 'ipfs-multipart' )
9
11
const toPull = require ( 'stream-to-pull-stream' )
10
12
const toStream = require ( 'pull-stream-to-stream' )
11
13
const pull = require ( 'pull-stream' )
12
14
const pushable = require ( 'pull-pushable' )
13
15
const abortable = require ( 'pull-abortable' )
14
16
const { serialize } = require ( 'pull-ndjson' )
17
+ const mfs = require ( 'ipfs-mfs/http' )
18
+ const resources = require ( './../resources' )
15
19
16
- const streams = [ ]
17
20
const filesDir = tempy . directory ( )
18
21
19
- const createMultipartReply = ( readStream , boundary , ipfs , query , reply ) => {
22
+ const createMultipartReply = ( readStream , boundary , ipfs , query , reply , cb ) => {
20
23
const fileAdder = pushable ( )
21
24
const parser = new multipart . Parser ( { boundary : boundary } )
22
25
23
26
readStream . pipe ( parser )
24
27
25
28
parser . on ( 'file' , ( fileName , fileStream ) => {
26
- console . log ( 'File: ' , fileName )
27
29
fileAdder . push ( {
28
30
path : decodeURIComponent ( fileName ) ,
29
31
content : toPull ( fileStream )
@@ -38,7 +40,6 @@ const createMultipartReply = (readStream, boundary, ipfs, query, reply) => {
38
40
} )
39
41
40
42
parser . on ( 'end' , ( ) => {
41
- console . log ( 'multipart end' )
42
43
fileAdder . end ( )
43
44
} )
44
45
@@ -94,10 +95,9 @@ const createMultipartReply = (readStream, boundary, ipfs, query, reply) => {
94
95
}
95
96
files . forEach ( ( f ) => pushStream . push ( f ) )
96
97
pushStream . end ( )
98
+ cb ( )
97
99
} )
98
100
)
99
-
100
- return parser
101
101
}
102
102
module . exports = ( server ) => {
103
103
const api = server . select ( 'API' )
@@ -142,7 +142,6 @@ module.exports = (server) => {
142
142
} )
143
143
144
144
api . route ( {
145
- // TODO fix method
146
145
method : 'POST' ,
147
146
path : '/api/v0/add-chunked' ,
148
147
config : {
@@ -151,65 +150,59 @@ module.exports = (server) => {
151
150
maxBytes : 10485760
152
151
} ,
153
152
handler : ( request , reply ) => {
154
- console . log ( 'received' )
155
- console . log ( request . headers [ 'content-range' ] )
156
- console . log ( request . headers [ 'x-ipfs-chunk-index' ] )
157
- console . log ( request . headers [ 'x-ipfs-chunk-group-uuid' ] )
153
+ // console.log('received')
154
+ // console.log(request.headers['content-range'])
155
+ // console.log(request.headers['x-ipfs-chunk-index'])
156
+ // console.log(request.headers['x-ipfs-chunk-group-uuid'])
158
157
const boundary = request . headers [ 'x-ipfs-chunk-boundary' ]
159
- const id = request . headers [ 'x-ipfs-chunk-group-uuid' ] // change name to id
158
+ const id = request . headers [ 'x-ipfs-chunk-group-uuid' ]
160
159
const index = Number ( request . headers [ 'x-ipfs-chunk-index' ] )
161
- const file = path . join ( filesDir , id )
160
+ const file = path . join ( filesDir , id ) + '-' + index
162
161
const match = request . headers [ 'content-range' ] . match ( / ( \d + ) - ( \d + ) \/ ( \d + | \* ) / )
163
162
const ipfs = request . server . app . ipfs
164
- // if (!match || !match[1] || !match[2] || !match[3]) {
165
- /* malformed content-range header */
166
- // res.send('Bad Request', 400)
167
- // return;
168
- // }
163
+
164
+ if ( ! match || ! match [ 1 ] || ! match [ 2 ] || ! match [ 3 ] ) {
165
+ return boom . badRequest ( 'malformed content-range header' )
166
+ }
169
167
170
168
const start = parseInt ( match [ 1 ] )
171
169
const end = parseInt ( match [ 2 ] )
172
170
const total = parseInt ( match [ 3 ] )
173
- // console.log(start, end, total, index, boundary)
174
171
175
- let stream = streams [ id ]
176
- if ( ! stream ) {
177
- console . log ( 'create new stream' , file )
178
- stream = fs . createWriteStream ( file , { flags : 'a+' } )
179
- streams [ id ] = stream
180
- }
181
-
182
- console . log ( 'stream' , file )
183
- let size = 0
184
- if ( fs . existsSync ( file ) ) {
185
- size = fs . statSync ( file ) . size
186
- }
187
-
188
- if ( ( end + 1 ) === size ) {
189
- /* duplicate chunk */
190
- // res.send('Created', 201)
191
- // return;
192
- }
193
-
194
- if ( start !== size ) {
195
- /* missing chunk */
196
- // res.send('Bad Request', 400)
197
- // return;
198
- }
172
+ // TODO validate duplicates, missing chunks
199
173
200
174
if ( start === total ) {
201
- // check if size + payload.length === total
202
175
/* all chunks have been received */
203
- stream . on ( 'finish' , function ( ) {
204
- console . log ( 'add to ipfs from the file' )
205
- var readStream = fs . createReadStream ( file )
206
- createMultipartReply ( readStream , boundary , ipfs , request . query , reply )
176
+ const base = path . join ( filesDir , id ) + '-'
177
+ const pattern = base + '*'
178
+ const files = glob . sync ( pattern )
179
+
180
+ files . sort ( ( a , b ) => {
181
+ return Number ( a . replace ( base , '' ) ) - Number ( b . replace ( base , '' ) )
207
182
} )
208
183
209
- stream . end ( )
184
+ let fileIndex = 0
185
+ const nextStream = ( ) => fileIndex === files . length ? null : fs . createReadStream ( files [ fileIndex ++ ] )
186
+ createMultipartReply (
187
+ new StreamConcat ( nextStream ) ,
188
+ boundary ,
189
+ ipfs ,
190
+ request . query ,
191
+ reply ,
192
+ ( ) => {
193
+ console . log ( 'Finished adding' )
194
+ del ( pattern , { force : true } )
195
+ . then ( paths => {
196
+ console . log ( 'Deleted files and folders:\n' , paths . join ( '\n' ) )
197
+ } )
198
+ . catch ( console . error )
199
+ }
200
+ )
210
201
} else {
202
+ const stream = fs . createWriteStream ( file )
211
203
stream . write ( request . payload )
212
- /* this chunk has been processed successfully */
204
+
205
+ // TODO handle errors
213
206
reply ( { Bytes : request . payload . length } )
214
207
}
215
208
}
0 commit comments