Инновации зовут
Используя удивительный новый чат GPT от открытого ИИ, голову, полную идей и знаний, чтобы связать все это воедино, я смог подготовить это руководство в рекордно короткие сроки.
Если вы еще не проверили это, поиграйте здесь.
Создайте React-приложение
В этом руководстве предполагается, что у вас настроен узел, если нет, вы можете установить его здесь.
Создайте новый каталог для нашего внешнего приложения на рабочем столе, откройте новое окно терминала и перейдите в этот каталог.
Оказавшись в этом новом каталоге, введите в терминал следующее, чтобы создать новое реагирующее приложение:
npx create-react-app FileCompressor
После установки ваша новая структура каталогов будет построена.
Добавить форму загрузки внешнего интерфейса
Перейдите к src/app.js и перейдите к функции App, чтобы поместить внутрь эту логику:
import React from "react"; function App(props) { const handleChange = e => { const fileReader = new FileReader(); fileReader.readAsText(e.target.files[0], "UTF-8"); fileReader.onload = e => { if(e.target !== null) { console.log("e.target.result", e.target.result); } }; }; return ( <> <h1>Upload file</h1> <input type="file" onChange={handleChange} /> </> ); } export default App;
Это создаст новую функцию с именем handleChange, которая вызывается каждый раз, когда файл загружается во внешний интерфейс.
Base64
Наши файлы в настоящее время не имеют формата, который может понять цепочка, затем нам нужно преобразовать их в строку base64, которую можно хранить в цепочке.
Вернитесь к вашему файлу app.js, где мы добавим логику base64 в метод handleChange:
import React from "react"; function App(props) { const handleChange = e => { const fileReader = new FileReader(); fileReader.readAsDataURL(file) fileReader.onload = () => { console.log(fileReader.result); } fileReader.onerror = (error) => { console.log(error); } }; return ( <> <h1>Upload file</h1> <input type="file" onChange={handleChange} /> </> ); } export default App;
На данный момент у нас есть форма загрузки файла, которая принимает входные данные, преобразует файл в строку base64 и выводит консоль. Как бы то ни было, это нормально, но гораздо лучше использовать сжатие, чтобы уменьшить количество байтов.
Сжатие строк LZ
Сначала установите библиотеку для сжатия lz:
npm i lzma-js
После установки измените app.js, чтобы он напоминал приведенный ниже пример, после чего на терминал будет записана сжатая строка base64:
import React from "react"; import LZMA from "lzma-js"; function App(props) { const handleChange = e => { const fileReader = new FileReader(); fileReader.readAsDataURL(file) fileReader.onload = () => { // Convert the base64 encoded string to a Uint8Array const uint8Array = Uint8Array.from(atob(fileReader.result), c => c.charCodeAt(0)); // Compress the Uint8Array using LZMA-JS LZMA.compress(uint8Array, 9, (result, error) => { if (error) { // Handle error } else { // The compressed data is a Uint8Array, so you need to convert it to a base64 encoded string const compressedBase64String = btoa(String.fromCharCode(...result)); console.log(compressedBase64String); // Outputs the compressed base64 encoded string } }); } fileReader.onerror = (error) => { console.log(error); } }; return ( <> <h1>Upload file</h1> <input type="file" onChange={handleChange} /> </> ); } export default App;
Смарт-контракт
Это простой смарт-контракт, в котором хранится массив строк bytes32, в данном случае наши строки bytes32 являются файлами.
// SPDX-License-Identifier: MIT pragma solidity ^0.8.10; contract FileStorage { mapping (address => bytes32[]) userFiles; function addFile(string calldata _file) public { userFiles[msg.sender].push(_file); } function deleteFile(uint arrayIndex) public { delete userFiles[msg.sender][arrayIndex]; } function getFiles() public view returns (bytes32[] memory) { return userFiles[msg.sender]; } }
Это минимальный уровень, поэтому для производственных случаев вам, вероятно, потребуется гораздо больше, но приведенного выше контракта будет достаточно для целей этого руководства. После развертывания вы готовы подключить свое реагирующее приложение к децентрализованной файловой базе данных.
Подключение децентрализованного приложения
Сначала возьмите abi для вашего развернутого контракта и сохраните в новом файле с именем abi.json.
[ { "inputs": [ { "internalType": "string", "name": "_file", "type": "string" } ], "name": "addFile", "outputs": [], "stateMutability": "nonpayable", "type": "function" }, { "inputs": [ { "internalType": "uint256", "name": "arrayIndex", "type": "uint256" } ], "name": "deleteFile", "outputs": [], "stateMutability": "nonpayable", "type": "function" }, { "inputs": [], "name": "getFiles", "outputs": [ { "internalType": "string[]", "name": "", "type": "string[]" } ], "stateMutability": "view", "type": "function" } ]
Если вы вернетесь к файлу app.js, последним этапом будет замена нашего консольного журнала строки файла вызовом смарт-контракта. Сначала мы вводим abi контракта, заполняем адрес контракта, подключаемся к MetaMask через интерфейс, а затем разрешаем сохранение файла пользователя после установления соединения.
import React from "react"; import LZMA from "lzma-js"; function App(props) { const abi = require('./abi.json'); const handleChange = e => { const fileReader = new FileReader(); const CONTRACT_ADDRESS = "0xof"; fileReader.readAsDataURL(file) fileReader.onload = () => { // Convert the base64 encoded string to a Uint8Array const uint8Array = Uint8Array.from(atob(fileReader.result), c => c.charCodeAt(0)); // Compress the Uint8Array using LZMA-JS LZMA.compress(uint8Array, 9, (result, error) => { if (error) { console.log(error); } else { // The compressed data is a Uint8Array, so you need to convert it to a base64 encoded string const compressedBase64String = btoa(String.fromCharCode(...result)); const { ethereum } = window; const provider = new ethers.providers.Web3Provider(ethereum); const signer = provider.getSigner() const connectedContract = new ethers.Contract(CONTRACT_ADDRESS, abi, signer); let tx = async() => await connectedContract.addFile(compressedBase64String); console.log(tx); // Outputs the result of the smart contract call } }); } fileReader.onerror = (error) => { console.log(error); } }; return ( <> <h1>Upload file</h1> <input type="file" onChange={handleChange} /> </> ); } export default App;
Это все, что вам нужно, чтобы сжать текстовый документ и сохранить его в цепочке, а не только текстовые документы, а практически любой тип файла, который может быть понят загрузчиком на основе браузера.
Чтобы вернуть ваши файлы и распаковать, вам нужно будет создать новый метод для запроса функции getFiles смарт-контрактов и прокрутить каждый из них, внутри каждой итерации вы просто вызовете метод ниже и сохраните распакованные данные любым способом, который подходит для вашего варианта использования. :
LZMA.decompress(properties, inStream, outStream, outSize);
У этого подхода так много возможностей, но, как всегда, это просто руководство, которое приведет вас к прочной основе и пониманию, но ни в коем случае не готово к производству.
Иди твори!
Новичок в трейдинге? Попробуйте криптотрейдинговых ботов или копи-трейдинг