CtrlK
BlogDocsLog inGet started
Tessl Logo

tessl/npm-superagent

Elegant & feature rich browser / node HTTP with a fluent API

Pending
Overview
Eval results
Files

file-uploads.mddocs/

File Uploads

Multipart form data support for file uploads and form submissions with comprehensive options for handling files, streams, and buffers.

Capabilities

File Attachment

Methods for attaching files to multipart requests.

/**
 * Attach a file to the request as multipart/form-data
 * @param {string} field - Form field name
 * @param {string|Buffer|Stream} file - File path, Buffer, or Stream
 * @param {string|object} [options] - Filename string or options object
 * @param {string} [options.filename] - Custom filename
 * @param {string} [options.contentType] - Custom content type
 * @returns {Request} Request instance for chaining
 */
Request.prototype.attach(field, file, options?): Request;

/**
 * Add a form field to multipart request
 * @param {string} name - Field name
 * @param {string|number|boolean} value - Field value
 * @returns {Request} Request instance for chaining
 */
Request.prototype.field(name, value): Request;

Usage Examples:

const superagent = require('superagent');
const fs = require('fs');

// Upload file from filesystem
superagent
  .post('https://api.example.com/upload')
  .attach('file', '/path/to/document.pdf');

// Upload with custom filename
superagent
  .post('https://api.example.com/upload')
  .attach('file', '/path/to/document.pdf', 'my-document.pdf');

// Upload with options object
superagent
  .post('https://api.example.com/upload')
  .attach('file', '/path/to/document.pdf', {
    filename: 'custom-name.pdf',
    contentType: 'application/pdf'
  });

// Upload Buffer
const buffer = Buffer.from('Hello World');
superagent
  .post('https://api.example.com/upload')
  .attach('file', buffer, 'hello.txt');

// Upload Stream
const stream = fs.createReadStream('/path/to/large-file.zip');
superagent
  .post('https://api.example.com/upload')
  .attach('file', stream, 'archive.zip');

Form Fields

Add non-file form fields to multipart requests.

// Mixed form with file and fields
superagent
  .post('https://api.example.com/upload')
  .field('title', 'My Document')
  .field('description', 'A sample document')
  .field('category', 'documents')
  .attach('file', '/path/to/document.pdf');

// Multiple values for same field
superagent
  .post('https://api.example.com/upload')
  .field('tags', 'document')
  .field('tags', 'pdf')
  .field('tags', 'important')
  .attach('file', '/path/to/document.pdf');

Multiple File Uploads

Upload multiple files in a single request.

// Multiple files with different field names
superagent
  .post('https://api.example.com/upload')
  .attach('document', '/path/to/document.pdf')
  .attach('image', '/path/to/image.jpg')
  .attach('archive', '/path/to/data.zip');

// Multiple files with same field name
superagent
  .post('https://api.example.com/upload')
  .attach('files', '/path/to/file1.txt')
  .attach('files', '/path/to/file2.txt')
  .attach('files', '/path/to/file3.txt');

// Mixed upload with metadata
superagent
  .post('https://api.example.com/upload')
  .field('user_id', '12345')
  .field('upload_type', 'batch')
  .attach('files', '/path/to/file1.txt', 'first-file.txt')
  .attach('files', '/path/to/file2.txt', 'second-file.txt');

Dynamic File Uploads

Upload files with dynamic content or from various sources.

// Upload from URL (download and upload)
const response = await superagent.get('https://example.com/remote-file.pdf');
superagent
  .post('https://api.example.com/upload')
  .attach('file', response.body, 'downloaded-file.pdf');

// Upload generated content
const csvData = 'name,age\nJohn,30\nJane,25';
const csvBuffer = Buffer.from(csvData);
superagent
  .post('https://api.example.com/upload')
  .attach('csv', csvBuffer, {
    filename: 'data.csv',
    contentType: 'text/csv'
  });

// Upload with progress tracking
superagent
  .post('https://api.example.com/upload')
  .attach('file', '/path/to/large-file.zip')
  .on('progress', (event) => {
    console.log(`Upload progress: ${event.percent}%`);
    console.log(`Loaded: ${event.loaded} / Total: ${event.total}`);
  });

Error Handling

Handle common file upload errors.

// Upload with comprehensive error handling
superagent
  .post('https://api.example.com/upload')
  .attach('file', '/path/to/document.pdf')
  .field('title', 'My Document')
  .end((err, res) => {
    if (err) {
      if (err.code === 'ENOENT') {
        console.error('File not found');
      } else if (err.status === 413) {
        console.error('File too large');
      } else if (err.status === 415) {
        console.error('Unsupported file type');
      } else {
        console.error('Upload failed:', err.message);
      }
      return;
    }
    
    console.log('Upload successful:', res.body);
  });

// Promise-based error handling
try {
  const response = await superagent
    .post('https://api.example.com/upload')
    .attach('file', '/path/to/document.pdf');
  
  console.log('Upload successful:', response.body);
} catch (err) {
  console.error('Upload failed:', err.message);
}

Advanced Upload Patterns

Chunked Upload

For large files, consider chunked upload patterns:

const fs = require('fs');
const path = require('path');

async function uploadLargeFile(filePath, chunkSize = 1024 * 1024) {
  const stats = fs.statSync(filePath);
  const totalSize = stats.size;
  let uploaded = 0;
  
  // Initialize upload session
  const session = await superagent
    .post('https://api.example.com/upload/init')
    .send({
      filename: path.basename(filePath),
      size: totalSize
    });
  
  const sessionId = session.body.sessionId;
  
  // Upload chunks
  while (uploaded < totalSize) {
    const start = uploaded;
    const end = Math.min(uploaded + chunkSize, totalSize);
    const chunk = fs.createReadStream(filePath, { start, end: end - 1 });
    
    await superagent
      .post(`https://api.example.com/upload/chunk/${sessionId}`)
      .attach('chunk', chunk)
      .field('offset', start.toString())
      .field('size', (end - start).toString());
    
    uploaded = end;
    console.log(`Uploaded: ${uploaded}/${totalSize} bytes`);
  }
  
  // Finalize upload
  const result = await superagent
    .post(`https://api.example.com/upload/finalize/${sessionId}`);
  
  return result.body;
}

Upload Validation

Validate files before uploading:

const fs = require('fs');
const path = require('path');

function validateFile(filePath) {
  const stats = fs.statSync(filePath);
  const ext = path.extname(filePath).toLowerCase();
  
  // Check file size (max 10MB)
  if (stats.size > 10 * 1024 * 1024) {
    throw new Error('File too large (max 10MB)');
  }
  
  // Check file type
  const allowedTypes = ['.pdf', '.jpg', '.jpeg', '.png', '.doc', '.docx'];
  if (!allowedTypes.includes(ext)) {
    throw new Error('Unsupported file type');
  }
  
  return true;
}

// Usage
try {
  validateFile('/path/to/document.pdf');
  
  const response = await superagent
    .post('https://api.example.com/upload')
    .attach('file', '/path/to/document.pdf');
    
  console.log('Upload successful');
} catch (err) {
  console.error('Validation or upload failed:', err.message);
}

Content Type Detection

Automatic and manual content type handling:

// Automatic content type detection (based on file extension)
superagent
  .post('https://api.example.com/upload')
  .attach('file', '/path/to/image.jpg'); // Automatically sets image/jpeg

// Manual content type override
superagent
  .post('https://api.example.com/upload')
  .attach('file', '/path/to/data.bin', {
    filename: 'data.json',
    contentType: 'application/json'
  });

// Content type for Buffers
const jsonData = JSON.stringify({ key: 'value' });
const buffer = Buffer.from(jsonData);
superagent
  .post('https://api.example.com/upload')
  .attach('data', buffer, {
    filename: 'data.json',
    contentType: 'application/json'
  });

Install with Tessl CLI

npx tessl i tessl/npm-superagent

docs

agent-sessions.md

auth-security.md

file-uploads.md

http-methods.md

index.md

parsers-serializers.md

request-building.md

request-execution.md

response-handling.md

tile.json