npm iUse this docker image to setup the scanner
docker run --name clamav -d -p 3310:3310 mkodockx/docker-clamavnode main.jsIn a seperate terminal, run
curl localhost:3000/upload -F 'file=@/path/to/file.ext'| const Hapi = require('@hapi/hapi') | |
| const fs = require('fs') | |
| const handleFileUpload = file => { | |
| return new Promise((resolve, reject) => { | |
| const { filename } = file.hapi | |
| const outFile = fs.createWriteStream(`./uploads/${filename}`) | |
| file | |
| .pipe(outFile) | |
| .on('error', err => { | |
| console.error(err) | |
| reject(err) | |
| }) | |
| .on('close', () => { | |
| console.log('done') | |
| resolve({ | |
| message: 'uploaded' | |
| }) | |
| }) | |
| }) | |
| } | |
| ;(async () => { | |
| const server = Hapi.server({ | |
| port: 3000 | |
| }) | |
| server.route({ | |
| path: '/upload', | |
| method: 'POST', | |
| options: { | |
| payload: { | |
| maxBytes: 1024 * 1024 * 100, // max 100MB | |
| parse: true, | |
| output: 'stream', | |
| allow: 'multipart/form-data', | |
| multipart: true | |
| } | |
| }, | |
| handler (request) { | |
| return handleFileUpload(request.payload.file) | |
| } | |
| }) | |
| await server.start() | |
| console.log('start started at %s', server.info.uri) | |
| })() |
| const Hapi = require('@hapi/hapi') | |
| const fs = require('fs') | |
| const NodeClam = require('clamscan') | |
| const clamav = new NodeClam() | |
| const handleFileUpload = (file, clamav) => { | |
| return new Promise((resolve, reject) => { | |
| const { filename } = file.hapi | |
| const dest = `./uploads/${filename}` | |
| const outFile = fs.createWriteStream(dest) | |
| const av = clamav.passthrough() | |
| av.on('scan-complete', result => { | |
| console.log(result) | |
| if (result.is_infected) { | |
| console.warn(`${filename} is infected with [${result.viruses}]`) | |
| fs.rename(dest, `${dest}.infected`, () => {}) | |
| } | |
| }) | |
| file | |
| .pipe(av) | |
| .pipe(outFile) | |
| .on('error', err => { | |
| console.error(err) | |
| reject(err) | |
| }) | |
| .on('close', () => { | |
| console.log('done') | |
| resolve({ | |
| message: 'uploaded' | |
| }) | |
| }) | |
| }) | |
| } | |
| ;(async () => { | |
| const server = Hapi.server({ | |
| port: 3000 | |
| }) | |
| server.route({ | |
| path: '/upload', | |
| method: 'POST', | |
| options: { | |
| payload: { | |
| maxBytes: 1024 * 1024 * 100, // max 100MB | |
| parse: true, | |
| output: 'stream', | |
| allow: 'multipart/form-data', | |
| multipart: true | |
| } | |
| }, | |
| handler (request) { | |
| return handleFileUpload(request.payload.file, request.server.clamav) | |
| } | |
| }) | |
| await clamav.init({ | |
| clamdscan: { | |
| host: '127.0.0.1', | |
| port: 3310 | |
| } | |
| }) | |
| server.decorate('server', 'clamav', clamav) | |
| await server.start() | |
| console.log('start started at %s', server.info.uri) | |
| })() |