注:本文提到的「steam.js」并非Steam官方推出的正式SDK,而是JavaScript生态中各类对接Steam OpenAPI、Steamworks接口的封装库的统称(包括
steam、steamapi、steamworks.js等社区主流工具),因开发者习惯将其简称为steam.js,本文沿用这一称谓。
对于独立游戏开发者、Steam MOD创作者而言,批量上传创意工坊内容、自动化管理云存档是高频需求,但Steam官方原生SDK基于C++开发,对JS生态开发者不够友好,而steam.js的出现完美解决了这个痛点:只需用熟悉的JS语法,就能快速实现Steam平台各类资源的上传操作,甚至可以集成到CI/CD流程实现自动化发布。
本文将从前置准备、核心场景实战、坑点排查三个维度,手把手教你用steam.js完成Steam平台的上传功能。
前置准备:搞定环境与权限
在开始写代码前,需要先准备好账号权限和开发环境:
账号与权限要求
- 普通用户场景(上传创意工坊MOD、社区内容):拥有可正常使用的Steam账号,且账号未被限制社区功能,上传对应游戏的MOD需要账号拥有该游戏。
- 开发者场景(上传云存档、官方创意工坊内容):需要加入Steamworks开发者计划,拥有对应游戏的AppID管理权限,以及Steam发布者API密钥。
- 通用API Key申请:登录Steam开发者API页面,填写任意域名(本地开发可填
localhost),同意协议后即可获取32位API Key(敏感信息切勿泄露)。
开发环境
- 安装Node.js 16+ 版本(推荐用LTS版本),确保npm/pnpm可用。
- 本文核心依赖:
steam:社区最主流的Steam协议JS封装库(俗称steam.js核心包),支持账号登录、基础接口调用。steam-workshop:基于steam封装的创意工坊工具库,简化上传流程。dotenv:用于管理敏感环境变量,避免账号密码硬编码。
核心实战1:Steam创意工坊物品上传
创意工坊MOD上传是steam.js最常用的场景,适合批量上传MOD、自动化更新内容,无需手动打开Steam客户端操作。
步骤1:初始化项目
创建新文件夹,执行以下命令初始化项目并安装依赖:
npm init -y npm install steam steam-workshop dotenv
在项目根目录创建.env文件,存放敏感信息:
STEAM_USERNAME=你的Steam账号 STEAM_PASSWORD=你的Steam密码 STEAM_GUARD_CODE=Steam手机令牌验证码(可选,可配合steam-totp自动生成)
步骤2:编写上传代码
创建upload-workshop.js文件,实现Steam登录→创建创意工坊物品→上传内容的全流程:
// 加载环境变量
require('dotenv').config();
const SteamUser = require('steam-user');
const SteamWorkshop = require('steam-workshop');
const path = require('path');
// 1. 初始化Steam客户端和创意工坊工具
const steamClient = new SteamUser();
const workshop = new SteamWorkshop(steamClient);
// 2. 配置上传参数
const CONFIG = {
appId: 480, // 游戏AppID,示例用Steam官方测试游戏Spacewar的ID,替换为目标游戏ID '用Steam.js上传的测试MOD',
modDescription: '这是通过steam.js自动上传的创意工坊测试内容,支持批量更新。',
modContentPath: path.resolve(__dirname, './mod-files'), // 本地MOD文件夹路径
modPreviewPath: path.resolve(__dirname, './preview.jpg'), // 预览图路径(必须为JPG/PNG,建议512x512)
tags: ['测试', '工具'], // MOD标签
visibility: 0 // 可见性:0=公开,1=好友可见,2=私密
};
// 3. 登录Steam账号
steamClient.logOn({
accountName: process.env.STEAM_USERNAME,
password: process.env.STEAM_PASSWORD,
twoFactorCode: process.env.STEAM_GUARD_CODE // 开启手机令牌需填写
});
// 4. 登录成功后执行上传
steamClient.on('loggedOn', async () => {
console.log('✅ Steam账号登录成功');
try {
// 4.1 首次上传需创建创意工坊物品(更新已有MOD可跳过此步,直接用已有publishedFileId)
console.log('🔨 正在创建创意工坊物品...');
const createRes = await workshop.createItem(CONFIG.appId);
const publishedFileId = createRes.publishedFileId;
console.log(`📦 物品创建成功,ID:${publishedFileId}`);
// 4.2 上传MOD内容和元信息
console.log('⬆️ 正在上传MOD内容...');
await workshop.updateItem(publishedFileId, {
title: CONFIG.modTitle,
description: CONFIG.modDescription,
contentPath: CONFIG.modContentPath,
previewPath: CONFIG.modPreviewPath,
tags: CONFIG.tags,
visibility: CONFIG.visibility
});
console.log(`🎉 MOD上传成功!访问地址:https://steamcommunity.com/sharedfiles/filedetails/?id=${publishedFileId}`);
steamClient.logOff();
} catch (err) {
console.error('❌ 上传失败:', err.message);
steamClient.logOff();
}
});
步骤3:运行脚本
把你的MOD文件放到mod-files文件夹,添加预览图preview.jpg,执行以下命令即可完成上传:
node upload-workshop.js
小技巧:如果需要全自动登录无需手动输入令牌,可以安装
steam-totp包,传入账号的shared_secret自动生成动态验证码。
核心实战2:Steam云存档上传
Steam云存档上传分为两类场景,对应不同的steam.js方案:
场景A:游戏客户端内云存档上传(面向玩家)
如果是Electron开发的桌面游戏、或游戏内嵌的网页界面,推荐用steamworks.js——它对接了原生Steamworks SDK,只要用户登录了Steam客户端,就能直接调用云存档上传能力,无需额外申请API Key。
示例代码(Electron环境):
// 安装依赖:npm install steamworks.js
const Steamworks = require('steamworks.js');
// 初始化Steamworks(需要游戏AppID,且用户已登录Steam客户端)
const client = Steamworks.init(480);
// 上传云存档文件
const saveContent = Buffer.from('玩家存档内容');
const result = client.remote_storage.uploadFile('save_slot1.dat', saveContent);
console.log(result ? '✅ 云存档上传成功' : '❌ 上传失败');
场景B:开发者后台云存档上传(面向开发者)
如果是游戏开发者需要修复玩家存档、批量管理云存档,可以用steam.js调用Steam Web API的ISteamRemoteStorage接口实现上传,需要用到Steam发布者密钥。
示例代码(用轻量steam.js封装库steamapi):
require('dotenv').config();
const SteamAPI = require('steamapi');
const fs = require('fs');
// 初始化Steam API客户端(需传入开发者发布者密钥)
const steam = new SteamAPI(process.env.STEAM_PUBLISHER_KEY);
const CONFIG = {
appId: 480,
userSteamId: '76561198000000000', // 玩家的SteamID64
localSavePath: './player-save.dat',
cloudFileName: 'save/slot1.dat' // 云存档中的文件路径
};
(async () => {
try {
const saveBuffer = fs.readFileSync(CONFIG.localSavePath);
// 调用云存档上传接口
const res = await steam.call('ISteamRemoteStorage', 'UploadFile', 'v1', {
appid: CONFIG.appId,
steamid: CONFIG.userSteamId,
filename: CONFIG.cloudFileName,
file: saveBuffer,
length: saveBuffer.length
});
console.log('✅ 云存档上传成功:', res);
} catch (err) {
console.error('❌ 上传失败:', err.message);
}
})();
浏览器端Steam.js上传的可行性说明
很多前端开发者会尝试在纯网页中调用steam.js上传,但Steam官方Web API默认不开启CORS跨域,普通网页无法直接调用上传接口,目前主流解决方案有三种:
- 服务端代理中转:用Node.js搭建后端服务,前端将文件上传到后端,再由后端调用Steam API完成上传,是最稳定的方案。
- Steam内置浏览器场景:如果页面运行在Steam客户端内置浏览器(比如游戏Overlay、商店页),可以通过Steam官方提供的
SteamClient原生JS接口调用上传能力,无需跨域。 - Electron桌面端:集成
steamworks.js直接对接本地Steam客户端,实现无API Key的上传。
常见坑点排查
- 403 Forbidden错误
- 检查API Key、账号密码是否正确,Steam Guard是否验证通过;
- 确认账号拥有对应游戏的权限,云存档上传需使用开发者发布者密钥,普通用户Key无权限。
- 创意工坊提示“预览图无效”
- 预览图必须为JPG/PNG格式,分辨率不小于128x128,大小不超过5MB;
- 首次上传必须提供预览图,更新时可省略。
- 文件大小超限
- 创意工坊单物品大小由对应游戏开发者设置(常见为100MB-2GB),可在游戏创意工坊页面查看限制;
- 云存档单文件大小不能超过游戏后台配置的上限。
- /描述乱码
- 确保JS文件编码为UTF-8,部分旧版封装库需要手动对中文参数执行
encodeURIComponent编码。
- 确保JS文件编码为UTF-8,部分旧版封装库需要手动对中文参数执行
- 上传后物品不可见
- 部分游戏的创意工坊需要人工审核,审核通过后才会公开显示;
- 检查物品可见性设置是否为“私密”或“好友可见”。
Steam.js极大降低了JS生态开发者对接Steam平台的门槛,无论是批量上传创意工坊MOD、自动化云存档管理,还是集成到CI/CD流程实现游戏内容自动发布,都能通过少量代码快速实现。
需要注意的是,社区封装的steam.js库可能存在版本滞后、接口不全的问题,如果是复杂的上传需求(比如大文件分片上传、批量物品管理),建议直接对接Steam官方Web API,结合Node.js的HTTP库自行封装,灵活性更高,最后请遵守Steam平台用户协议,避免上传违规内容导致账号封禁。

