Javascript – Unable to Upload Images to IPFS Using ipfs-http-client

ipfsjavascriptreact

I am having an issue with uploading images to IPFS after having switched to ipfs-http-client from ipfs-api. This is what my page code is like at the moment:

import ipfs from "../utils/ipfs";

export default function NewReview() {

    const [ipfsHash, setIpfsHash] = useState("");
    const [buffer, setBuffer] = useState(null);
    const [isFile, setFile] = useState(null);

    function getHash() {
        ipfs.files.add(Buffer.from(buffer), (error, result) => {
            if (error) {
                console.error(error)
                return
            }
            setIpfsHash(result[0].hash);
    });
    }

    useEffect(() => {
        if (buffer) {
            getHash()
        }
    });

    const captureFile = (event) => {
        if (event.target.files[0]) {
            event.preventDefault();
            setFile(URL.createObjectURL(event.target.files[0]));
        
            const reader = new FileReader();
            reader.readAsArrayBuffer(event.target.files[0])
            reader.addEventListener("load", () => {
                    setBuffer(reader.result)
            })
        }
    }

// skipping a bit to where the image is uploaded

<div>
    <img src={isFile} alt="" style={{ maxWidth: '400px' }} />
    <input type="file" onChange={captureFile} />
</div>

// I don't think the rest is relevant

The images are meant to be saved to the blockchain via a smart contract function and should be displayed on another page like this:

// other code
<li className="list-group-item">
    <img src={ `https://ipfs.io/ipfs/${review.ipfsHash}` } alt="" />
</li>

This is what ipfs.js looks like:

const { create } = require('ipfs-http-client');
const ipfs = create({host: 'ipfs.infura.io', port: 5001, protocol: 'https'});

export default ipfs;

When I was using ipfs-api the above code used to work. However with ipfs-http-client I can't used ipfs.files.add as I get a TypeError: default.files.add is not a function error.

I have tried replacing ipfs.files.add with just ipfs.add but that doesn't work, even if I put the buffer in a JavaScript object as the documentation for ipfs.add suggests I do. I don't even seem to get any error messages when I look at the console, it just doesn't seem to work and the ipfsHash is just an empty string (like the original state).

I'd really appreciate your thoughts and suggestions! Without even getting any errors in the console I'm not sure what the error is and how I can get ipfs-http-client to save an image file to IPFS like my code used to to successfully.

Best Answer

I found a solution to my problem!

With ipfs-http-client, you need to use ipfs.add as part of an async/await function in order for ipfs.add to actually execute, it seems. Without it being in an async/await function, it didn't do anything at all when getHash() ran.

This is how I changed getHash():

async function getHash() {
    
    try {
        const uploadResult = await ipfs.add(Buffer.from(buffer))
        setIpfsHash(uploadResult.path)
    } catch(e) {
        console.log(e)
        toast.error(e.message)
        return
    }
}
Related Topic