Uploading, Getting, and Downloading document using SignNow in a Node.js and React.js environment .

Abhishek Mishra
6 min readJan 24, 2024

--

SignNow Image

In this blog we will learn how to integrate SignNow in Node.js and React.js. Now without wasting any single second lets start.

To use SignNow, you need to create a SignNow account, and then you will obtain a SignNow Basic Authorization Token.

First, create a Node.js server and a React.js project. The first step is to generate an access token. Here is Official Doc and code for generate access token :

 //here is code for generate access token
getAccessToken: async (req, res) => {
try {
const url = "https://api.signnow.com/oauth2/token";
const options = {
method: "POST", //Method should be POST
headers: {
"Content-Type": "application/x-www-form-urlencoded",
Authorization: `Basic ${process.env.Signow_Authorization_Token}`, //SignNow give AUthorization
},
body: new URLSearchParams({
username: process.env.Signnow_username, //Username which is email address
password: process.env.Signnow_password, //password is signnow password
grant_type: "password",
scope: "*",
}),
};

const response = await fetch(url, options);
const data = await response.json();

if (!response.ok) {

throw new Error(`HTTP error! Status: ${response.status}`);
}
return res.status(200).json({
status: "success",
message: "Get Tenant Doc",
data, //we need this Access token on frontend side
});
} catch (error) {
console.error(error);
// Handle errors and send an appropriate response to the client
return res.status(500).json({
status: "error",
message: "Internal Server Error",
});
}
},

Now, we will learn how to upload a document to SignNow and obtain its unique identifier. To achieve this, we will send the document from the frontend to the backend for uploading ,Here is the example :

import React, { useState } from 'react';
import axios from 'axios';

const FileUploadComponent = () => {
const [selectedFile, setSelectedFile] = useState(null);

const handleFileChange = (e) => {
const file = e.target.files[0];

if (file && file.type === 'application/pdf') {
// Valid PDF file selected
setSelectedFile(file);
} else {
// Invalid file type
alert('Please select a valid PDF file.');
e.target.value = ''; // Clear the input field
}
};

const UploadDoc = async () => {
if (!selectedFile) {
alert('Please select a PDF file before uploading.');
return;
}

// Create a new FormData object
const formData = new FormData();
formData.append('pdfFile', selectedFile); // 'pdfFile' should be the field name expected by your backend

try {
// Make a POST request using Axios
const response = await axios.post('/upload-file', //Assuming axios and proxy are already set up
formData, {
headers: {
'Content-Type': 'multipart/form-data',
},
});

if (response.status === 200) {
alert('File uploaded successfully!');
// You can handle any additional logic here after successful upload
} else {
alert('File upload failed. Please try again.');
}
} catch (error) {
console.error('Error uploading file:', error);
alert('An error occurred while uploading the file. Please try again.');
}
};

return (
<div>
<h2>PDF File Upload</h2>
<input
type="file"
accept=".pdf" //we are uploading pdf only but it is not necessary
onChange={handleFileChange}
/>
{selectedFile && (
<p>Selected file: {selectedFile.name}</p>
)}
<button onClick={UploadDoc}>Upload File</button>
</div>
);
};

export default FileUploadComponent;

Next, we’ll leverage Node.js to handle the uploading process to SignNow. I am assuming you have already Node.js set with express-fileupload ,if not then just install it because we want that file buffer on server side so we can use it and use express-fileupload in your project like this :

const fileUpload = require(“express-fileupload”);

app.use(fileUpload())

tenantDocument: async (req, res) => {
try {
const { pdfFile } = req.files;
const PDfId = await uploadSignDoc(pdfFile);

//you can also save this id in any database ,but here we want these Id for show it on client side
return res.status(200).json({
status: "success",
message: "Document Upadated successfully",
PDfId,
});
} catch (error) {
return res.status(500).json({ msg: error.message });
}
}


//here below UploadSignDoc code for upload file and ID of that file

const uploadSignDoc = async (file) => {
const url = "https://api.signnow.com/document";
const form = new FormData();

// Create a Blob from the file data
const fileBlob = new Blob([file.data], { type: file.mimetype });

// Append the Blob to the form
form.append("file", fileBlob, file.name);
form.append("check_fields", "");

const options = {
method: "POST",
headers: {
Authorization: `Bearer ${process.env.Signow_Access_Token}`, //set Access token to env for better security
Accept: "application/json",
},
body: form, //here we are sending file
};

try {
const response = await fetch(url, options);
const data = await response.json();
console.log(data, "datatatta"); //we can see what we are getting in response
return data;
} catch (error) {
console.error(error);
}
};

Now, we will move on to the next step, which involves rendering the document on the frontend side. Let’s proceed :

To render or display the document, we require two essential elements. Firstly, we need the ID of the document, and secondly, we need the access token obtained by calling the ‘getAccessToken’ function. It’s important to note that the access token has a limited duration, so each time we render the document, we must make an API call to obtain the latest access token.

Assuming we’ve stored the access token in a variable named access_token and the document ID in Id, we can effortlessly incorporate them into an iframe like this :

import React,{,useStateuseEffect} from 'react';

const IframeComponent = () => {
const [access_token,setAccessToken]=useState() //use redux or any state management tool for better experience
useEffect(()=>{
let access=getAccessToken();
setAccessToken(access.data.data)
},[])
//when we upload doc then we will get id of doc but in this component we don't have that if so use any state management toole or save it into database and get that here
return (
<>
{/* uploadSignDoc function will return a id and that id we are using here */}
{Id && accesstoken ? (
<iframe
className="iframe-100"
width="100%"
height="100%"
src={`https://app.signnow.com/webapp/document/${Id}?access_token=${accesstoken}`} //Design iframe according to your required
></iframe>
) : (
<h5>No doc uploaded</h5>
)}
</>
);
};

export default IframeComponent;

Now, let’s move on to the final part where we’ll explore how to download that document with just a single click. Let’s get started!

First we will create frontend part here :

//this is frontend
import React from 'react';

const DownloadFile = () => {
const handleDownload = () => {
try {
const response = await axios.get(`/download/${id}`, {
headers: {
"Content-Type": "application/json",

},
responseType: 'blob',
});

// Access the binary data directly from response.data
const blobData = response.data;

// Now you can do something with the blobData, for example, create a download link
const downloadLink = document.createElement('a');
downloadLink.href = URL.createObjectURL(blobData);
downloadLink.download = 'Document.pdf'; // Replace with the desired file name

// Append the link to the document, trigger a click, and then remove the link
document.body.appendChild(downloadLink);
downloadLink.click();
document.body.removeChild(downloadLink);
} catch (error) {
dispatch(ShowSnackBar({ severity: "error", message: error.message }));
}
};

return (
<div>
<button onClick={handleDownload}>Download</button>
</div>
);
};

export default DownloadFile;

Now time to create API for it :

//this is backend and in this way we can send any pdf file to frontend so it is usefull for other node.js application where we want to send file from server side to client side
dowloadFile: async (req, res) => {
try {
const fileId = req.params.id; //it will be doc id which we want to download

// Set the custom headers you need
const headers = {
Authorization: `Basic ${process.env.Signow_Authorization_Token}`, //SignNow give AUthorization
};

const apiUrl = `https://api.signnow.com/document/${fileId}/download?type=collapsed`;

// Make a GET request to the API endpoint
const response = await fetch(apiUrl, {
method: "GET",
headers: headers,
});
if (response.ok) {
// Convert the array buffer to a Buffer
const arrayBuffer = await response.arrayBuffer();
const buffer = Buffer.from(arrayBuffer);

// Set the necessary headers for the response
res.setHeader('Content-Type', 'application/pdf');
res.setHeader('Content-Disposition', `attachment; filename=${fileId}.pdf`);

// Send the Buffer as the response
res.end(buffer);
} else {
// Handle non-successful response
res.status(response.status).json({ error: 'Failed to download file' });
}

} catch (error) {
// Handle any unexpected errors and return the error response
res.status(500).json({ error: "Internal Server Error" });
}
},

Feel free to reach out if you come across any errors or encounter any issues here. I’m here to help 🙂!

Happy coding…😊

Sign up to discover human stories that deepen your understanding of the world.

Free

Distraction-free reading. No ads.

Organize your knowledge with lists and highlights.

Tell your story. Find your audience.

Membership

Read member-only stories

Support writers you read most

Earn money for your writing

Listen to audio narrations

Read offline with the Medium app

--

--

Abhishek Mishra
Abhishek Mishra

Written by Abhishek Mishra

Full stack developer 👨🏽‍💻 | MERN STACK | Rust🦀

No responses yet

Write a response