Pinning Files
With Pinata, there are a few ways you can pin files to IPFS!
API & SDKs
If you’re a developer that needs to build decentralized applications, then you will likely want to use the SDK or the Pinata API. These make it simple to integrate IPFS uploads into your App!
Using the SDK
The Pinata SDK is able to handle mutliple kinds of uploads, whether its file objects, base64 strings, or even content from remote URLs.
import { PinataSDK } from "pinata-web3";
const pinata = new PinataSDK({
pinataJwt: process.env.PINATA_JWT!,
pinataGateway: "example-gateway.mypinata.cloud",
});
const file = new File(["hello"], "Testing.txt", { type: "text/plain" });
const upload = await pinata.upload.file(file);
The SDK is also equipped to handle an array of file objects.
import { PinataSDK } from "pinata-web3";
const pinata = new PinataSDK({
pinataJwt: process.env.PINATA_JWT!,
pinataGateway: "example-gateway.mypinata.cloud",
});
const file1 = new File(["hello world!"], "hello.txt", { type: "text/plain" })
const file2 = new File(["hello world again!"], "hello2.txt", { type: "text/plain" })
const upload = await pinata.upload.fileArray([file1, file2])
Using the API
The API is a bit more flexible, as it can be used in multiple languages or environments, and is sometimes preferred for client side uploads. With that, we should express warning in that client side applications will expose API keys.
Using your API Keys in a client side application will expose them! Consider using a signed JWT approach.
The API accepts File
objects (and blobs in the right environment) through a multipart form data request, where the object has a key of file
. Additionally you can add pinataMetadata and pinataOptions to the request. Here is an example of how you could upload with the API:
const JWT = "YOUR_PINATA_JWT";
async function pinFileToIPFS() {
try {
const formData = new FormData();
const file = new File(["hello"], "Testing.txt", { type: "text/plain" });
formData.append("file", file);
const pinataMetadata = JSON.stringify({
name: "File name",
});
formData.append("pinataMetadata", pinataMetadata);
const pinataOptions = JSON.stringify({
cidVersion: 1,
});
formData.append("pinataOptions", pinataOptions);
const request = await fetch("https://api.pinata.cloud/pinning/pinFileToIPFS", {
method: "POST",
headers: {
Authorization: `Bearer ${JWT}`
},
body: formData,
});
const response = await request.json();
console.log(response);
} catch (error) {
console.log(error);
}
}
Common File Recipes
Below are some common recipes for uploading a file.
Blob
Usually you can pass a Blob directly into the request but to help guarantee success we recommend passing it into a File
object.
import { PinataSDK } from "pinata-web3";
const pinata = new PinataSDK({
pinataJwt: process.env.PINATA_JWT!,
pinataGateway: "example-gateway.mypinata.cloud",
});
const text = "Hello World!";
const blob = new Blob([text], { type: "text/plain" });
const file = new File(["hello world!"], "hello.txt", { type: "text/plain" })
const upload = await pinata.upload.file(file)
JSON
Pinata makes it easy to upload JSON objects using the json method.
import { PinataSDK } from "pinata-web3";
const pinata = new PinataSDK({
pinataJwt: process.env.PINATA_JWT!,
pinataGateway: "example-gateway.mypinata.cloud",
});
const upload = await pinata.upload.json({
name: "Pinnie NFT",
description: "A Pinnie NFT from Pinata",
image: "ipfs://bafkreih5aznjvttude6c3wbvqeebb6rlx5wkbzyppv7garjiubll2ceym4"
})
Local Files
If you need to upload files from a local file source you can use fs
to feed a file into a blob
, then turn that blob
into a File
.
const { PinataSDK } = require("pinata-web3")
const fs = require("fs")
const { Blob } = require("buffer")
const pinata = new PinataSDK({
pinataJwt: process.env.PINATA_JWT!,
pinataGateway: "example-gateway.mypinata.cloud"
})
const blob = new Blob([fs.readFileSync("./hello-world.txt")]);
const file = new File([blob], "hello-world.txt", { type: "text/plain"})
const upload = await pinata.upload.file(file);
URL
To upload a file from an external URL you can stream the contents into an arrayBuffer
, which then gets passed into a new Blob
that can then be uploaded to Pinata. This has been abstracted in the SDK using the url method.
import { PinataSDK } from "pinata-web3";
const pinata = new PinataSDK({
pinataJwt: process.env.PINATA_JWT!,
pinataGateway: "example-gateway.mypinata.cloud",
});
const upload = await pinata.upload.url("https://i.imgur.com/u4mGk5b.gif")
base64
To upload a file in base64 simply turn the contents into a buffer
that is passed into a Blob
. Alternatively you can use the SDK for this as well using the base64 method.
import { PinataSDK } from "pinata-web3";
const pinata = new PinataSDK({
pinataJwt: process.env.PINATA_JWT!,
pinataGateway: "example-gateway.mypinata.cloud",
});
const upload = await pinata.upload.base64("SGVsbG8gV29ybGQh")
Folders
The SDK can accept an array of files using the fileArray method. Folders can also be uploaded via the API by creating an array of files and mapping over them to add them to the form data. This is different then having a single file
entry and having multiple files for that one entry, which does not work.
We also have other tools like the Pinata CLI or Next.js Starter which can be used to upload using API Keys!
Web App
If you’re non-technical, you can use Pinata App to upload files, perfect if you just want to get started with NFTs and IPFS! It’s as simple as clicking the “Upload” button in the top right corner of the files page. Select your file, give it a name, then upload. Once it’s complete you’ll see it listed in the files page.
Start uploading by signing up for a free account!
Pin by CID
Another way you can upload content to Pinata is by transferring content that is already on IPFS. This could be CIDs that are on your own local IPFS node or another IPFS pinning service! You can do this with the “Pin by CID” button in the web app, like so:
Or you can pin by CID with the SDK using the cid method.
import { PinataSDK } from "pinata-web3";
const pinata = new PinataSDK({
pinataJwt: process.env.PINATA_JWT!,
pinataGateway: "example-gateway.mypinata.cloud",
});
const pin = await pinata.upload.cid("QmVLwvmGehsrNEvhcCnnsw5RQNseohgEkFNN1848zNzdng")
This will result in a request_id
and Pinata will start looking for the file. Progress can be checked by using the pinJobs method.
import { PinataSDK } from "pinata-web3";
const pinata = new PinataSDK({
pinataJwt: process.env.PINATA_JWT!,
pinataGateway: "example-gateway.mypinata.cloud",
});
const jobs = await pinata.pinJobs().status("prechecking")
All possible filters are included in the API reference below, but these are the possible “status” filters:
Filter by the status of the job in the pinning queue (see potential statuses below)
prechecking
Pinata is running preliminary validations on your pin request.searching
Pinata is actively searching for your content on the IPFS network. This may take some time if your content is isolated.retrieving
Pinata has located your content and is now in the process of retrieving it.expired
Pinata wasn’t able to find your content after a day of searching the IPFS network. Please make sure your content is hosted on the IPFS network before trying to pin again.over_free_limit
Pinning this object would put you over the free tier limit. Please add a credit card to continue pinning content.over_max_size
This object is too large of an item to pin. If you’re seeing this, please contact us for a more custom solution.invalid_object
The object you’re attempting to pin isn’t readable by IPFS nodes. Please contact us if you receive this, as we’d like to better understand what you’re attempting to pin.bad_host_node
You provided a host node that was either invalid or unreachable. Please make sure all provided host nodes are online and reachable.
Predetermining the CID
If you find yourself in a position where you want to pre-determine the CID before uploading you can use the multiformats
library. The key is making sure you use raw
codec and use blobs just like the Pinata API accepts to get the same results.
import { CID } from 'multiformats/cid'
import * as raw from 'multiformats/codecs/raw'
import { sha256 } from 'multiformats/hashes/sha2'
const JWT = "YOUR_PINATA_JWT"
async function main(){
try {
const text = "Hello World!";
const blob = new Blob([text], { type: "text/plain" });
const unit8array = new Uint8Array(await blob.arrayBuffer());
const bytes = raw.encode(unit8array)
const hash = await sha256.digest(bytes)
const cid = CID.create(1, raw.code, hash)
console.log(cid.toString())
} catch(error) {
console.log(error)
}
}
async function pinFileToIPFS() {
try {
const text = "Hello World!";
const blob = new Blob([text], { type: "text/plain" });
const data = new FormData();
data.append("file", blob);
const options = JSON.stringify({
cidVersion: 1
})
data.append("pinataOptions", options)
const res = await fetch("https://api.pinata.cloud/pinning/pinFileToIPFS", {
method: "POST",
headers: {
Authorization: `Bearer ${JWT}`,
},
body: data
});
const resData = await res.json();
console.log(resData.IpfsHash);
} catch (error) {
console.log(error);
}
};
main()
pinFileToIPFS()