Skip to content
This repository has been archived by the owner on Feb 12, 2024. It is now read-only.

Commit

Permalink
docs(example): create an example of cat'ing files added from ipfs CLI
Browse files Browse the repository at this point in the history
using only webrtc-star as a transport
  • Loading branch information
haadcode authored and daviddias committed Jan 25, 2017
1 parent 5078ddc commit 4c5443a
Show file tree
Hide file tree
Showing 8 changed files with 514 additions and 0 deletions.
2 changes: 2 additions & 0 deletions examples/access-go-ipfs-files/cat-a-file/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
node_modules/
public/ipfs.js
90 changes: 90 additions & 0 deletions examples/access-go-ipfs-files/cat-a-file/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,90 @@
# access-go-ipfs-files - cat-a-file

**WIP**

## TODO

- Add "connect to peer" input field and "connect" button under the "Peers" section in index.html
- Add `connectToPeer` function which calls `ipfs.swarm.connect(multiaddr)`. See https://github.com/ipfs/js-ipfs/blob/b0a7cd83cbf146b0f147467dedc686f94a5f751f/examples/ipfm/src/DataStore.js#L82 and https://github.com/ipfs/js-ipfs/blob/b0a7cd83cbf146b0f147467dedc686f94a5f751f/examples/ipfm/README.md#start-an-interplanetary-file-exchange-daemon. The multiaddr to connect to looks like this: `/ip4/127.0.0.1/tcp/9999/ws/ipfs/QmZGH8GeASSkSZoNLPEBu1MqtzLTERNUEwh9yTHLEF5kcW`
- Hook up "connect" button's click event to `connectToPeer` function
- Add instructions to this README on how to add a file in go-ipfs
- Add instructions to this README on how to cat it in the UI
- Make sure the "Start a go-ipfs daemon" instructions are correct
- Make sure go-ipfs daemon and the example connect to each other

## Step-by-step Instructions

### Start a go-ipfs daemon

1. Install go-ipfs from master (TODO: link).

2. Run `ipfs init`

3. Edit your IPFS config file, located at `~/.ipfs/config`

4. Add a Websocket listener address to `Addresses.Swarm`. It should look like this after editing:
```
"Addresses": {
"API": "/ip4/127.0.0.1/tcp/5001",
"Gateway": "/ip4/0.0.0.0/tcp/8080",
"Swarm": [
"/ip4/0.0.0.0/tcp/4001",
"/ip4/0.0.0.0/tcp/9999/ws"
]
},
```

5. Start the go-ipfs daemon with:
```
ipfs daemon
```

6. You should see the Websocket address in the output:
```
Initializing daemon...
Swarm listening on /ip4/127.0.0.1/tcp/4001
Swarm listening on /ip4/127.0.0.1/tcp/9999/ws
Swarm listening on /ip4/192.168.10.38/tcp/4001
Swarm listening on /ip4/192.168.10.38/tcp/9999/ws
API server listening on /ip4/127.0.0.1/tcp/5001
Gateway (readonly) server listening on /ip4/0.0.0.0/tcp/8080
Daemon is ready
```

If you see address like `Swarm listening on /ip4/127.0.0.1/tcp/9999/ws`, it means all good!

## Start the example

**NOTE!** Before running the examples, you need to build `js-ipfs`. You can do this by following the instructions in https://github.com/ipfs/js-ipfs#clone-and-install-dependnecies and then building it as per https://github.com/ipfs/js-ipfs#build-a-dist-version.

```
npm install
npm start
```

Open http://127.0.0.1:8080 in a browser.

**TODO: add instructions how to cat a hash in the UI.**

## Tutorial

Steps
1. create IPFS instance

TODO. See `./start-ipfs.js`

3. add a file in go-ipfs
4. copy file's hash
5. ipfs.files.cat

TODO. add ipfs.files.cat code examples from index.html

6. output the buffer to <img>

```
...
stream.on('end', () => {
const blob = new Blob(buf)
picture.src = URL.createObjectURL(blob)
})
```
14 changes: 14 additions & 0 deletions examples/access-go-ipfs-files/cat-a-file/package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
{
"name": "cat-a-file",
"version": "1.0.0",
"description": "",
"scripts": {
"postinstall": "cp ../../../dist/index.js ./public/ipfs.js",
"start": "http-server -c-1"
},
"author": "Haad",
"license": "MIT",
"devDependencies": {
"http-server": "^0.9.0"
}
}
281 changes: 281 additions & 0 deletions examples/access-go-ipfs-files/cat-a-file/public/index.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,281 @@
<html>
<head>
<meta charset="utf-8">
<link rel="stylesheet" href="styles.css">
<!-- Include IPFS -->
<script src="ipfs.js"></script>
<!-- Include a helper script that starts IPFS -->
<script type="text/javascript" src="start-ipfs.js" charset="utf-8"></script>
</head>

<body>
<div class="center">
<div id="ipfs" class="ipfs" ondragover="event.preventDefault()">
<h1 id="state" class="center"></h1>
<div>
<div id="buttons" class="buttons center">
<button id="start" type="button">Start</button>
<button id="stop" type="button">Stop</button>
</div>
<div id="directory">
<h2>IPFS Settings</h2>
<label for="dir">Data Directory</label>
<input id="dir" type="text" placeholder="IPFS data directory"/>
<br><br>
<label for="signalServerInput">Signal Server</label>
<input id="signalServerInput" type="text" value="188.166.203.82:20000"/>
</div>
</div>
<div id="details"></div>
<div id="peers"></div>
<div id="files">
<h2>Files</h2>
<div id="filesStatus"></div>
<br>
<label for="multihash">Mutihash</label>
<input id="multihash" type="text" placeholder="Multihash"/>
<button id="cat" type="button">Cat</button>
<img id="picture"/>
</div>
<pre id="errors"></pre>
</div>
</div>

<script type="text/javascript">
const rootElement = document.getElementById("ipfs")
const startButton = document.getElementById("start")
const stopButton = document.getElementById("stop")
const output = document.getElementById("state")
const details = document.getElementById("details")
const peers = document.getElementById("peers")
const errors = document.getElementById("errors")
const directory = document.getElementById("directory")
const dirInput = document.getElementById("dir")
const signalServerInput = document.getElementById("signalServerInput")
const files = document.getElementById("files")
const filesStatus = document.getElementById("filesStatus")
const picture = document.getElementById("picture")
const multihashInput = document.getElementById("multihash")
const catButton = document.getElementById("cat")

let ipfs, peerInfo, pollPeersTimer

const ipfsOptions = {
// Directory to which save IPFS data to
IpfsDataDir: dirInput.value,
// IPFS dev server: webrtc-star-signalling.cloud.ipfs.team
SignalServer: signalServerInput.value,
// Local webrtc-star server, you can get it from:
// https://github.com/libp2p/js-libp2p-webrtc-star
// SignalServer: '127.0.0.1:9090',
}

// Start IPFS instance
const start = () => {
if (!ipfs) {
// Update the UI with initial settings
updateView('starting', ipfs)

// Create an IPFS instance
// window.startIpfs() is exposed in ./start-ipfs.js
window.startIpfs(ipfsOptions, (err, node) => {
if (err) {
onError(err)
return
}

ipfs = node

// Get our IPFS instance's info: ID and address
ipfs.id().then((id) => {
peerInfo = id
// Update the UI
updateView('ready', ipfs)

// Poll for peers from IPFS and display them
pollPeersTimer = setInterval(updatePeers, 1000)
peers.innerHTML = '<h2>Peers</h2><i>Waiting for peers...</i>'
})
})
}
}

// Stop IPFS instance
const stop = () => {
if (ipfs) {
if (pollPeersTimer)
clearInterval(pollPeersTimer)

ipfs.goOffline()
ipfs = null
updateView('stopped', ipfs)
}
}

// Fetch file contents from IPFS and display it
const catFile = () => {
// Get the hash to cat from the input field
const multihash = multihashInput.value

// Update UI
picture.innerHTML = multihash ? '<i>Loading...</i>' : ''
picture.className = multihash ? 'picture visible' : 'hidden'
errors.className = 'hidden'

// Get the file from IPFS
if (multihash) {
// IPFS.files.cat()
// https://github.com/ipfs/interface-ipfs-core/tree/master/API/files#javascript---ipfscatmultihash-callback
ipfs.files.cat(multihash)
.then((stream) => {
// Buffer all contents of the file as text
// and once buffered, create a blob for the picture
let buf = []
stream.on('data', (d) => buf.push(d))
stream.on('end', () => {
const blob = new Blob(buf)
picture.src = URL.createObjectURL(blob)
})
})
.catch(onError)
}
}

// Display an error
const onError = (e) => {
console.error(e)
errors.innerHTML = '<br/><span class="error">' + e.stack + '</span>'
errors.className = 'error visible'
}

// Handle file drop
const onDrop = (event) => {
picture.innerHTML = ''
picture.className = 'hidden'
errors.className = 'hidden'

event.preventDefault()
var dt = event.dataTransfer
var files = dt.files

const readFileContents = (file) => {
return new Promise((resolve) => {
const reader = new FileReader()
reader.onload = (event) => resolve(event.target.result)
reader.readAsArrayBuffer(file)
})
}

// TODO: Promise reduce?
for (var i = 0; i < files.length; i++) {
const file = files[i]
console.log("Add file", file.name, file.size)
readFileContents(file)
.then((buffer) => {
// IPFS.files.add()
// https://github.com/ipfs/interface-ipfs-core/tree/master/API/files#javascript---ipfsfilesadddata-options-callback
return ipfs.files.add([{
path: file.name,
content: new ipfs.types.Buffer(buffer)
}])
})
.then((files) => {
console.log("Files added", files)
multihashInput.value = files[0].hash
filesStatus.innerHTML = files
.map((e) => `Added ${e.path} as ${e.hash}`)
.join('<br>')
})
.catch(onError)
}
}

// Get peers from IPFS and display them
const updatePeers = () => {
ipfs.swarm.peers((err, res) => {
// PeerId.toJSON()
// https://github.com/libp2p/js-peer-id/blob/3ef704ba32a97a9da26a1f821702cdd3f09c778f/src/index.js#L106
// Multiaddr.toString()
// https://multiformats.github.io/js-multiaddr/#multiaddrtostring
const peersAsHtml = res
.map((e, idx) => {
return (idx + 1) + '.'
+ e.peer.id.toJSON().id
+ '<br>'
+ e.addr.toString()
+ '<br>'
})
.join('')

peers.innerHTML = res.length > 0
? '<h2>Peers</h2>' + peersAsHtml
: '<h2>Peers</h2><i>Waiting for peers...</i>'
})
}

/* UI functions */
function initView() {
const initElement = (e, className) => {
e.innerHTML = ''
e.className = className
}

// Initial view
const elements = [errors, details, peers]
elements.map((e) => initElement(e, 'hidden'))
errors.innerHTML = ''
output.innerHTML = '🔌 IPFS stopped'
dirInput.value = '/ipfs/' + new Date().getTime()
directory.className = 'visible'
files.className = 'hidden'
filesStatus.innerHTML = ''
picture.innerHTML = ''
startButton.disabled = false
stopButton.disabled = true
multihashInput.value = null
picture.className = 'hidden'
// Remove old event listeners
rootElement.removeEventListener('drop', onDrop)
startButton.removeEventListener('click', start)
stopButton.removeEventListener('click', stop)
catButton.removeEventListener('click', catFile)
// Setup event listeners for interaction
rootElement.addEventListener('drop', onDrop)
startButton.addEventListener('click', start)
stopButton.addEventListener('click', stop)
catButton.addEventListener('click', catFile)
}

function updateView(state, ipfs) {
if (state === 'ready') {
// Set the header to display the current state
output.innerHTML = '🚀 IPFS started'
// Display IPFS info
details.innerHTML = '<div>'
+ '<h2>IPFS Node</h2>'
+ '<b>ID</b><br>'
+ peerInfo.id + '<br><br>'
+ '<b>Address</b><br>'
+ peerInfo.addresses[0] + '<br><br>'
+ '<b>IPFS Data Directory</b><br>'
+ dirInput.value
// Set the file status
filesStatus.innerHTML = '<i>Drop a picture here to add it to IPFS.</i>'
details.className = 'visible'
peers.className = 'visible'
files.className = 'visible'
stopButton.disabled = false
} else if (state === 'starting') {
output.innerHTML = '📡 IPFS starting'
startButton.disabled = true
directory.className = 'hidden'
} else if (state === 'stopped') {
initView()
}
}

// Start the app
initView()
</script>
</body>
</html>
Loading

0 comments on commit 4c5443a

Please sign in to comment.