如何在以太坊上存一张图片

学习以太坊有一段时间了,今天突然在想能不能在链上存一张图片?真正文件上链肯定不能直接存,这里主要还是为了学习智能合约的操作。

首先看看官方api

这里是web3js的api地址

以太坊并不提供操纵文件的方法,不过我们可以把文件转化成base64字符串再存在链上。

首先写好合约

pragma solidity ^0.4.11;

contract Mrc{
    mapping (uint => string) pic;
    uint x=0;
    address owner;
    function Mrc(){
        owner = msg.sender;
    }
    function save(string s) public{
        require(msg.sender == owner);
        pic[x]=s;
        x++;
    }
    function getpic(uint i) constant public returns (string){
        require(msg.sender == owner);
        return pic[i];
    }
}

这个合约十分简单,意思是只有合约创建者可以存取内容,你可以使用remix创建合约,也可以用infura创建合约(参考我的另外一篇文章)。

remix里点击deploy部署合约(要下好metamask钱包,并且选择inject web3)


如何在以太坊上存一张图片_第1张图片

然后选择一张要存的图片

如何在以太坊上存一张图片_第2张图片

随便选了张图片,这张图片的大小是46KB

要注意的是如果我们要把这样一个文件存在链上,调用一次合约存下整个图片是不行的,因为每一个块有gas限制,也就是gaslimit,当前的gaslimit可以通过ethstats查看,写这篇文章的时候gaslimit大约是8000000。

我把这张图片转化成base64字符串,然后分割成每个5KB的字符串片段,逐个调用合约存储

如何在以太坊上存一张图片_第3张图片

nodejs调用合约

可以使用infura发送交易,使用sendSignedTransaction签名发送

如何在以太坊上存一张图片_第4张图片

交易参数可以使用encodeFunctionCall序列化成交易data,私钥签名之后直接发送,不懂的可以参考web3js官方api里的实例,因为我已经发送完了交易,这里就不在重新演示。

发送完成后可以在区块链浏览器查看

如何在以太坊上存一张图片_第5张图片

可以看到,存储5KB的字符串要花费大约0.0036的eth,费用不小,不过这是在测试网络所以随便弄没关系

最终我们就把这张图片以base64的方式存在了链上,很显然,想要获得这张图片只需要call合约的getpic就可以了,不过call得到的也是base64片段,需要再拼在一起去得到完整的图片。

我们可以写一个静态html用js得到这张图片(使用infura)

如何在以太坊上存一张图片_第6张图片

这里为了保证传过来的片段是顺序的,使用递归

最后效果

如何在以太坊上存一张图片_第7张图片

成功的存了一张图片在链上,如果你有兴趣的话还可以存别的文件,不过要注意gas消耗。

你可能感兴趣的:(区块链,区块链)