【IPFS相关】构建可加载图片的分布式应用程序

本文由IPFS原力区收集译制

 

分布式应用程序(DApps)是在计算机的P2P网络上运行的应用程序,而不是单个计算机,其代码库是公开开放的,作为可供访问和定制的开源。DApps分布在多个服务器上,而不是位于集中式服务器上,这有助于管理大量数据和流量需求。

 

【IPFS相关】构建可加载图片的分布式应用程序

 

比特币是分布式应用程序的一个例子,由于最近获得的兴趣,我们将更多地讨论它。

 

【IPFS相关】构建可加载图片的分布式应用程序

Blockchain并不是关于Cryptocurrencies(加密货币)和ICO(代币发行)人们认为的,围绕它的技术是令人着迷的。

“区块链是一个不可摧毁的经济交易数字分类账,可编程记录不仅仅是金融交易,而是几乎所有有价值的东西。”Don&Alex Tapscott,作者Blockchain Revolution(2016)

这正是区块链的所在。区块链上的信息作为共享 – 并且不断调和 – 数据库存在,这意味着互联网上的每个人都可以访问数据。

使用区块链存储大型文件或数据是很昂贵的,我们在InterPlanetary文件系统(IPFS)上保存大型文件,之后我们将哈希存储在区块链上。

InterPlanetary文件系统是一种协议和网络,旨在创建一种内容可寻址的点对点方法,用于在分布式文件系统中存储和共享超媒体

 

【IPFS相关】构建可加载图片的分布式应用程序

 

“IPFS和Blockchain完美匹配!您可以使用IPFS处理大量数据,并将不可变的永久IPFS链接放入区块链事务中。这个时间戳和保护您的内容,而不必将数据放在链本身上。“作者Michael Chan

现在我们了解所有区块链的全部内容。让我们构建一些东西!我们将构建一个允许用户上传图片的移动应用程序,该图片保存在IPFS上,并将IPFS哈希值保存在以太坊区块链上。

如何构建它:

Prequisite:

  1. Node.js  :它是基于谷歌Chrome的JavaScript引擎(V8引擎)构建的服务器端平台

  2. MetaMask:它是一个桥梁,允许您今天在浏览器中访问明天的分布式网络。它允许您直接在浏览器中运行Ethereum dApp,而无需运行完整的以太坊节点

  3. 松露:它是以太坊的一个开发环境,它提供了一系列工具,如ganache-core,它模拟了localhost中的以太网网络,非常适合入门。

  4. Web3:它是一组库,允许您使用HTTP或IPC连接与本地或远程以太它节点进行交互 。此处提供了更多信息。

因此,服务器将构建在Node.js和具有React-native的移动应用程序上。

我们将从编写一个获取并保存哈希的简单智能合约开始。

【IPFS相关】构建可加载图片的分布式应用程序


既然我们已经需要将可靠性代码转换为Javascript,我们将使用名为solc的npm模块。

 

【IPFS相关】构建可加载图片的分布式应用程序

在solc定义的模块的帮助下,将可靠性代码转换为Javascript对象,并将其导入我们的文件中。然后使用web3它与智能合约进行交互。

const code =fs.readFileSync('./contracts/StoreHash.sol').toString();
const solc = require('solc');
const compiledCode = solc.compile(code);
const abi =JSON.parse(compiledCode.contracts[':SaveAddress'].interface);
const SavingContract = new web3.eth.Contract(abi, '0xb1caf625d9d29421dfd8dae4a7a9083b4175f80a');
// where 0xb1caf625d9d29421dfd8dae4a7a9083b4175f80a is the ethereum address

 

现在,我们有我们的智能合同规定,让我们继续前进,上传file.Going通过定义images.js 在这里 ,我主要做的是:

1.从移动应用程序获取我们的文件

exports.uploadFile = async (req, res, next) => {
    if (!req.file) {
        return res.status(422).json({
            error: 'File needs to be provided.',
        });
    }

    const mime = req.file.mimetype;
    if (mime.split('/')[0] !== 'image') {
        fs.unlink(req.file.path);

        return res.status(422).json({
            error: 'File needs to be an image.',
        });
    }

    const fileSize = req.file.size;
    if (fileSize > MAX_SIZE) {
        fs.unlink(req.file.path);

        return res.status(422).json({
            error: `Image needs to be smaller than ${MAX_SIZE} bytes.`,
        });
    }

    const data = fs.readFileSync(req.file.path);
    return ipfs.add(data)
        .then((file) => {
            if (file) {
                req.data = file;
                next();
            } else {
                res.status(400).send('Error processing file');
            }
        })
        .catch((err) => {
            res.status(500).send(err.message);
        });
};

2.将其上传到IPFS

3.将哈希值保存在以太坊区块链上

exports.postData = async (req, res, next) => {
    try {
        const { hash } = req.data[0];
        const accounts = await web3.eth.getAccounts();

        const resp = await SavingContract.methods.saveHash(hash)
            .send({
                from: accounts[0],
            });
        const data = Object.assign({ ipfsHash: hash }, resp);
        req.data = data;
        next();
    } catch (err) {
        res.status(500).send(err.message);
    }
};

 

4.在我们的mongo数据库中保存区块链哈希和IPFS哈希

exports.create = async (req, res) => {
    try {
        const data = {
            label: req.body.label,
            ipfsHash: req.data.ipfsHash,
            ipfsAddress: `https://gateway.ipfs.io/ipfs/${req.data.ipfsHash}`,
            transactionHash: req.data.ipfsHash,
            blockHash: req.data.blockHash,
        };
        const resp = await Image.create(data);
        res.send(resp);
    } catch (err) {
        res.status(500).send(err.message);
    }
};

 

完整的后端源代码可以在这里找到https://github.com/linux08/Dapp/tree/master/backend

让我们移动到移动应用程序,我们使用创建一个新的应用程序

react-native init dapp

这将为您创建一个新的react-native应用程序。从这里https://github.com/linux08/Dapp/blob/master/frontend/dapp/App.js我们可以看到我们正在启动API调用我们的API服务器已启动以获取上传的所有图像

componentDidMount() {
    const config = {
      method: 'GET',
      headers: {
        Accept: 'application/json'
      },
    };
    fetch('http://10.0.2.2:5000/images', config)
      .then((resp) => resp.json())
      .then((res) => {
        this.setState({
          images: res,
          fetchLoading: false
        })
      })
      .catch((err) => {
        console.log('err', err.message)
        this.setState({
          fetchLoading: false,
          error: err.message
        });
      })
  }

 

如果没有可用的图像,我们可以上传新的图像。我们将使用

 

【IPFS相关】构建可加载图片的分布式应用程序

在我们的本机应用程序中上传图像。我们声明了两个函数:

1.从我们的手机阅读图像

selectImage = async () => {

    ImagePicker.showImagePicker(options, async (response) => {

      if (response.didCancel) {
        this.setState({ error: 'Image upload failed', loading: null });
      } else if (response.error) {
        this.setState({ error: 'Image upload failed', loading: null });
      } else if (response.customButton) {
        this.setState({ error: 'Image upload failed', loading: null });
      } else {
        const source = { uri: response.uri };
        this.setState({
          uploadStatus: true,
          avatarSource: source,
          uri: response.uri,
          type: response.type,
          name: response.fileName,
          originalName: response.fileName
        });


        global.data = new FormData();

        data.append('file', {
          uri: response.uri,
          type: response.type,
          name: response.fileName,
          originalname: response.fileName,
        });


        const config = {
          method: 'POST',
          headers: {
            Accept: 'application/json',
            'Content-Type': 'multipart/form-data',
          },
          body: data,
        };
      }
    })
  }

2.将图像上传到本地服务器

 upload = async () => {
    this.setState({
      loading: true
    });
    if (!this.state.uploadStatus) {
      this.setState({ loading: null })
      return alert('Image yet to be uploaded')
    }
    if (this.state.label === '') {
      this.setState({ loading: null })
      return alert('Enter image label')
    }
    else {
      data.append('label', this.state.label);
      const config = {
        method: 'POST',
        headers: {
          Accept: 'application/json',
          'Content-Type': 'multipart/form-data',
        },
        body: data,
      };

      fetch('http://10.0.2.2:5000/upload', config)
        .then((resp) => resp.json())
        .then((res) => {
          this.setState((prevState) => ({
            label: res.label,
            hash: res.ipfsHash,
            address: res.ipfsAddress,
            transactionHash: res.transactionHash,
            blockHash: res.blockHash,
            loading: false,
            images: prevState.images.concat(res),
          }))
        })
        .catch((err) => {
          this.setState({
            loading: false,
            error: err.message
          });
        })
    }

【IPFS相关】由IPFS原力区译制整理,收集外网中各领域人士在使用或开发IPFS及其相关应用时所分享的文章内容。

 

IPFS原力区官网:http://ipfsforce.com

IPFSER社区: http://ipfser.org

微博:http://weibo.com/ipfsforce

【IPFS相关】构建可加载图片的分布式应用程序

原创文章,作者:IPFSforce,如若转载,请注明出处:http://ipfser.org/2018/12/04/build-a-decentralized-react-native-application/

发表评论

登录后才能评论

联系我们

在线咨询:点击这里给我发消息

邮件:[email protected]

工作时间:周一至周五,9:30-18:30,节假日休息

QR code