Skip to content
nodejs使用蓝奏云上传并分享
js
const https = require('https');
const fs = require('fs');
const path = require('path');

// 配置信息
const config = {
  hostname: 'pc.woozooo.com',
  port: 443,
  path: '/html5up.php',
  method: 'POST',
  cookie: 'XXXXXXXX',   // 请替换为实际的蓝奏云cookie
};

/**
 * 上传文件到网盘并获取下载链接
 * @param {string} filePath - 文件的绝对路径或相对路径
 * @returns {Promise<{success: boolean, url?: string, pwd?: string, error?: string}>} - 上传结果
 */
function uploadFile(filePath) {
  return new Promise((resolve, reject) => {
    try {
      // 解析文件路径
      const resolvedPath = path.isAbsolute(filePath) ? filePath : path.join(process.cwd(), filePath);
      const fileName = path.basename(resolvedPath);
      
      // 检查文件是否存在
      if (!fs.existsSync(resolvedPath)) {
        reject({ success: false, error: `文件不存在: ${resolvedPath}` });
        return;
      }
      
      // 读取文件
      const fileBuffer = fs.readFileSync(resolvedPath);
      const fileSize = fileBuffer.length;
      const fileModifiedDate = new Date().toUTCString();
      
      console.log('开始上传文件:', fileName);
      console.log('文件大小:', fileSize, 'bytes');
      
      // 生成boundary
      const boundary = '----WebKitFormBoundary' + Math.random().toString(36).substring(2, 15);
      
      // 构建multipart form-data
      const formData = buildFormData(boundary, fileName, fileBuffer, fileSize, fileModifiedDate);
      
      // 发送上传请求
      uploadFileToServer(formData, boundary, fileName)
        .then(result => resolve(result))
        .catch(error => reject({ success: false, error: error.message || error }));
        
    } catch (error) {
      reject({ success: false, error: error.message });
    }
  });
}

// 构建multipart form-data
function buildFormData(boundary, fileName, fileBuffer, fileSize, fileModifiedDate) {
  const chunks = [];
  
  // 添加表单字段
  const fields = [
    { name: 'task', value: '1' },
    { name: 'vie', value: '2' },
    { name: 've', value: '2' },
    { name: 'id', value: 'WU_FILE_2' },
    { name: 'name', value: fileName },
    { name: 'type', value: 'text/plain' },
    { name: 'lastModifiedDate', value: fileModifiedDate },
    { name: 'size', value: fileSize.toString() },
    { name: 'folder_id_bb_n', value: '-1' }
  ];

  fields.forEach(field => {
    chunks.push(Buffer.from(`--${boundary}\r\n`));
    chunks.push(Buffer.from(`Content-Disposition: form-data; name="${field.name}"\r\n\r\n`));
    chunks.push(Buffer.from(`${field.value}\r\n`));
  });

  // 添加文件
  chunks.push(Buffer.from(`--${boundary}\r\n`));
  chunks.push(Buffer.from(`Content-Disposition: form-data; name="upload_file"; filename="${fileName}"\r\n`));
  chunks.push(Buffer.from(`Content-Type: text/plain\r\n\r\n`));
  chunks.push(fileBuffer);
  chunks.push(Buffer.from(`\r\n--${boundary}--\r\n`));

  return Buffer.concat(chunks);
}

// 上传文件到服务器
function uploadFileToServer(formData, boundary, fileName) {
  return new Promise((resolve, reject) => {
    const options = {
      hostname: config.hostname,
      port: config.port,
      path: config.path,
      method: config.method,
      headers: {
        'Accept': '*/*',
        'Accept-Encoding': 'gzip, deflate, br',
        'Accept-Language': 'zh-CN,zh;q=0.9',
        'Cache-Control': 'no-cache',
        'Content-Length': formData.length,
        'Content-Type': `multipart/form-data; boundary=${boundary}`,
        'Cookie': config.cookie,
        'Origin': 'https://pc.woozooo.com',
        'Pragma': 'no-cache',
        'Priority': 'u=1, i',
        'Sec-Ch-Ua': '"Google Chrome";v="147", "Not.A/Brand";v="8", "Chromium";v="147"',
        'Sec-Ch-Ua-Mobile': '?0',
        'Sec-Ch-Ua-Platform': '"Windows"',
        'Sec-Fetch-Dest': 'empty',
        'Sec-Fetch-Mode': 'cors',
        'Sec-Fetch-Site': 'same-origin',
        'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/147.0.0.0 Safari/537.36'
      }
    };

    const req = https.request(options, (res) => {
      let data = '';
      res.on('data', (chunk) => {
        data += chunk;
      });

      res.on('end', () => {
        if (res.statusCode === 200) {
          try {
            const uploadResult = JSON.parse(data);
            
            if (uploadResult.zt === 1 && uploadResult.text && uploadResult.text.length > 0) {
              const fileId = uploadResult.text[0].id;
              const domain = uploadResult.text[0].is_newd;
              
              console.log('✓ 文件上传成功!');
              console.log('文件ID:', fileId);
              
              // 获取下载链接
              getDownloadLink(fileId, domain)
                .then(linkInfo => {
                  console.log('✓ 获取下载链接成功!');
                  resolve(linkInfo);
                })
                .catch(error => reject(error));
            } else {
              reject(new Error(uploadResult.info || '上传失败'));
            }
          } catch (error) {
            reject(new Error('解析上传响应失败: ' + error.message));
          }
        } else {
          reject(new Error(`上传失败,状态码: ${res.statusCode}`));
        }
      });
    });

    req.on('error', (error) => {
      reject(error);
    });

    req.write(formData);
    req.end();
  });
}

// 获取下载链接
function getDownloadLink(fileId, domain) {
  return new Promise((resolve, reject) => {
    const postData = `task=22&file_id=${fileId}`;
    
    const downloadOptions = {
      hostname: config.hostname,
      port: config.port,
      path: '/doupload.php',
      method: 'POST',
      headers: {
        'Accept': 'application/json, text/javascript, */*; q=0.01',
        'Accept-Encoding': 'gzip, deflate, br',
        'Accept-Language': 'zh-CN,zh;q=0.9',
        'Cache-Control': 'no-cache',
        'Content-Type': 'application/x-www-form-urlencoded; charset=UTF-8',
        'Content-Length': Buffer.byteLength(postData),
        'Cookie': config.cookie,
        'Origin': 'https://pc.woozooo.com',
        'Pragma': 'no-cache',
        'Priority': 'u=1, i',
        'Sec-Ch-Ua': '"Google Chrome";v="147", "Not.A/Brand";v="8", "Chromium";v="147"',
        'Sec-Ch-Ua-Mobile': '?0',
        'Sec-Ch-Ua-Platform': '"Windows"',
        'Sec-Fetch-Dest': 'empty',
        'Sec-Fetch-Mode': 'cors',
        'Sec-Fetch-Site': 'same-origin',
        'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/147.0.0.0 Safari/537.36',
        'X-Requested-With': 'XMLHttpRequest'
      }
    };
    
    const downloadReq = https.request(downloadOptions, (res) => {
      let data = '';
      res.on('data', (chunk) => {
        data += chunk;
      });
      
      res.on('end', () => {
        try {
          const result = JSON.parse(data);
          
          if (result.zt === 1 && result.info) {
            const f_id = result.info.f_id;
            const is_newd = result.info.is_newd;
            const pwd = result.info.pwd || '';
            
            const fullUrl = `${is_newd}/${f_id}`;
            
            resolve({
              success: true,
              url: fullUrl,
              pwd: pwd
            });
          } else {
            reject(new Error(result.info || '获取下载链接失败'));
          }
        } catch (error) {
          reject(new Error('解析下载链接响应失败: ' + error.message));
        }
      });
    });
    
    downloadReq.on('error', (error) => {
      reject(error);
    });
    
    downloadReq.write(postData);
    downloadReq.end();
  });
}

// 使用示例
async function main() {
  try {
    // 传入文件的绝对路径
    const filePath = 'C:\\Users\\22560\\Desktop\\ceshi\\仙武帝尊.txt';
    const result = await uploadFile(filePath);
    
    if (result.success) {
      console.log('\n===== 上传结果 =====');
      console.log('下载链接:', result.url);
      if (result.pwd) {
        console.log('提取码:', result.pwd);
      }
      console.log('====================\n');
    } else {
      console.log('上传失败:', result.error);
    }
  } catch (error) {
    console.error('上传过程中发生错误:', error);
  }
}

// 运行
main();

// 导出函数供其他模块使用
module.exports = { uploadFile };