
Security News
Feross on the 10 Minutes or Less Podcast: Nobody Reads the Code
Socket CEO Feross Aboukhadijeh joins 10 Minutes or Less, a podcast by Ali Rohde, to discuss the recent surge in open source supply chain attacks.
@atomfe/oss-uploader
Advanced tools
🚀 A powerful OSS uploader for uploading files to Aliyun OSS 🚀
Simple, Fast, and Reliable - Perfect for your deployment workflow
English | 简体中文
npm install -g @atomfe/oss-uploader
# or
pnpm add -g @atomfe/oss-uploader
# or
yarn global add @atomfe/oss-uploader
# 1. Initialize configuration (JSON)
oss-uploader init
# 2. Edit .ossrc.json with your credentials
{
"region": "YOUR_REGION",
"accessKeyId": "YOUR_ACCESS_KEY_ID",
"accessKeySecret": "YOUR_ACCESS_KEY_SECRET",
"bucket": "YOUR_BUCKET_NAME"
}
# 3. Upload files
oss-uploader upload ./file.txt
oss-uploader upload ./dist -t static/
# 1. Initialize JavaScript configuration
oss-uploader init -o oss.config.js
# 2. Set environment variables or edit oss.config.js
export OSS_REGION="oss-cn-hangzhou"
export OSS_ACCESS_KEY_ID="your-access-key-id"
export OSS_ACCESS_KEY_SECRET="your-access-key-secret"
export OSS_BUCKET="your-bucket-name"
# 3. Upload files
oss-uploader upload ./file.txt
oss-uploader upload ./dist -t static/
# Upload file(s) or directory
oss-uploader upload <sources...> [options]
# List files in OSS bucket
oss-uploader list [prefix]
# Delete file from OSS
oss-uploader delete <path>
# Show bucket information
oss-uploader info
# Create sample configuration
oss-uploader init [options]
# Options for init command:
# -o, --output <path> Output path for configuration file (default: .ossrc.json)
# -t, --type <type> Configuration file type: json or js
| Option | Description |
|---|---|
-t, --target <path> | Target path in OSS bucket |
-c, --config <path> | Configuration file path |
-r, --recursive | Upload directory recursively (default: true) |
-o, --overwrite | Overwrite existing files (default: true) |
-i, --include <patterns...> | Include file patterns (glob) |
-e, --exclude <patterns...> | Exclude file patterns (glob) |
-v, --verbose | Show verbose output |
-m, --mapping [path] | Generate upload mapping file (default: .oss-uploader-mapping.json) |
--no-mapping | Do not generate upload mapping file |
-h, --content-hash | Add content hash to filename (default: true) |
--no-content-hash | Do not add content hash to filename |
# Upload single file
oss-uploader upload ./image.png
# Upload multiple files (batch upload)
oss-uploader upload ./file1.js ./file2.css ./image.png
# Upload multiple files to specific directory
oss-uploader upload ./image1.png ./image2.jpg ./logo.svg -t images/2024/
# Upload to specific directory
oss-uploader upload ./image.png -t images/2024/
# Upload directory with patterns
oss-uploader upload ./dist -i "**/*.js" "**/*.css"
# Exclude files
oss-uploader upload ./dist -e "**/*.map" "**/test/**"
# Verbose mode
oss-uploader upload ./dist -v
# Generate custom mapping file
oss-uploader upload ./dist -m ./upload-map.json
# Don't generate mapping file
oss-uploader upload ./dist --no-mapping
# Upload with content hash (default behavior)
oss-uploader upload ./dist
# Result: file.js → file.a1b2c3d4.js
# Upload without content hash
oss-uploader upload ./dist --no-content-hash
# Result: file.js → file.js
# Mix files and directories (batch upload)
oss-uploader upload ./src/file1.js ./src/file2.css ./assets
The tool displays real-time progress during uploads with two modes:
For batch uploads, a beautiful progress bar is displayed showing:
Upload Progress |████████████████████░░░░░░| 75% | 15/20 Files | src/components/Button.tsx
Use -v or --verbose option to see detailed upload information for each file:
oss-uploader upload ./dist -v
Sample output:
✓ Uploaded: src/index.js → static/index.js (24.5 KB)
✓ Uploaded: src/styles.css → static/styles.css (12.3 KB)
...
By default, the uploader adds an 8-character content hash to filenames (similar to webpack's chunkhash), providing cache-busting capabilities for your assets.
The tool generates an MD5 hash from the file content and appends the first 8 characters before the file extension:
Original: app.js
Uploaded: app.a1b2c3d4.js
Original: style.min.css
Uploaded: style.min.e5f6g7h8.css
# Default: Content hash enabled
oss-uploader upload ./dist
# app.js → app.a1b2c3d4.js
# Disable content hash
oss-uploader upload ./dist --no-content-hash
# app.js → app.js
# With programmatic API
import { OSSUploader } from '@atomfe/oss-uploader';
const uploader = new OSSUploader(config);
// With content hash (default)
await uploader.upload({
source: './dist',
target: 'static/',
contentHash: true // default
});
// Without content hash
await uploader.upload({
source: './dist',
target: 'static/',
contentHash: false
});
After each upload, the tool automatically generates a .oss-uploader-mapping.json file in the current directory with detailed information about all uploaded files:
{
"uploadTime": "2025-10-18T10:30:00.000Z",
"bucket": "my-bucket",
"region": "YOUR_REGION",
"totalFiles": 10,
"totalSize": 1024000,
"files": [
{
"localPath": "/path/to/local/file.js",
"remotePath": "static/file.js",
"url": "https://my-bucket.YOUR_REGION.aliyuncs.com/static/file.js",
"size": 1024,
"uploadTime": "2025-10-18T10:30:00.000Z"
}
]
}
The tool supports multiple configuration sources:
Priority Order: Config file first, fallback to Environment variables
Note: If a config file exists, it will be used exclusively. Environment variables are only used when no config file is found.
Config Files (searched in order):
.ossrc / .ossrc.json.ossrc.yaml / .ossrc.ymloss.config.js / oss.config.jsonoss field in package.jsonEnvironment Variables:
OSS_REGIONOSS_ACCESS_KEY_IDOSS_ACCESS_KEY_SECRETOSS_BUCKETOSS_ENDPOINT (optional)OSS_INTERNAL (optional, true/false)OSS_SECURE (optional, true/false)OSS_TIMEOUT (optional, in milliseconds)| Field | Required | Description |
|---|---|---|
region | ✅ | OSS region (e.g., oss-cn-hangzhou) |
accessKeyId | ✅ | AccessKey ID |
accessKeySecret | ✅ | AccessKey Secret |
bucket | ✅ | Bucket name |
endpoint | ❌ | Custom endpoint |
internal | ❌ | Use internal network |
secure | ❌ | Use HTTPS (default: true) |
timeout | ❌ | Timeout in ms (default: 60000) |
.ossrc.json{
"region": "YOUR_REGION",
"accessKeyId": "YOUR_ACCESS_KEY_ID",
"accessKeySecret": "YOUR_ACCESS_KEY_SECRET",
"bucket": "my-bucket"
}
oss.config.jsGenerate JavaScript config with oss-uploader init -o oss.config.js
ESM format (with fallback values):
export default {
region: process.env.OSS_REGION || 'YOUR_REGION',
accessKeyId: process.env.OSS_ACCESS_KEY_ID || 'YOUR_ACCESS_KEY_ID',
accessKeySecret: process.env.OSS_ACCESS_KEY_SECRET || 'YOUR_ACCESS_KEY_SECRET',
bucket: process.env.OSS_BUCKET || 'YOUR_BUCKET_NAME',
// Optional fields
// endpoint: process.env.OSS_ENDPOINT,
// internal: process.env.OSS_INTERNAL === 'true',
secure: true,
timeout: 60000,
};
CommonJS format:
module.exports = {
region: process.env.OSS_REGION || 'YOUR_REGION',
accessKeyId: process.env.OSS_ACCESS_KEY_ID || 'YOUR_ACCESS_KEY_ID',
accessKeySecret: process.env.OSS_ACCESS_KEY_SECRET || 'YOUR_ACCESS_KEY_SECRET',
bucket: process.env.OSS_BUCKET || 'YOUR_BUCKET_NAME',
secure: true,
timeout: 60000,
};
# Set environment variables
export OSS_REGION="YOUR_REGION"
export OSS_ACCESS_KEY_ID="your-access-key-id"
export OSS_ACCESS_KEY_SECRET="your-access-key-secret"
export OSS_BUCKET="my-bucket"
# Optional environment variables
export OSS_SECURE="true"
export OSS_TIMEOUT="60000"
# Now you can use the CLI without a config file
oss-uploader upload ./dist -t static/
# Note: If a config file exists, it will be used instead of environment variables
import { OSSUploader, loadConfig } from 'oss-uploader';
const config = await loadConfig();
const uploader = new OSSUploader(config);
const results = await uploader.upload({
source: './dist',
target: 'static/',
recursive: true,
overwrite: true,
verbose: true,
generateMapping: true,
});
console.log('Upload results:', results);
const { OSSUploader, loadConfig } = require('oss-uploader');
(async () => {
const config = await loadConfig();
const uploader = new OSSUploader(config);
const results = await uploader.upload({
source: './dist',
target: 'static/',
recursive: true,
overwrite: true,
verbose: true,
generateMapping: true,
});
console.log('Upload results:', results);
})();
npm run build
oss-uploader upload ./dist -t static/my-app/
# GitHub Actions - Using environment variables (recommended)
- name: Upload to OSS
env:
OSS_REGION: ${{ secrets.OSS_REGION }}
OSS_ACCESS_KEY_ID: ${{ secrets.OSS_ACCESS_KEY_ID }}
OSS_ACCESS_KEY_SECRET: ${{ secrets.OSS_ACCESS_KEY_SECRET }}
OSS_BUCKET: ${{ secrets.OSS_BUCKET }}
run: |
npm install -g @atomfe/oss-uploader
oss-uploader upload ./dist -t static/
# Alternative: Using config file
- name: Upload to OSS
run: |
npm install -g @atomfe/oss-uploader
echo '{"region":"${{ secrets.OSS_REGION }}","accessKeyId":"${{ secrets.OSS_ACCESS_KEY_ID }}","accessKeySecret":"${{ secrets.OSS_ACCESS_KEY_SECRET }}","bucket":"${{ secrets.OSS_BUCKET }}"}' > .ossrc.json
oss-uploader upload ./dist -t static/
{
"scripts": {
"deploy": "npm run build && oss-uploader upload ./dist -t static/"
}
}
// Read mapping file
import mapping from './.oss-uploader-mapping.json' assert { type: 'json' };
// Get all uploaded URLs
const urls = mapping.files.map(f => f.url);
// Update resource references in HTML
const updateHTML = html => {
mapping.files.forEach(file => {
html = html.replace(
new RegExp(file.localPath, 'g'),
file.url
);
});
return html;
};
.ossrc.json to .gitignoreContributions are welcome! Please feel free to submit a Pull Request.
For bug reports or feature requests, please create an issue.
# Install dependencies
pnpm install
# Development mode
pnpm run dev
# Build
pnpm run build
# Test
pnpm run test
pnpm run test:coverage
# Lint & Format
pnpm run lint
pnpm run format
See CHANGELOG.md for version history.
MIT © 2025
export OSS_ACCESS_KEY_ID="your-key"
export OSS_ACCESS_KEY_SECRET="your-secret"
export OSS_BUCKET="your-bucket"
export OSS_REGION="YOUR_REGION"
# Merge multiple mapping files
cat .oss-uploader-mapping-*.json | jq -s 'map(.files) | add' > all-uploads.json
#!/bin/bash
# deploy.sh
# Build project
npm run build
# Upload to OSS
oss-uploader upload ./dist -t "static/v$(date +%Y%m%d)/" -v
# Read mapping file and send notification
node -e "
const mapping = require('./.oss-uploader-mapping.json');
console.log(\`✅ Upload complete! Total \${mapping.totalFiles} files\`);
console.log(\`📦 Total size: \${(mapping.totalSize / 1024 / 1024).toFixed(2)} MB\`);
"
Made with ❤️ by lorainwings
FAQs
A powerful OSS uploader for uploading files to Aliyun OSS
We found that @atomfe/oss-uploader demonstrated a healthy version release cadence and project activity because the last version was released less than a year ago. It has 1 open source maintainer collaborating on the project.
Did you know?

Socket for GitHub automatically highlights issues in each pull request and monitors the health of all your open source dependencies. Discover the contents of your packages and block harmful activity before you install or update your dependencies.

Security News
Socket CEO Feross Aboukhadijeh joins 10 Minutes or Less, a podcast by Ali Rohde, to discuss the recent surge in open source supply chain attacks.

Research
/Security News
Campaign of 108 extensions harvests identities, steals sessions, and adds backdoors to browsers, all tied to the same C2 infrastructure.

Security News
OpenAI rotated macOS signing certificates after a malicious Axios package reached its CI pipeline in a broader software supply chain attack.