【问题标题】:Pinata IPFS's pinFileToIPFS method not accepting a user uploaded filePinata IPFS 的 pinFileToIPFS 方法不接受用户上传的文件
【发布时间】:2022-04-23 23:04:06
【问题描述】:

我正在开发一个项目(使用 React.js Express.js 和 Node.js)将用户上传的图像转换为以太坊区块链上的 NFT,为此,我需要将图像上传到 IPFS(我是使用 Pinata),然后使用元数据中的 pinata URI 来铸造一个新的 NFT。 (如果我在这里错了,请告诉我,我还是 web3 的新手)

为了将我的图像上传到 Pinata IPFS,我将图像的 base64 字符串从客户端发送到服务器端,然后调用 pinFileToIPFS 方法。这是我的服务器端文件的代码

const axios = require('axios');
const fs = require('fs');
const FormData = require('form-data');
const router = require('express').Router();
const { Readable } = require('stream');

const pinFileToIPFS = (image) => {
    const url = `https://api.pinata.cloud/pinning/pinJSONToIPFS`;
    const buffer = Buffer.from(image);
    const stream = Readable.from(buffer);
    const filename = `an-awesome-nft_${Date.now()}.png`;
    stream.path = filename;

    const formData = new FormData();
    formData.append("file", stream);

return axios.post(url,
        formData,
        {
            headers: {
                'Content-Type': `multipart/form-data; boundary= ${formData._boundary}`,
                'pinata_api_key': "*******************",
                'pinata_secret_api_key': "**********************************",
            }
        }
    ).then(function (response) {
        console.log("Success: ", response);
    }).catch(function (error) {
        console.log("Fail! ", error.response.data);
    });
};

router.route('/').post((req, res) => {
    const image = req.body.image;
    pinFileToIPFS(image);
});

module.exports = router;

这里req.body.image 包含用户上传文件的base64 字符串。 我试图将base64字符串转换为缓冲区,然后将缓冲区转换为可读流(如官方Pianata文档中所做的那样,但对于本地文件),然后将其包装在FormData()中,但我不断收到以下信息错误。

data: {
  error: 'This API endpoint requires valid JSON, and a JSON content-type'
}

我知道问题出在我的图像/文件发送到 API 的格式上,但我不知道。我还是 web3 和区块链的新手,所以请帮忙!

【问题讨论】:

    标签: javascript node.js reactjs mern ipfs


    【解决方案1】:

    与 Pinata 交互的推荐方式是使用他们的Node.JS SDK。此 SDK 有一个pinFileToIPFS 功能,允许您以 readableStream 的形式将图像上传到其 IPFS 节点。 一个这样的示例看起来像

    const fs = require('fs');
    const readableStreamForFile = fs.createReadStream('./yourfile.png');
    const options = {
        pinataMetadata: {
            name: MyCustomName,
            keyvalues: {
                customKey: 'customValue',
                customKey2: 'customValue2'
            }
        },
        pinataOptions: {
            cidVersion: 0
        }
    };
    pinata.pinFileToIPFS(readableStreamForFile, options).then((result) => {
        //handle results here
        console.log(result);
    }).catch((err) => {
        //handle error here
        console.log(err);
    });
    

    但是,如果您不喜欢使用他们的 API 端点并只是通过 axios 发布到他们,那么有一个 seperate API endpoint/pinning/pinFileToIPFS。这种方法的例子可以在他们的API Docs找到。

    【讨论】:

      【解决方案2】:

      您可能需要考虑更改以下两行并改用https://api.pinata.cloud/pinning/pinFileToIPFS 端点:

      const buffer = Buffer.from(image); -> const buffer = Buffer.from(image, "base64");

      formData.append("file", stream); -> formData.append("file", stream, "fileNameOfChoiche.png);

      【讨论】:

        【解决方案3】:

        当您使用节点 js 将图像或文件上传到 Pinata IPFS 时。这些步骤甚至不需要 Pinata Node.js SDK。

        1- 您可以使用 React 或 Next.js 从前端上传图片。代码如下。

        const uploadAttachment = async (data, token) => {
          try {
            return await Api.post(`${ApiRoutes.upload_attachment}`, data, {
              headers: {
                Authorization: "Bearer " + token, //the token is a variable which holds the token
              },
            });
          } catch (error) {
            return {
              status: 404,
            };
          }
        };
        
        export default uploadAttachment;
        

        2- 上传图片需要安装multer。

        const multer = require("multer");
        global.uploadSingleFile = multer({ dest: "uploads/" });
        

        3- 使用您要调用的 multer 中间件和操作设置您的路线。

         .post(
            "/attachments/upload",
            uploadSingleFile.single("file"),
            actions.attachments.upload.pinFileToIPFSLocal
          );
        

        4- 最后一步,您将使用 Pinata API 和密钥访问 Pinata 端点。

        pinFileToIPFSLocal: async (req, res, next) => {
            try {
              const url = "https://api.pinata.cloud/pinning/pinFileToIPFS";
              let formData = new FormData();
              formData.append("file", JSON.stringify(req.file), req.file.originalname);
        
              axios
                .post(url, formData, {
                  maxContentLength: -1,
                  headers: {
                    "Content-Type": `multipart/form-data; boundary=${formData._boundary}`,
                    pinata_api_key: process.env.PINATA_API_KEY,
                    pinata_secret_api_key: process.env.PINATA_API_SECRET,
                    path: "somename",
                  },
                })
                .then((data) => {
                  console.log("Result...", data);
                  return utils.response.response(
                    res,
                    "Upload image to ipfs.",
                    true,
                    200,
                    data.data
                  );
                })
                .catch((err) => {
                  return utils.response.response(
                    res,
                    "Image not upload to ipfs",
                    false,
                    200,
                    err
                  );
                });
            } catch (error) {
              next(error);
            }
        

        【讨论】:

          猜你喜欢
          • 2021-04-05
          • 2022-01-01
          • 1970-01-01
          • 2022-07-01
          • 1970-01-01
          • 2022-11-10
          • 2022-11-12
          • 2021-04-02
          • 2021-12-18
          相关资源
          最近更新 更多