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

简介:

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

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

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

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

服务端代码:

Server.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

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配置         

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. 注意文件位置!!

原文:https://juejin.cn/post/739319446865009051

  • 6
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
要在Node.js中上文件到服务器,可以使用Node.js的`formidable`模块。以下是一个简单的例子,演示如何将文件上服务器: 首先,需要安装`formidable`模块: ``` npm install formidable ``` 然后,在Node.js文件中,需要引入`formidable`模块,并创建一个用于处理文件上的路由。以下是一个示例代码: ```javascript const formidable = require('formidable'); const http = require('http'); const fs = require('fs'); http.createServer(function(req, res) { if (req.url == '/upload' && req.method.toLowerCase() == 'post') { // 创建一个新的formidable.IncomingForm对象 const form = new formidable.IncomingForm(); // 设置文件上目录 form.uploadDir = "./upload"; // 保留文件扩展名 form.keepExtensions = true; // 解析上的文件 form.parse(req, function(err, fields, files) { if (err) throw err; // 将上的文件从临时目录移动到上目录 const oldpath = files.file.path; const newpath = './upload/' + files.file.name; fs.rename(oldpath, newpath, function(err) { if (err) throw err; // 文件上成功,返回客户端 res.writeHead(200, {'Content-Type': 'text/html'}); res.write('File uploaded!'); res.end(); }); }); } else { // 显示文件上表单 res.writeHead(200, {'Content-Type': 'text/html'}); res.write('<form action="/upload" method="post" enctype="multipart/form-data">'); res.write('<input type="file" name="file"><br>'); res.write('<input type="submit" value="Upload">'); res.write('</form>'); res.end(); } }).listen(3000); ``` 在上面的代码中,当用户访问`/upload`路由并提交文件上表单时,`formidable`模块将解析上的文件并将其移动到指定的上目录中。 注意,这个例子中的`uploadDir`和`newpath`都是相对路径,如果要使用绝对路径,需要将其改为绝对路径。 希望这能帮助到你!

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值