Script Membuat File Kosong Ukuran Berapapun Di Server Nodejs, Lalu Mendownloadnya Melalui REST api


Script ini berfungsi untuk menghasilkan file kosong dengan ukuran size yang kita inginkan. File ini nantinya bisa kita download melalui rest api dengan format query request url sebagai berikut :

/download?name={nama-file}&size={ukuran-file-dalam-number}&format={format-file}

File yang dihasilkan tidak disimpan di server. File yang di transfer merupakan stream byte data string spasi. Data ini dikirim saat itu juga sesuai ukuran size yang di request.

Contoh Link Download

Sebagai contoh, silahkan kamu kunjungi beberapa url berikut : 

  1. Download file kosong ukuran 10 mb.
  2. Download file kosong ukuran 10 mb, format file ".txt".
  3. Download file kosong ukuran 10 mb, format file ".txt", dengan nama file "file-kosong".
Note : Jika suatu saat link demo di atas tidak dapat di akses, silahkan deploy sendiri script empty file di server nodejs kamu.

Cara Menghitung Size File

Untuk ukuran file, kamu dapat menentukan dengan rumus berikut :

1 kb = 1024
1 mb = 1024 x 1024 = 1048576
1 gb = 1024 x 1024 x 1024 = 1073741824

Misal, kamu ingin membuat file dengan ukuran 15 mb, maka size filenya adalah :

15 x 1048576 = 15728640

Script Empty File

/--- setting port --------
const port = 80;
//--- import module npm ----
const express = require('express');
const bodyParser = require('body-parser');
const isIp = require('is-ip');
const dir = process.cwd();
const app = express();
const sendData = async (res, data, time) => {
    return new Promise((resolve) => {
        res.write(data, 'utf8', () => {
            resolve();
        });
    });
};
//--- constructor url ---
app.use((req, res, next) => {
    const statusIp = isIp(req.hostname);
    let origin = req.protocol + "://" + req.hostname;
    if (statusIp && port != 80) {
        origin += ":" + port;
    };
    req.infoUrl = {
        all: origin + req.url,
        origin: origin,
        protocol: req.protocol,
        hostname: req.hostname,
        pathname: req.path,
        query: req.query,
        method: req.method,
        port: port
    };
    next();
});
//------ start ----------
app.use(async (req, res, next) => {
    const infoUrl = req.infoUrl;
    const path = infoUrl.pathname;
    const query = infoUrl.query;
    let run = true;
    res.on('close', () => {
        run = false;
        res.end();
    });
    res.on('finish', () => {
        run = false;
    });
    if (path == "/download") {
        const file = {};
        if (query.name) {
            file.name = query.name;
        } else {
            file.name = "unamed";
        };
        if (query.format) {
            file.format = query.format
        } else {
            file.format = "txt";
        };
        if (query.mime) {
            file.mime = query.mime;
        } else {
            file.mime = "text/plain";
        };
        if (query.size) {
            const numberSize = Number(query.size);
            if (isNaN(numberSize) == true) {
                res.end("err download/?size={number}, the query value 'size' must be a number")
            } else {
                file.size = 10;
                const sizeFile = (numberSize).toString(); // gb
                const headers = req.headers;
                let rangeStart = 0;
                let rangeEnd = "*";
                if (headers.range) {
                    if (headers.range.indexOf("bytes=") == 0) {
                        const range = headers.range.replace("bytes=", "");
                        const splitRange = range.split("-");
                        rangeStart = Number(splitRange[0]) + 1;
                        rangeEnd = splitRange[1];
                        if (rangeEnd.length == 0) {
                            rangeEnd = 2 * Number(rangeStart);
                            rangeStart = rangeStart - 1;
                        }
                    };
                };
                if (rangeStart == 0) {
                    res.writeHead(200, {
                        "Access-Control-Allow-Origin": "*",
                        "Content-Type": file.mime,
                        "Content-disposition": "attachment; filename=" + file.name + "." + file.format,
                        "Connection": "keep-alive",
                        "Accept-Ranges": "bytes",
                        "Content-Length": sizeFile,
                    });
                } else {
                    res.writeHead(206, {
                        "Access-Control-Allow-Origin": "*",
                        "Content-Type": file.mime,
                        "Content-disposition": "attachment; filename=" + file.name + "." + file.format,
                        "Connection": "keep-alive",
                        "Accept-Ranges": "bytes",
                        "Content-Range": "bytes " + rangeStart + "-" + rangeEnd + "/" + sizeFile,
                        "Content-Length": sizeFile,
                    });
                };
                let data = "";
                for (let i = 0; i < 1024; i++) {
                    data += " ";
                };
                while (run) {
                    await sendData(res, data);
                };
            };
        } else {
            res.writeHead(404);
            res.end("err download/?size={number}, query size not found");
        };
    } else {
        res.writeHead(404);
        res.end(`Format Request : ` + infoUrl.origin + `/download?name={name-file}&size={number-size-file-byte}&format={format-size-file}

Example : ` + infoUrl.origin + `/download?name=fake-file&size=1048576&format=txt

Design By www.maskoding.com`);
    };
    next();
});
//--- run app ----
app.listen(port, () => {
    console.log("server running on port : " + port)
});

Jika error saat mejalankan "npm install", silahkan gunakan extensi "is-ip" versi 3.1.0. Atau gunakan file package.json dibawah ini.

package.json

{
    "name": "empty-file",
    "version": "1.0.0",
    "description": "Generate an empty file with a specific size.",
    "main": "index.js",
    "scripts": {
        "test": "echo \"Error: no test specified\" && exit 1",
        "start": "node index.js"
    },
    "keywords": [
        "empty",
        "file"
    ],
    "author": "Abdi Syahputra Harahap",
    "license": "ISC",
    "dependencies": {
        "body-parser": "^1.19.1",
        "express": "^4.17.2",
        "is-ip": "^3.1.0"
    }
}

Fork

Github : https://github.com/maskodingku/Empty-File

Repl : https://replit.com/@blogspot/empty-file