mirror of
https://github.com/Permissionless-Software-Foundation/ipfs-bch-wallet-consumer.git
synced 2026-09-21 16:52:03 -07:00
Merge pull request #68 from Permissionless-Software-Foundation/ct-unstable
feat(GET /ipfs/download/:cid): Download CID as readable stream
This commit is contained in:
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"password": "yKm2qMy2LkRNFJsCiD2B",
|
||||
"password": "BJdugaoiq10ZJnA7Uskd",
|
||||
"email": "system@system.com",
|
||||
"id": "67bb5a07da0eb4a2e7fc7bde",
|
||||
"token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpZCI6IjY3YmI1YTA3ZGEwZWI0YTJlN2ZjN2JkZSIsImlhdCI6MTc0MDMzMTUyN30.o-MDjJpoq2MNElzWQsrWjy-kL_wji2hxPrXLPomrw7I"
|
||||
"id": "67c114fd4935ba05e48f6bb2",
|
||||
"token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpZCI6IjY3YzExNGZkNDkzNWJhMDVlNDhmNmJiMiIsImlhdCI6MTc0MDcwNzA2OX0.R5nU8J5yhGorp7I5kc8_dRESbo4hwCIrTtqJiVYVhLA"
|
||||
}
|
||||
@@ -45,6 +45,9 @@ class IpfsFilesAdapter {
|
||||
this.rpcHandler = this.rpcHandler.bind(this)
|
||||
this.getStatus = this.getStatus.bind(this)
|
||||
this.selectProvider = this.selectProvider.bind(this)
|
||||
this.getFileMetadata = this.getFileMetadata.bind(this)
|
||||
this.getPins = this.getPins.bind(this)
|
||||
this.waitForRPCResponse = this.waitForRPCResponse.bind(this)
|
||||
}
|
||||
|
||||
// This handler is triggered when RPC data comes in over IPFS.
|
||||
@@ -120,7 +123,7 @@ class IpfsFilesAdapter {
|
||||
return true
|
||||
} catch (err) {
|
||||
// console.log('createUser() error: ', err)
|
||||
wlogger.error('Error in adapters/files/getStatus()')
|
||||
wlogger.error('Error in adapters/files/selectProvider()')
|
||||
throw err
|
||||
}
|
||||
}
|
||||
|
||||
@@ -40,6 +40,7 @@ class IpfsRESTControllerLib {
|
||||
this.getFileInfo = this.getFileInfo.bind(this)
|
||||
this.getPins = this.getPins.bind(this)
|
||||
this.cid2json = this.cid2json.bind(this)
|
||||
this.downloadFile = this.downloadFile.bind(this)
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -165,12 +166,34 @@ class IpfsRESTControllerLib {
|
||||
)
|
||||
ctx.body = readStream
|
||||
} catch (err) {
|
||||
// wlogger.error('Error in ipfs/controller.js/viewFile(): ', err)
|
||||
console.log('Error in ipfs/controller.js/viewFile(): ', err)
|
||||
this.handleError(ctx, err)
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @api {get} /ipfs/download/:cid Download a file via its IPFS CID
|
||||
* @apiPermission public
|
||||
* @apiName GetCidDownload
|
||||
* @apiGroup REST IPFS
|
||||
* @apiDescription Download a file via its IPFS CID. Returns a readable stream.
|
||||
*
|
||||
* @apiExample Example usage:
|
||||
* curl -H "Content-Type: application/json" -X GET localhost:5001/ipfs/download/bafkreieaqtdhfywyddomswogynzymukosqqgqo7lkt5lch2zwfnc55m6om
|
||||
*/
|
||||
async downloadFile (ctx) {
|
||||
try {
|
||||
const { cid } = ctx.params
|
||||
|
||||
const { readStream } = await this.useCases.ipfs.downloadCid({ cid })
|
||||
|
||||
ctx.body = readStream
|
||||
} catch (err) {
|
||||
console.log('Error in ipfs/controller.js/downloadFile(): ', err)
|
||||
this.handleError(ctx, err)
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @api {get} /ipfs/service Get the IPFS ID for the File Pin service
|
||||
* @apiPermission public
|
||||
@@ -192,7 +215,7 @@ class IpfsRESTControllerLib {
|
||||
selectedIpfsFileProvider
|
||||
}
|
||||
} catch (err) {
|
||||
// wlogger.error('Error in ipfs/controller.js/viewFile(): ', err)
|
||||
// wlogger.error('Error in ipfs/controller.js/getService(): ', err)
|
||||
console.log('Error in ipfs/controller.js/getService(): ', err)
|
||||
this.handleError(ctx, err)
|
||||
}
|
||||
@@ -220,7 +243,6 @@ class IpfsRESTControllerLib {
|
||||
|
||||
ctx.body = metadata
|
||||
} catch (err) {
|
||||
// wlogger.error('Error in ipfs/controller.js/viewFile(): ', err)
|
||||
console.log('Error in ipfs/controller.js/getFileInfo(): ', err)
|
||||
this.handleError(ctx, err)
|
||||
}
|
||||
@@ -248,7 +270,6 @@ class IpfsRESTControllerLib {
|
||||
|
||||
ctx.body = pinData
|
||||
} catch (err) {
|
||||
// wlogger.error('Error in ipfs/controller.js/viewFile(): ', err)
|
||||
console.log('Error in ipfs/controller.js/getPins(): ', err)
|
||||
this.handleError(ctx, err)
|
||||
}
|
||||
@@ -274,7 +295,6 @@ class IpfsRESTControllerLib {
|
||||
|
||||
ctx.body = json
|
||||
} catch (err) {
|
||||
// wlogger.error('Error in ipfs/controller.js/viewFile(): ', err)
|
||||
console.log('Error in ipfs/controller.js/cid2json(): ', err.message)
|
||||
this.handleError(ctx, err)
|
||||
}
|
||||
|
||||
@@ -57,6 +57,7 @@ class IpfsRouter {
|
||||
this.router.post('/connect', this.ipfsRESTController.connect)
|
||||
this.router.get('/node', this.ipfsRESTController.getThisNode)
|
||||
this.router.get('/view/:cid', this.ipfsRESTController.viewFile)
|
||||
this.router.get('/download/:cid', this.ipfsRESTController.downloadFile)
|
||||
this.router.get('/service', this.ipfsRESTController.getService)
|
||||
this.router.get('/file-info/:cid', this.ipfsRESTController.getFileInfo)
|
||||
this.router.get('/pins', this.ipfsRESTController.getPins)
|
||||
|
||||
@@ -9,6 +9,7 @@
|
||||
// import { exporter } from 'ipfs-unixfs-exporter'
|
||||
import { Duplex } from 'stream'
|
||||
import PSFFPP from 'psffpp'
|
||||
import { CID } from 'multiformats'
|
||||
|
||||
// Local libraries
|
||||
// import PinEntity from '../entities/pin.js'
|
||||
@@ -28,11 +29,13 @@ class IpfsUseCases {
|
||||
|
||||
// Encapsulate dependencies
|
||||
this.psffpp = null // placeholder
|
||||
this.CID = CID
|
||||
|
||||
// Bind 'this' object to all class subfunctions.
|
||||
this.downloadCid = this.downloadCid.bind(this)
|
||||
// this.downloadCid2 = this.downloadCid2.bind(this)
|
||||
this.getWritePrice = this.getWritePrice.bind(this)
|
||||
this.getCidMetadata = this.getCidMetadata.bind(this)
|
||||
this.cid2json = this.cid2json.bind(this)
|
||||
|
||||
// State
|
||||
@@ -43,7 +46,7 @@ class IpfsUseCases {
|
||||
// Returns a readable stream.
|
||||
async downloadCid (inObj = {}) {
|
||||
try {
|
||||
const { cid } = inObj
|
||||
let { cid } = inObj
|
||||
|
||||
if (!cid) throw new Error('CID is undefined')
|
||||
|
||||
@@ -64,6 +67,47 @@ class IpfsUseCases {
|
||||
|
||||
const helia = this.adapters.ipfs.ipfs
|
||||
|
||||
const cidClass = this.CID.parse(cid)
|
||||
|
||||
// Download the file from other nodes.
|
||||
await helia.blockstore.get(cidClass)
|
||||
|
||||
// list cid content, to dermine if this is a file-based or directory-based CID.
|
||||
const contentArray = []
|
||||
for await (const file of helia.fs.ls(cid)) {
|
||||
contentArray.push(file)
|
||||
}
|
||||
|
||||
// Handle directory-based CIDs. This is used by Token Tiger for mutable and immutable token data.
|
||||
/**
|
||||
* If the cid is a directory
|
||||
* The next block of code sends a html page with a list of links with the file names into the directory.
|
||||
* Skipping this code delivers directly the first file detected in the directory.
|
||||
*/
|
||||
const isDir = contentArray[0].path.match('/') // TODO : looking for a better way to detect if is a directory
|
||||
// 'listDir' is a flag to ignore this code on /download endpoint.
|
||||
if (isDir) {
|
||||
console.log('This CID is a directory. contentArray[0]: ', contentArray[0])
|
||||
cid = `${cid}/${contentArray[0].name}`
|
||||
|
||||
// throw new Error('CID is a directory. Not supported yet.')
|
||||
// const stream = new Stream.Readable({ read () { } })
|
||||
// for (let i = 0; i < contentArray.length; i++) {
|
||||
// const cont = contentArray[i]
|
||||
// // List all paths excluding root path.
|
||||
// if (cont.path !== cid) {
|
||||
// // Add links to the gateway with the format cid/:filename
|
||||
// stream.push(`<a href='${this.config.domainName}/ipfs/view/${cid}/${cont.name}' >/${cont.name} ( CID: ${cont.cid} )</a><hr />`)
|
||||
// }
|
||||
// }
|
||||
|
||||
// stream.push(null)
|
||||
// // return fileName as html because the controller the library <mime.lookup> sends it as html
|
||||
// return { readStream: stream }
|
||||
} else {
|
||||
console.log('This CID is not a directory.')
|
||||
}
|
||||
|
||||
// Convert the file to a Buffer.
|
||||
const fileChunks = []
|
||||
for await (const chunk of helia.fs.cat(cid)) {
|
||||
|
||||
Reference in New Issue
Block a user