Node.js integration example
This example demonstrates a complete Node.js server implementation that handles document upload and session token generation and provides the necessary endpoints for integrating with DWS Viewer API and Nutrient Web SDK.
Package dependencies
Install the required dependencies:
npm install express multerComplete server implementation
const express = require("express");const multer = require("multer");
const upload = multer();const app = express();
app.use(express.json());
// Helper function to create session token for a document.const createSessionToken = async (documentId, apiKey) => { const sessionPayload = { allowed_documents: [ { document_id: documentId, document_permissions: ["read", "write", "download"], }, ], exp: Math.floor(Date.now() / 1000) + 60 * 60, // 1 hour from now };
const sessionResponse = await fetch( "https://api.nutrient.io/viewer/sessions", { method: "POST", headers: { "Content-Type": "application/json", Authorization: `Bearer ${apiKey}`, }, body: JSON.stringify(sessionPayload), }, );
if (!sessionResponse.ok) { throw new Error(`Session creation failed: ${sessionResponse.statusText}`); }
const sessionResult = await sessionResponse.json(); return sessionResult.jwt;};
// Upload document and generate session token.app.post( "/api/upload-and-create-session", upload.single("file"), async (req, res) => { try { const apiKey = process.env.NUTRIENT_DWS_VIEWER_API_KEY;
if (!req.file) { return res.status(400).json({ success: false, error: "No file uploaded", }); }
// Step 1: Upload document to DWS. const uploadResponse = await fetch( "https://api.nutrient.io/viewer/documents", { method: "POST", headers: { Authorization: `Bearer ${apiKey}`, "Content-Type": req.file.mimetype, "Content-Length": req.file.size.toString(), }, body: req.file.buffer, }, );
if (!uploadResponse.ok) { throw new Error(`Upload failed: ${uploadResponse.statusText}`); }
const uploadResult = await uploadResponse.json();
// Step 2: Extract document ID from nested response. const documentId = uploadResult.data?.document_id;
if (!documentId) { throw new Error("No document ID found in upload response"); }
// Step 3: Generate session token. const sessionToken = await createSessionToken(documentId, apiKey);
res.json({ success: true, documentId: documentId, sessionToken: sessionToken, title: uploadResult.data?.title || "Untitled Document", }); } catch (error) { console.error("Error:", error); res.status(500).json({ success: false, error: error.message, }); } },);
// Generate session token for existing document.app.post("/api/create-session", async (req, res) => { try { const { documentId } = req.body; const apiKey = process.env.NUTRIENT_DWS_VIEWER_API_KEY;
if (!documentId) { return res.status(400).json({ success: false, error: "Document ID is required", }); }
// Generate session token. const sessionToken = await createSessionToken(documentId, apiKey);
res.json({ success: true, sessionToken: sessionToken, }); } catch (error) { console.error("Error:", error); res.status(500).json({ success: false, error: error.message, }); }});
const PORT = process.env.PORT || 3000;app.listen(PORT, () => { console.log(`Server running on port ${PORT}`);});Frontend integration
Once your server is running, you can use the endpoints from your frontend to upload documents and load them in Nutrient Web SDK.
Security note: In production, implement proper authentication between your frontend and backend to prevent unauthorized users from uploading documents or creating session tokens. This could include user authentication, API keys, rate limiting, or other access control mechanisms appropriate for your application.
// Upload file and get session token.const uploadAndLoad = async (file) => { try { const formData = new FormData(); formData.append("file", file);
const response = await fetch("/api/upload-and-create-session", { method: "POST", body: formData, });
const result = await response.json();
if (result.success) { // Load document in Nutrient Web SDK. await NutrientViewer.load({ container: document.querySelector("#viewer-container"), session: result.sessionToken, }); } else { console.error("Upload failed:", result.error); } } catch (error) { console.error("Error:", error); }};
// Generate new session for existing document.const loadExistingDocument = async (documentId) => { try { const response = await fetch("/api/create-session", { method: "POST", headers: { "Content-Type": "application/json", }, body: JSON.stringify({ documentId }), });
const result = await response.json();
if (result.success) { await NutrientViewer.load({ container: document.querySelector("#viewer-container"), session: result.sessionToken, }); } else { console.error("Session creation failed:", result.error); } } catch (error) { console.error("Error:", error); }};Environment setup
Make sure to set your API key as an environment variable:
export NUTRIENT_DWS_VIEWER_API_KEY=your_api_key_hereOr create a .env file:
NUTRIENT_DWS_VIEWER_API_KEY=your_api_key_hereError handling
The example includes comprehensive error handling for common scenarios:
- Missing files in upload requests
- Failed document uploads
- Missing document IDs in responses
- Session token generation failures
- Invalid document IDs for existing documents
Security considerations
- API keys are kept on the server side and never exposed to the frontend
- Session tokens have expiration times to limit access duration
- File uploads are processed on the server to maintain security
- Document permissions can be customized per session token