代码上传你的服务器(纯node环境完成)

简介:

目前很多公司,都不是在本地开发自己代码,或者本地开发完代码后需要把build后的文件上传给远程服务器。然后进行dev环境的测试。

当然,现在有很多种方法,很多种语言或方法都可以上传代码服务器,通常简便的方法就是使用python3,但是这样需要安装python,以及安装各种插件,通常在安装的过程中并不是很安逸,都有各种报错,或者网络超时(可以切换源解决)

这次我带来的方法是使用纯血node环境 上传代码到服务器,不需要安装任何插件。只需要两个js脚本,即可完成选择本地文件夹,上传服务器的任意文件夹路径下。

好的,准备上传你的优秀代码吧,少年!!

服务端代码:

Server.js

js 复制代码
const http = require('http');
const fs = require('fs');
const path = require('path');

const UPLOAD_DIRECTORY = path.join(__dirname, 'uploads');
if (!fs.existsSync(UPLOAD_DIRECTORY)) {
    fs.mkdirSync(UPLOAD_DIRECTORY, { recursive: true });
}

const server = http.createServer((req, res) => {
    if (req.method.toLowerCase() === 'post' && req.url === '/upload') {
        const boundary = req.headers['content-type'].split('; ')[1].replace('boundary=', '');
        let rawData = Buffer.alloc(0);

        req.on('data', (chunk) => {
                rawData = Buffer.concat([rawData, chunk]);
        });

        req.on('end', () => {
                 const rawString = rawData.toString('binary');
            const parts = rawString.split('--' + boundary).filter(part => part.trim() !== '');
            let fileData = null;
            let fileName = null;
            let targetPath = '/';

            parts.forEach(part => {
                if (part.indexOf('Content-Disposition: form-data; name="file"; filename="') !== -1) {
                    const match = part.match(/filename="(.+)"/);
                    fileName = match && match[1];
                    const fileContentIndex = part.indexOf('\r\n\r\n') + 4;
                    fileData = Buffer.from(part.substring(fileContentIndex, part.length - 2), 'binary');
                } else if (part.indexOf('Content-Disposition: form-data; name="to"') !== -1) {
                    const toIndex = part.indexOf('\r\n\r\n') + 4;
                    targetPath = part.substring(toIndex, part.length - 2).trim();
                }
            });

            if (!fileName || !fileData) {
                res.writeHead(400, { 'Content-Type': 'application/json' });
                res.end(JSON.stringify({ error: 'Invalid file upload' }));
                return;
            }

            const uploadDir =  targetPath;
            if (!fs.existsSync(uploadDir)) {
                fs.mkdirSync(uploadDir, { recursive: true });
            }

            const uploadPath = path.join(uploadDir, fileName);
            const fileStream = fs.createWriteStream(uploadPath);
            fs.writeFile(uploadPath, fileData, (err) => {
                if (err) {
                    res.writeHead(500, { 'Content-Type': 'application/json' });
                    res.end(JSON.stringify({ error: 'Error saving file' }));
                    return;
                }

                res.writeHead(200, { 'Content-Type': 'application/json' });
                res.end(JSON.stringify({
                    message: 'File uploaded successfully',
                    path: uploadPath
                }));
            });
         });
    } else {
        res.writeHead(405, { 'Content-Type': 'text/html' });
        res.end('<html><head><title>405 Not Allowed</title></head><body><h1>405 Not Allowed</h1></body></html>');
    }
});

const PORT = 8500;
server.listen(PORT, () => {
    console.log(`Server is running on http://localhost:${PORT}`);
});

客户端代码

push.js

js 复制代码
const fs = require('fs');
const path = require('path');
const http = require('http');

// 从命令行参数获取文件路径和目标路径
const directoryPath = process.argv[2];  // 第一个命令行参数:本地目录路径
const targetPath = process.argv[3];  // 第二个命令行参数:目标上传路径
// 检查命令行参数是否存在
if (!directoryPath || !targetPath) {
    console.error('Usage: node upload.js <directoryPath> <targetPath>');
    process.exit(1);
}

// 递归遍历目录并上传文件的函数
const uploadDirectory = (dir, baseDir) => {
    // 读取目录中的文件和子目录
    fs.readdir(dir, (err, files) => {
        if (err) {
            console.error(`Error reading directory: ${dir}`, err);
            return;
        }

        files.forEach(file => {
            console.log("file",file);
            const filePath = path.join(dir, file);
            fs.stat(filePath, (err, stats) => {
                if (err) {
                    console.error(`Error getting stats for file: ${filePath}`, err);
                    return;
                }

                if (stats.isDirectory()) {
                    // 如果是目录,递归调用
                    uploadDirectory(filePath, baseDir);
                } else {
                    // 如果是文件,上传文件
                    uploadFile(filePath, baseDir+'/'+dir+'/');
                }
            });
        });
    });
};

// 上传单个文件的函数
const uploadFile = (filePath, relativePath) => {
    // 准备 HTTP 请求选项
    const options = {
        hostname: '自己的服务器ip',
        // port: ,
        path: '/upload',
        method: 'POST',
        headers: {
            'Content-Type': 'multipart/form-data; boundary=----WebKitFormBoundary7MA4YWxkTrZu0gW'
        }
    };

    const req = http.request(options, (res) => {
        let data = '';
        res.on('data', (chunk) => {
            data += chunk;
        });
        res.on('end', () => {
            console.log(`Uploaded: ${filePath} -> ${data}`);
        });
    });

    // 处理请求错误
    req.on('error', (error) => {
        console.error(`Error uploading file: ${filePath}`, error);
    });

    // 创建 multipart/form-data 内容
    const boundary = '----WebKitFormBoundary7MA4YWxkTrZu0gW';
    const fileName = path.basename(filePath);
    const fileStream = fs.createReadStream(filePath);

    req.write(`--${boundary}\r\n`);
    req.write(`Content-Disposition: form-data; name="file"; filename="${fileName}"\r\n`);
    req.write(`Content-Type: application/octet-stream\r\n\r\n`);

    fileStream.pipe(req, { end: false });

    fileStream.on('end', () => {
        req.write(`\r\n--${boundary}\r\n`);
        req.write(`Content-Disposition: form-data; name="to"\r\n\r\n`);
        req.write(`${relativePath}\r\n`); // 目标地址
        req.write(`--${boundary}--\r\n`);
        req.end();
    });
};

// 开始递归遍历和上传
uploadDirectory(directoryPath, targetPath);

nginx配置

js 复制代码
http {
  ...
  client_max_body_size 100M; # 文件大小限制
}
server {
  	location /upload {
                proxy_pass http://127.0.0.1:8500;  # 代理到你的 Node.js 服务器
                proxy_set_header Host $host;
                proxy_set_header X-Real-IP $remote_addr;
                proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
                proxy_set_header X-Forwarded-Proto $scheme;

                # 允许 POST 请求
                if ($request_method !~ ^(GET|POST)$ ) {
                        return 405;
                }
        }
}

上传命令:

  1. 使用pm2 start Server.js 启动服务端服务 (可以直接使用node启动,推荐pm2)
  2. 本地服务node push.js <要推送的文件地址> <目标地址> 例如: node push.js test-push/ workSpace/ [注]:有没有 / 都可以
  3. 注意文件位置!!
相关推荐
理想不理想v6 小时前
vue种ref跟reactive的区别?
前端·javascript·vue.js·webpack·前端框架·node.js·ecmascript
暮毅10 小时前
10.Node.js连接MongoDb
数据库·mongodb·node.js
~甲壳虫16 小时前
说说webpack中常见的Plugin?解决了什么问题?
前端·webpack·node.js
~甲壳虫17 小时前
说说webpack中常见的Loader?解决了什么问题?
前端·webpack·node.js
~甲壳虫17 小时前
说说webpack proxy工作原理?为什么能解决跨域
前端·webpack·node.js
熊的猫17 小时前
JS 中的类型 & 类型判断 & 类型转换
前端·javascript·vue.js·chrome·react.js·前端框架·node.js
前端青山1 天前
Node.js-增强 API 安全性和性能优化
开发语言·前端·javascript·性能优化·前端框架·node.js
GDAL1 天前
npm入门教程1:npm简介
前端·npm·node.js
郑小憨2 天前
Node.js简介以及安装部署 (基础介绍 一)
java·javascript·node.js
lin-lins2 天前
模块化开发 & webpack
前端·webpack·node.js