是否可以将图像存储在以太坊区块链上?

Is it possible to store images on the Ethereum blockchain?

我正在加紧学习 Solidity,并且有一些想法。目前我很好奇 files/images 是否可以放在区块链上。我在想一种替代方法是一些混合方法,其中一些东西在区块链上,一些东西在更传统的文件存储中,并使用地址引用来获取它。我预见的一个问题是文件上传的汽油价格。

在链上存储图像是一个重要的NO!

在数据库中存储图像也不是一个好的做法,我假设您只是指像 S3 / firebase 这样的文件存储解决方案。将图像存储在中央服务器上是可以的,但这取决于您想要实现的目标,您可以研究 IPFS 和 Swarm 等去中心化存储解决方案。

从技术上讲,是的,您可以存储非常小的图像。但你不应该。

首选备选方案

将图像存储在分布式文件存储(例如,Swarm 或 IPFS)中,并在链上存储图像的哈希值,如果证明图像未被篡改真的很重要的话。如果这不重要,那么也许不要把任何东西放在链上。

有什么技术限制?

主要是区块的气体限制。目前,以太坊主网有 8Mgas 区块限制。每个新的 32bytes 存储使用 20k gas。所以你不能存储总和超过 12.8kb 的数据,因为它不适合块。

为什么我不应该将它用于小文件?

区块链不是为这种用途而设计的(这就是为什么存在其他项目,如 Swarm 和 IPFS)。它会膨胀并减慢一切,与其他文件存储系统相比没有任何好处。以此类推,您通常也不会将文件存储在 SQL 数据库中。

Is it possible to store images on the Ethereum blockchain?

绝对有可能!

你应该这样做吗?几乎可以肯定不是!

One issue I foresee is gas price of file uploads.

  • 数据存储成本为每千字节数据 640k gas。
  • 当前 gas 价格约为 15 Gwei(或 0.000000015 ETH)。
  • 按照今天的价格,1 ETH 大约是 200 美元。

每千字节的价格不到 2 美元。

我不会告诉你这对你的应用程序来说是否太贵了,但你也应该考虑到 Gas 和 Ether 的价格随时间变化很大,你应该预料到这个数字会出现变化的时期显着 更高。

我完全同意@Peter Hall 的观点,将图像存储在以太坊上成本太高。


那么,你可以做什么来代替这个?

  • 您可以将图像存储在 IPFS 上。 IPFS 给你一个固定长度的散列。现在,您可以将此哈希存储在以太坊上,而且成本低于其他方式。

以太坊太重也太贵了,无法存储像图像这样的大块, 视频等。因此,需要一些外部存储来存储更大的 对象。这就是星际文件系统 (IPFS) 的用武之地 图片。以太坊 Dapp 可以保存少量数据,而对于 保存更多或更大的内容,例如图像、文字、PDF 文件等, 我们使用 IPFS。

IPFS 是一种开源协议和网络,旨在创建一种存储和共享数据的点对点方法。它类似于 Bit Torrent。

如果您想将 PDF、Word 或图像文件上传到 IPFS.

1- 您将 PDF、Word 或图像文件放在工作目录中。

2-您通知 IPFS 添加此文件,这会生成文件的哈希值。注意 IPFS 哈希总是以“Qm....”开头

3- 您的文件在 IPFS 网络上可用。

现在您上传了文件并想与 Bob 共享该文件。您将文件的哈希发送给 Bob,Bob 使用该哈希并为该文件调用 IPFS。该文件现在已在 Bob 端下载。这里的问题是任何可以访问哈希的人也可以访问该文件。

通过非对称加密在 IPFS 上共享数据

假设你上传了一个文件到 IPFS 并且你只想与 Bob 分享它。

  • Bob 将向您发送一个 public 密钥。你将使用 Bob 的 public 密钥加密文件,然后将其上传到 IPFS 网络。

  • 您将文件的哈希值发送给 Bob。 Bob 使用此哈希并获取文件。

  • Bob 使用用于加密文件的 public 密钥的私钥解密文件。

在非对称密码学中,public 密钥由私钥生成,如果您使用 public 密钥锁定某物,唯一能解锁该物的密钥是给定的私钥public 密钥生成自。

注意:我试图存储 100kb 图像的 +10,000 长 base64 字符串,但它不接受。但是当我尝试 1kb 图像时,它起作用了。

是的。这是执行此操作的可靠代码:-

// SPDX-License-Identifier: GPL-3.0
pragma solidity >=0.7.0 <0.9.0;
contract ImgStorage {
    uint i=0;
    mapping(uint => string[]) public base64_images;
    function push(string memory  base64_img) public {
        base64_images[i].push(base64_img);
        i++;        
    }
    function returnImage(uint n) public view returns(string[] memory){
        return base64_images[n];
    }
}

工作代码图像:

您可以在线将图像转换为base64,反之亦然。 这是将图像转换为 base64 字符串的 NodeJS 代码:

const imageToBase64 = require('image-to-base64');
const fs=require('fs')
imageToBase64("img/1kb.png") 
    .then(data => {fs.writeFile('1kb_png.md',data, (err)=>{console.log(err)})})
    .catch(err =>console.log(err))