Error Uploading File to IPFS. I am using the pinFileToIPFS gateway

161 views Asked by At

I am trying to upload an image to IPFS, which was selected by user in the front-end. I am storing the image in state hook and passing it on to the Form-data.

Following the pinata documentation I have also added the name of the file and pinata options in the form-data.

I am using axios to perform a get request to the Pinata server. The "handleFileUpload" function is used to deal with uploading the files to Pinata.

But I am getting a Bad-Request error (detailed error below) when I make the post request to the server.

Below I am providing my full code, this code is from one of my react components named create. My Full Code is provided below:

import { useState } from 'react';
import { Row, Form, Button } from 'react-bootstrap';
import { create as ipfsHttpClient } from 'ipfs-http-client';
import axios from 'axios';
import FormData from 'form-data';

const Create = ({ marketplace, nft }) => {
  const [image, setImage] = useState();
  const [price, setPrice] = useState(null);
  const [name, setName] = useState('');
  const [description, setDescription] = useState('');
  let ImgHash;
  const JWT = 'JWT_here'

  const handleFileUpload = async(e) => 
  {
    e.preventDefault();
    if(image)
    {
      const formData = new FormData();
      formData.append("file", image[0]);

      const pinataMetadata = JSON.stringify({
        name: name,
      });
      formData.append('pinataMetadata', pinataMetadata);

      const pinataOptions = JSON.stringify({
         cidVersion: 0,
      })
      formData.append('pinataOptions', pinataOptions);

      try
      {
        const res = await axios.post("https://api.pinata.cloud/pinning/pinFileToIPFS", formData, 
        {
          maxBodyLength: "Infinity",
          headers: {
            'Content-Type': `multipart/form-data; boundary=${formData._boundary}`,
            Authorization: JWT,
            path: 'somename'
          }
        });
        console.log(res.data);
        ImgHash = `ipfs://${res.data.IpfsHash}`;
      } 
      catch (error) 
      {
        console.error('Error uploading file:', error);
      }
    }
  }

  return (
    <div className="container-fluid mt-5">
      <div className="row">
        <main role="main" className="col-lg-12 mx-auto" style={{ maxWidth: '1000px' }}>
          <div className="content mx-auto">
            <Row className="g-4">
              <Form.Control
                type="file"
                required
                name="file"
                onChange={(e) => setImage(e.target.files[0])}
              />
              <Form.Control onChange={(e) => setName(e.target.value)} size="lg" required type="text" placeholder="Name" />
              <Form.Control onChange={(e) => setDescription(e.target.value)} size="lg" required as="textarea" placeholder="Description" />
              <Form.Control onChange={(e) => setPrice(e.target.value)} size="lg" required type="number" placeholder="Price in ETH" />
              <div className="d-grid px-0">
                <Button onClick={handleFileUpload} variant="primary" size="lg">
                  Create & List NFT!
                </Button>
              </div>
            </Row>
          </div>
        </main>
      </div>
    </div>
  );
}

export default Create

I tried going through the documentation to figure out the error, but could not figure out the exact cause.

Below are the Error Message I received when trying to make a post request:

AxiosError {message: 'Request failed with status code 400', name: 'AxiosError', code: 'ERR_BAD_REQUEST', config: {…}, request: XMLHttpRequest, …} code : "ERR_BAD_REQUEST" config : {transitional: {…}, adapter: Array(2), transformRequest: Array(1), transformResponse: Array(1), timeout: 0, …} message : "Request failed with status code 400" name : "AxiosError" request : XMLHttpRequest {onreadystatechange: null, readyState: 4, timeout: 0, withCredentials: false, upload: XMLHttpRequestUpload, …} response : {data: {…}, status: 400, statusText: '', headers: AxiosHeaders, config: {…}, …} stack : "AxiosError: Request failed with status code 400\n at settle (http://localhost:5173/node_modules/.vite/deps/axios.js?v=8be9dcc7:3371:12)\n at XMLHttpRequest.onloadend (http://localhost:5173/node_modules/.vite/deps/axios.js?v=8be9dcc7:3611:7)" [[Prototype]] : Error

2

There are 2 answers

1
Yilmaz On

400 status code indicates either endpoint is wrong or you are sending invalid or missing parameters in the request. But your endpoint url is correct, so probably you are setting wrong parameters. From docs

This endpoint will accept a single file or a single directory. The request must include a read stream for the payload in order for the API to accept it.

Example from docs

const axios = require('axios')
const FormData = require('form-data')
const fs = require('fs')
const JWT = 'Bearer PASTE_YOUR_PINATA_JWT'

const pinFileToIPFS = async () => {
    const formData = new FormData();
    const src = "path/to/file.png";
    
    const file = fs.createReadStream(src)
    formData.append('file', file)
    
    const pinataMetadata = JSON.stringify({
      name: 'File name',
    });
    formData.append('pinataMetadata', pinataMetadata);

    try{
      const res = await axios.post("https://api.pinata.cloud/pinning/pinFileToIPFS", formData, {
        maxBodyLength: "Infinity",
        headers: {
          'Content-Type': `multipart/form-data; boundary=${formData._boundary}`,
          Authorization: JWT
        }
      });
      console.log(res.data);
    } catch (error) {
      console.log(error);
    }
}
0
Steve Simkins On

It also might be how you're doing the authorization as I dont see the Bearer before the jwt. Another option could be checking out npx create-pinata-app as its a full blown next js starter template with uploads and rendering with the gateway! more info here