DEVELOPER DOCS
Uploader

Uploader

The Uploader component (opens in a new tab) is used to upload either single files or groups of files using a single wallet interaction. Uploads are signed and paid for using the user's wallet.

Uploading

The component uses lazy funding, only funding when the currently funded balance is not sufficient to cover the cost of this upload. Once uploaded, file URLs are stored in the fileUrls state variable.

When uploading a single file, the URL generated is in the form https://gateway.irys.xyz/[transaction-id]. When uploading multiple files, they are grouped together and uploaded as a group along with a manifest. The URL generated is in the form https://gateway.irys.xyz/[manifest-id]/[file-name].

Image & receipt preview

Once uploaded, the UI updates to include buttons that can be clicked to view the upload and the upload receipt. When previewing uploads, all image types are supported. If your application is working with files other than images, you can remove the upload preview or modify the code to include support for previewing your file type.

If you don't choose to show the receipt, you can retrieve it later using the upload transaction id and the function irys.utils.getReceipt().

Customizing the UI

In default mode, the Uploader component shows both the image preview and receipt preview buttons. They can be hidden by passing config parameters to the component.

DescriptionCode
Default Behavior<Uploder />
Hide the image preview<Uploder showImageView={ false } />
Hide the receipt preview<Uploder showReceiptView={ false } />

If either parameter is left blank, it defaults to true.

Code

The component is designed to be used as-is. Users making significant changes to the UI will need to understand the following.

Gateway

To download data uploded to Arweave, use a gateway. The Uploader component is currently configured to use the Arweave gateway, to change this modify this variable.

const GATEWAY_BASE = "https://gateway.irys.xyz/";

FileWrapper

The Uploader component wraps the base File (opens in a new tab) object with a FileWrapper instance used to track the file's progress as it gets uploaded.

components/Uploader.tsx
interface FileWrapper {
	file: File;
	isUploaded: boolean;
	id: string;
	previewUrl: string;
	loadingReceipt: boolean;
}

Single file uploads

File uploads happen in the function handleUpload().

For single file uploads, first a Content-Type tag is created to assist the browser in rendering the file, then the file is upload and the FileWrapper object is updated.

components/Uploader.tsx
// This occurs when exactly one file is selected
try {
	for (const file of files) {
		const tags: Tag[] = [{ name: "Content-Type", value: file.file.type }];
		const uploadedTx = await fundAndUpload(file.file, tags);
		file.id = uploadedTx;
		file.isUploaded = true;
		file.previewUrl = GATEWAY_BASE + uploadedTx;
	}
} catch (e) {
	console.log("Error on upload: ", e);
}

Multiple file uploads

When uploading multiple files at once, they are grouped together as a nested bundle and uploaded with a manifest.

components/Uploader.tsx
try {
	// Remove the File objects from the FileWrapper objects
	const filesToUpload: File[] = files.map((file) => file.file);
	console.log("Multi-file upload");
	const manifestId = await fundAndUpload(filesToUpload);
 
	// Now that the upload is done, update the FileWrapper objects with the preview URL
	const updatedFiles = files.map((file) => ({
		...file,
		isUploaded: true,
		previewUrl: GATEWAY_BASE + manifestId + "/" + file.file.name,
	}));
	setFiles(updatedFiles);
} catch (e) {
	console.log("Error on upload: ", e);
}

Showing receipts

When showing a receipt, it is first retrieved using irys.utils.getReceipt() and then set to the receipt state variable.

The receipt is formatted in the class ReceiptJSONView, which can be modified if you desire custom formatting.

components/Uploader.tsx
const showReceipt = async (id: string) => {
	setReceiptQueryProcessing(true);
	try {
		const irys = await getIrys();
		const receipt = await irys.utils.getReceipt(id);
		console.log(receipt);
		setReceipt(receipt);
		setPreviewURL(""); // Only show one or the other
	} catch (e) {
		console.log("Error fetching receipt: " + e);
	}
	setReceiptQueryProcessing(false);
};