Skip to main content
This example demonstrates the comprehensive file upload capabilities of VK-IO. You’ll learn how to upload files from various sources including file paths, streams, buffers, and URLs.

What You’ll Learn

  • Uploading files from different sources
  • Working with the Upload API
  • Uploading photos for walls, albums, and messages
  • Uploading multiple files at once
  • Custom upload URLs and timeouts
  • Automatic content type detection

Prerequisites

1

Install dependencies

npm install vk-io
# Optional: for URL uploads
npm install node-fetch
2

Set up your access token

export TOKEN=your_vk_access_token

Upload Sources

VK-IO supports uploading files from multiple sources:

File Path

const { VK } = require('vk-io');

const vk = new VK({
    token: process.env.TOKEN,
});

vk.upload.wallPhoto({
    source: {
        value: './path/to/cat1.jpg',
    },
});
When uploading from a file path, VK-IO automatically detects the content type and filename from the file extension.

File Stream

const fs = require('fs');

vk.upload.wallPhoto({
    source: {
        value: fs.createReadStream('./path/to/cat2.jpg'),
    },
});

Buffer

const fs = require('fs');

vk.upload.wallPhoto({
    source: {
        value: fs.readFileSync('./path/to/cat3.jpg'),
    },
});

URL (Direct)

vk.upload.wallPhoto({
    source: {
        value: 'http://lorempixel.com/400/200/cats/',
    },
});
When uploading from a URL, VK-IO downloads the file and uploads it to VK’s servers.

URL to Buffer

const fetch = require('node-fetch');

fetch('http://lorempixel.com/400/200/cats/')
    .then(response => response.buffer())
    .then(buffer =>
        vk.upload.wallPhoto({
            source: {
                value: buffer,
            },
        }),
    );

URL to Stream

const fetch = require('node-fetch');

fetch('http://lorempixel.com/400/200/cats/').then(response =>
    vk.upload.wallPhoto({
        source: {
            value: response.body,
            contentLength: response.headers.get('content-length'),
        },
    }),
);

Complete Upload Example

const { VK } = require('vk-io');
const fetch = require('node-fetch');
const fs = require('fs');

const vk = new VK({
    token: process.env.TOKEN,
});

// Upload photos from various sources
Promise.all([
    /* File path */
    vk.upload.wallPhoto({
        source: {
            value: './path/to/cat1.jpg',
        },
    }),

    /* File stream */
    vk.upload.wallPhoto({
        source: {
            value: fs.createReadStream('./path/to/cat2.jpg'),
        },
    }),

    /* Buffer */
    vk.upload.wallPhoto({
        source: {
            value: fs.readFileSync('./path/to/cat3.jpg'),
        },
    }),

    /* URL */
    vk.upload.wallPhoto({
        source: {
            value: 'http://lorempixel.com/400/200/cats/',
        },
    }),

    /* URL Buffer */
    fetch('http://lorempixel.com/400/200/cats/')
        .then(response => response.buffer())
        .then(buffer =>
            vk.upload.wallPhoto({
                source: {
                    value: buffer,
                },
            }),
        ),

    /* URL Stream */
    fetch('http://lorempixel.com/400/200/cats/').then(response =>
        vk.upload.wallPhoto({
            source: {
                value: response.body,
                contentLength: response.headers.get('content-length'),
            },
        }),
    ),
]).then(photos => {
    console.log('All photos uploaded successfully:', photos);
});

Custom Content Type and Filename

For files without extensions or with custom formats, you can specify the content type and filename:
// JPEG stored as .dat file
vk.upload.wallPhoto({
    source: {
        value: './path/to/cat1.dat',
        contentType: 'image/jpeg',
        filename: 'cat1.jpg',
    },
});

// PNG file without extension
vk.upload.wallPhoto({
    source: {
        value: fs.createReadStream('./path/to/cat2'),
        contentType: 'image/png',
        filename: 'cat2.png',
    },
});
Specifying contentType and filename is useful when working with files that don’t have standard extensions or when the MIME type cannot be automatically detected.

Uploading Multiple Files

Some upload methods support multiple files (like photoAlbum):
vk.upload.photoAlbum({
    source: {
        timeout: 1e3 * 60, // 60 seconds timeout
        values: [
            {
                value: './path/to/cat1.jpg',
            },
            {
                value: 'http://lorempixel.com/400/200/cats/',
            },
            {
                value: fs.createReadStream('./path/to/cat2.jpg'),
            },
            {
                value: fs.createReadStream('./path/to/cat3.jpg'),
                filename: 'cat3.jpg',
            },
            {
                value: './path/to/cat5.dat',
                contentType: 'image/jpeg',
                filename: 'cat5.jpg',
            },
        ],
    },
});
Note the use of values (plural) instead of value when uploading multiple files. Each item in the array follows the same format as single file uploads.

Custom Upload URL and Timeout

You can customize the upload URL or set custom timeouts:
vk.upload.photoAlbum({
    source: {
        uploadUrl: '<custom upload url>', // Optional: custom upload endpoint
        timeout: 60e3, // 60 seconds
        values: [
            {
                value: '<value>',
            },
        ],
    },
});

Upload Methods

VK-IO provides various upload methods for different content types:

Photos

vk.upload.wallPhoto({
    source: { value: './photo.jpg' },
});

Videos

vk.upload.video({
    title: 'My Video',
    description: 'Video description',
    source: {
        value: './video.mp4',
    },
});

Documents

vk.upload.messageDocument({
    source: {
        value: './document.pdf',
        filename: 'document.pdf',
    },
    title: 'Important Document',
});

Audio

vk.upload.audio({
    source: {
        value: './song.mp3',
    },
    artist: 'Artist Name',
    title: 'Song Title',
});

Stories

vk.upload.storiesPhoto({
    source: {
        value: './story.jpg',
    },
});

vk.upload.storiesVideo({
    source: {
        value: './story.mp4',
    },
});

Using Uploads in Messages

After uploading, you can attach files to messages:
const [photo] = await vk.upload.messagePhoto({
    source: {
        value: 'https://loremflickr.com/400/300/',
    },
});

await vk.api.messages.send({
    peer_id: 123456789,
    message: 'Check out this photo!',
    attachment: photo.toString(),
    random_id: Math.random(),
});
Or use the convenient context methods:
vk.updates.on('message_new', async context => {
    if (context.text === '/photo') {
        await context.sendPhotos({
            value: 'https://loremflickr.com/400/300/',
        });
    }
});

Error Handling

Always handle upload errors properly:
try {
    const photo = await vk.upload.wallPhoto({
        source: {
            value: './photo.jpg',
        },
    });
    
    console.log('Photo uploaded:', photo);
} catch (error) {
    if (error.code === 'ENOENT') {
        console.error('File not found');
    } else {
        console.error('Upload failed:', error.message);
    }
}

Best Practices

  • Use streams for large files to avoid loading them entirely into memory
  • Set appropriate timeouts for large file uploads
  • Always specify content type for files without standard extensions
  • Handle errors gracefully with try-catch blocks
  • Use Promise.all() to upload multiple files concurrently

Next Steps

Build docs developers (and LLMs) love