Nutrient

SDK

Cloud

Low-Code

Workflow

Node.js integration example

This example demonstrates a complete Node.js server implementation that handles document upload, session token generation, and provides the necessary endpoints for integrating with DWS Viewer API and Nutrient Web SDK.

Package dependencies

Install the required dependencies:

Shell
npm install express multer

Complete server implementation

JavaScript
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.

JavaScript
// 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:

Shell
export NUTRIENT_DWS_VIEWER_API_KEY=your_api_key_here

Or create a .env file:

NUTRIENT_DWS_VIEWER_API_KEY=your_api_key_here

Error 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