Saving uploaded file to Pinata IPFS in NodeJS

1.4k views Asked by At

I've been trying to save uploaded image files to IPFS in NodeJs , while it seems Pinata saves them, the files are pretty much gibberish (after downloading the images are broken).

My code :

// Nodejs route.
exports.postImage = async (req, res, next) => {
    // Using multer to get the file.
    fileUploadMiddleware(req, res, async (err) => {
        // getting bunch of data from query string.
        let meta = {
            origin,
            originid,
            context,
            ownerid,
            format
        } = req.query;

        if(!meta.format || !req.files) {
            return next(new ErrorResponse("File format not specified", 404));
        }

        if(!meta.originid) {
            meta.originid = uuidv4();
        }        
        
        // NOTE: is this the right way to get the data of the file ?
        const buffer = req.files[0].buffer;
        
 const filename = `${metadata.origin}_${metadata.originid}.${ metadata.format }`;

    let stream;
    try {
        stream = Readable.from(buffer);
        // HACK to make PINATA WORK.
        stream.path = filename;
    }
    catch(e) {
        logger.logError(e);
        return false;
    }

    const options = {
        pinataMetadata: {
            name: filename,
            keyvalues: {
                context: metadata.context,
                ownerid: metadata.ownerid
            }
        },
        pinataOptions: {
            cidVersion: 0
        }
    };

    try {
        var result = await pinata.pinFileToIPFS(stream, options);
        console.log("SUCCESS ", result);

        return result;
    }
    catch(e) {
        logger.logError(e);
        return null;
    }

        res.status(200).json({
            success: true,
            data: 'You got access'
        })
    });
}

So basically creating the stream based on the uploaded file buffer and sending it away to Pinata. Where do I go wrong?

1

There are 1 answers

0
Yilmaz On
const buffer = req.files[0].buffer;

If you used MemoryStorage. buffer property would be available. It is not available for diskStorage because it will save the file locally.:

const storage = multer.memoryStorage()
const upload = multer({ storage: storage })

Also I think it not req.files[0]

const buffer = req.file.buffer;

after I get the buffer, I convert it to FormData using form-data npm package:

   import FormData from "form-data";

   const formData = new FormData();
      formData.append("file", buffer, {
         contentType,
        filename: fileName + "-" + uuidv4(),
      });

then you send a post request to pinata

  const url = `https://api.pinata.cloud/pinning/pinFileToIPFS`;
  const fileRes = await axios.post(url, formData, {
    maxBodyLength: Infinity,
    headers: {
      // formData.getBoundary() is specific to npm package. native javascript FormData does not have this method
      "Content-Type": `multipart/form-data: boundary=${formData.getBoundary()}`,
      pinata_api_key: pinataApiKey,
      pinata_secret_api_key: pinataSecretApiKey,
    },
  });