1. 程式人生 > >如何在以太坊上存一張圖片

如何在以太坊上存一張圖片

學習以太坊有一段時間了,今天突然在想能不能在鏈上存一張圖片?真正檔案上鍊肯定不能直接存,這裡主要還是為了學習智慧合約的操作。

首先看看官方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)


然後選擇一張要存的圖片


隨便選了張圖片,這張圖片的大小是46KB

要注意的是如果我們要把這樣一個檔案存在鏈上,呼叫一次合約存下整個圖片是不行的,因為每一個塊有gas限制,也就是gaslimit,當前的gaslimit可以通過ethstats檢視,寫這篇文章的時候gaslimit大約是8000000。

我把這張圖片轉化成base64字串,然後分割成每個5KB的字串片段,逐個呼叫合約儲存


nodejs呼叫合約

可以使用infura傳送交易,使用sendSignedTransaction簽名傳送


交易引數可以使用encodeFunctionCall序列化成交易data,私鑰簽名之後直接傳送,不懂的可以參考web3js官方api裡的例項,因為我已經發送完了交易,這裡就不在重新演示。

傳送完成後可以在區塊鏈瀏覽器檢視


可以看到,儲存5KB的字串要花費大約0.0036的eth,費用不小,不過這是在測試網路所以隨便弄沒關係

最終我們就把這張圖片以base64的方式存在了鏈上,很顯然,想要獲得這張圖片只需要call合約的getpic就可以了,不過call得到的也是base64片段,需要再拼在一起去得到完整的圖片。

我們可以寫一個靜態html用js得到這張圖片(使用infura)


這裡為了保證傳過來的片段是順序的,使用遞迴

最後效果


成功的存了一張圖片在鏈上,如果你有興趣的話還可以存別的檔案,不過要注意gas消耗。