CatPtain commited on
Commit
1ba8490
·
verified ·
1 Parent(s): cfddb81

Upload 8 files

Browse files
Files changed (5) hide show
  1. Dockerfile +2 -1
  2. LICENSE +44 -18
  3. README.md +130 -61
  4. package.json +4 -4
  5. server.js +32 -9
Dockerfile CHANGED
@@ -44,7 +44,8 @@ COPY package*.json ./
44
 
45
  # 清理 npm cache 并安装依赖
46
  RUN npm cache clean --force \
47
- && npm ci --omit=dev --no-audit --no-fund \
 
48
  && npm cache clean --force
49
 
50
  # 复制应用代码
 
44
 
45
  # 清理 npm cache 并安装依赖
46
  RUN npm cache clean --force \
47
+ # && npm ci --omit=dev --no-audit --no-fund \
48
+ && npm install --only=production --no-audit --no-fund \
49
  && npm cache clean --force
50
 
51
  # 复制应用代码
LICENSE CHANGED
@@ -1,27 +1,53 @@
1
- PROPRIETARY SOFTWARE LICENSE
2
 
3
  Copyright (c) 2024. All rights reserved.
4
 
5
- NOTICE: This software and its documentation are proprietary and confidential
6
- information. This software is provided under a proprietary license agreement.
7
 
8
- RESTRICTIONS:
9
- - You may NOT copy, modify, or distribute this software
10
- - You may NOT reverse engineer or decompile this software
11
- - You may NOT use this software for commercial purposes without a license
12
- - You may NOT redistribute or sublicense this software
 
 
 
13
 
14
- PERMITTED USES:
15
- - Personal, non-commercial use only
16
- - Educational purposes with proper attribution
17
- - Evaluation for potential commercial licensing
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
18
 
19
  COMMERCIAL LICENSING:
20
- Commercial use requires a separate license agreement. Contact the developer
21
- for commercial licensing terms and pricing.
 
 
 
22
 
23
- DISCLAIMER:
24
- This software is provided "AS IS" without warranty of any kind. The author
25
- shall not be liable for any damages arising from the use of this software.
26
 
27
- For licensing inquiries: [Contact Information]
 
1
+ PROPRIETARY NON-COMMERCIAL LICENSE
2
 
3
  Copyright (c) 2024. All rights reserved.
4
 
5
+ NOTICE: This software and its documentation are proprietary and confidential.
6
+ This is NOT open source software and is subject to strict usage restrictions.
7
 
8
+ STRICT RESTRICTIONS:
9
+ - COMMERCIAL USE IS STRICTLY PROHIBITED
10
+ - You may NOT sell, rent, lease, or monetize this software in any way
11
+ - You may NOT use this software in any business or commercial environment
12
+ - You may NOT copy, modify, distribute, or redistribute this software
13
+ - You may NOT reverse engineer, decompile, or disassemble this software
14
+ - You may NOT sublicense or transfer rights to this software
15
+ - You may NOT remove or modify copyright notices
16
 
17
+ PERMITTED USES ONLY:
18
+ - Personal, non-commercial use for individual learning purposes
19
+ - Educational use in academic institutions for teaching purposes only
20
+ - Research and evaluation for non-commercial academic purposes
21
+ - Internal testing and development (non-commercial)
22
+
23
+ EDUCATIONAL USE REQUIREMENTS:
24
+ - Must include proper attribution to original author
25
+ - Cannot be used for any profit-generating activities
26
+ - Students/teachers cannot commercialize any derivatives
27
+ - Institution must be accredited educational organization
28
+
29
+ TERMINATION:
30
+ This license terminates automatically if you violate any terms.
31
+ Upon termination, you must destroy all copies of the software.
32
+
33
+ DISCLAIMER OF WARRANTY:
34
+ This software is provided "AS IS" without warranty of any kind, express or
35
+ implied. The author disclaims all warranties including merchantability and
36
+ fitness for a particular purpose.
37
+
38
+ LIMITATION OF LIABILITY:
39
+ The author shall not be liable for any damages whatsoever arising from the
40
+ use of this software, including but not limited to direct, indirect,
41
+ incidental, or consequential damages.
42
 
43
  COMMERCIAL LICENSING:
44
+ For any commercial use, you must obtain a separate commercial license.
45
+ Contact the developer for commercial licensing terms and pricing.
46
+
47
+ VIOLATION CONSEQUENCES:
48
+ Violation of this license may result in legal action and monetary damages.
49
 
50
+ By using this software, you acknowledge that you have read, understood,
51
+ and agree to be bound by the terms of this license.
 
52
 
53
+ For licensing inquiries or permission requests, contact the developer.
README.md CHANGED
@@ -5,12 +5,12 @@ colorFrom: blue
5
  colorTo: green
6
  sdk: docker
7
  pinned: false
8
- license: mit
9
  ---
10
 
11
  # 📸 Page Screenshot API
12
 
13
- Professional web page screenshot service built with Node.js and Puppeteer, optimized for Hugging Face Spaces.
14
 
15
  ## 🚀 Live Demo
16
 
@@ -18,84 +18,111 @@ Professional web page screenshot service built with Node.js and Puppeteer, optim
18
  - **Demo Interface**: `https://your-username-page-shot.hf.space/demo`
19
  - **Health Check**: `https://your-username-page-shot.hf.space/`
20
 
21
- ## 🔐 Access Control
22
 
23
- This API uses **Hugging Face system-level authentication**:
 
24
 
25
- ### Public Spaces
26
- - Open access for all users
27
- - Rate limited to 100 requests per 15 minutes
28
- - Perfect for demos and testing
29
-
30
- ### Private Spaces
31
- - Requires valid Hugging Face access token
32
- - Access controlled by HF platform automatically
33
- - Higher security for production use
34
 
35
- ## 📖 API Usage
 
36
 
37
- ### Public Space Access
38
  ```bash
 
39
  curl -X POST https://your-space.hf.space/screenshot \
40
  -H "Content-Type: application/json" \
41
  -d '{"url": "https://example.com", "width": 1280, "height": 720}' \
42
  --output screenshot.jpg
43
  ```
44
 
45
- ### Private Space Access
 
 
46
  ```bash
 
47
  curl -X POST https://your-space.hf.space/screenshot \
48
  -H "Content-Type: application/json" \
49
  -H "Authorization: Bearer hf_your_token_here" \
50
- -d '{"url": "https://example.com", "width": 1280, "height": 720}' \
51
  --output screenshot.jpg
52
  ```
53
 
54
- ### JavaScript Example
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
55
  ```javascript
56
- const response = await fetch('https://your-space.hf.space/screenshot', {
 
57
  method: 'POST',
58
  headers: {
59
  'Content-Type': 'application/json',
60
- // Add this line only for private spaces:
61
- // 'Authorization': 'Bearer hf_your_token_here'
62
  },
63
  body: JSON.stringify({
64
  url: 'https://example.com',
65
- width: 1280,
66
- height: 720,
67
- quality: 80
68
  })
69
  });
70
-
71
- const imageBlob = await response.blob();
72
  ```
73
 
74
- ## 📊 Parameters
 
75
 
76
- | Parameter | Type | Default | Range | Description |
77
- |-----------|------|---------|-------|-------------|
78
- | `url` | string | **required** | - | Target webpage URL |
79
- | `width` | number | 1280 | 100-1600 | Screenshot width in pixels |
80
- | `height` | number | 720 | 100-1200 | Screenshot height in pixels |
81
- | `quality` | number | 75 | 10-100 | JPEG quality percentage |
 
 
 
 
 
 
 
 
 
82
 
83
  ## 🔄 Response Examples
84
 
85
  ### Success Response
86
  ```
87
  HTTP/1.1 200 OK
88
- Content-Type: image/jpeg
89
  Content-Length: 245760
90
 
91
- [Binary JPEG data]
92
  ```
93
 
94
- ### Error Response
95
  ```json
96
  {
97
- "error": "Failed to capture screenshot",
98
- "message": "Navigation timeout exceeded"
 
99
  }
100
  ```
101
 
@@ -111,53 +138,95 @@ Content-Length: 245760
111
 
112
  ## 🛠️ Features
113
 
 
 
 
 
114
  - ✅ **Queue Management** - Handles concurrent requests efficiently
115
  - ✅ **CPU Monitoring** - Automatic load balancing
116
- - ✅ **Rate Limiting** - Prevents abuse
117
- - ✅ **HF Authentication** - Integrated with HuggingFace platform
118
  - ✅ **Error Handling** - Comprehensive error responses
119
- - ✅ **Demo Interface** - Built-in testing UI
120
  - ✅ **Health Monitoring** - Status endpoint for monitoring
121
 
122
- ## 📈 Monitoring
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
123
 
124
  ### Health Check
125
  ```bash
126
  curl https://your-space.hf.space/
 
127
  ```
128
 
129
  ### Server Status
130
  ```bash
131
  curl https://your-space.hf.space/status
 
132
  ```
133
 
134
- ## 🚨 Rate Limits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
135
 
136
- | Space Type | Requests | Window |
137
- |------------|----------|--------|
138
- | Public | 100 | 15 minutes |
139
- | Private | 100 | 15 minutes |
 
140
 
141
- ## 🔧 Deployment
142
 
143
- This application is optimized for Hugging Face Spaces with:
144
- - Docker-based deployment
145
- - Automatic dependency management
146
- - Resource-efficient Chrome configuration
147
- - Built-in security features
148
- - HuggingFace platform integration
149
 
150
- ## 🔒 Security Notes
151
 
152
- - **Private Spaces**: Access automatically controlled by HF platform
153
- - **Public Spaces**: Open access with rate limiting
154
- - **No API keys needed**: Authentication handled by HuggingFace
155
- - **Secure by design**: Follows HF Spaces best practices
156
 
157
  ## 📄 License
158
 
159
- Proprietary - Commercial use requires license. See [LICENSE](LICENSE) for details.
 
 
 
160
 
161
  ## 🤝 Support
162
 
163
- For technical support or questions, please contact the administrator.
 
5
  colorTo: green
6
  sdk: docker
7
  pinned: false
8
+ license: other
9
  ---
10
 
11
  # 📸 Page Screenshot API
12
 
13
+ Professional web page screenshot service built with Node.js and Puppeteer, optimized for Hugging Face Spaces with **full-page support** and **flexible authentication**.
14
 
15
  ## 🚀 Live Demo
16
 
 
18
  - **Demo Interface**: `https://your-username-page-shot.hf.space/demo`
19
  - **Health Check**: `https://your-username-page-shot.hf.space/`
20
 
21
+ ## 🔐 Authentication Options
22
 
23
+ ### Option 1: Custom API Key (Recommended)
24
+ Set `API_KEY` environment variable in Space settings for secure access:
25
 
26
+ ```bash
27
+ # With API key authentication
28
+ curl -X POST https://your-space.hf.space/screenshot \
29
+ -H "Content-Type: application/json" \
30
+ -H "Authorization: Bearer your-api-key-here" \
31
+ -d '{"url": "https://example.com", "fullPage": true}' \
32
+ --output screenshot.jpg
33
+ ```
 
34
 
35
+ ### Option 2: Open Access Mode
36
+ If no `API_KEY` is set, the API runs in open access mode:
37
 
 
38
  ```bash
39
+ # Open access (no authentication)
40
  curl -X POST https://your-space.hf.space/screenshot \
41
  -H "Content-Type: application/json" \
42
  -d '{"url": "https://example.com", "width": 1280, "height": 720}' \
43
  --output screenshot.jpg
44
  ```
45
 
46
+ ### Option 3: Private Space with HF Token
47
+ For private spaces, use HuggingFace access token:
48
+
49
  ```bash
50
+ # Private space access
51
  curl -X POST https://your-space.hf.space/screenshot \
52
  -H "Content-Type: application/json" \
53
  -H "Authorization: Bearer hf_your_token_here" \
54
+ -d '{"url": "https://example.com"}' \
55
  --output screenshot.jpg
56
  ```
57
 
58
+ ## 📊 API Parameters
59
+
60
+ | Parameter | Type | Default | Range | Description |
61
+ |-----------|------|---------|-------|-------------|
62
+ | `url` | string | **required** | - | Target webpage URL (must start with http/https) |
63
+ | `width` | number | 1280 | 100-1600 | Screenshot width in pixels |
64
+ | `height` | number | 720 | 100-1200 | Screenshot height in pixels |
65
+ | `quality` | number | 75 | 10-100 | JPEG quality percentage (JPEG only) |
66
+ | `fullPage` | boolean | false | - | **NEW**: Capture full page length (long screenshots) |
67
+ | `format` | string | "jpeg" | jpeg/png | **NEW**: Output format (jpeg or png) |
68
+
69
+ ## 🆕 New Features in v1.5.0
70
+
71
+ ### 📜 Full Page Screenshots
72
+ Capture entire webpage including content below the fold:
73
+
74
  ```javascript
75
+ // Capture full page length
76
+ const response = await fetch('/screenshot', {
77
  method: 'POST',
78
  headers: {
79
  'Content-Type': 'application/json',
80
+ 'Authorization': 'Bearer your-api-key'
 
81
  },
82
  body: JSON.stringify({
83
  url: 'https://example.com',
84
+ fullPage: true, // 🆕 Captures entire page height
85
+ format: 'png' // 🆕 PNG format for better quality
 
86
  })
87
  });
 
 
88
  ```
89
 
90
+ ### 🖼️ Multiple Image Formats
91
+ Choose between JPEG (smaller size) and PNG (better quality):
92
 
93
+ ```bash
94
+ # PNG format (lossless, larger file)
95
+ curl -X POST https://your-space.hf.space/screenshot \
96
+ -H "Content-Type: application/json" \
97
+ -H "Authorization: Bearer your-api-key" \
98
+ -d '{"url": "https://example.com", "format": "png"}' \
99
+ --output screenshot.png
100
+
101
+ # JPEG format (compressed, smaller file)
102
+ curl -X POST https://your-space.hf.space/screenshot \
103
+ -H "Content-Type: application/json" \
104
+ -H "Authorization: Bearer your-api-key" \
105
+ -d '{"url": "https://example.com", "format": "jpeg", "quality": 85}' \
106
+ --output screenshot.jpg
107
+ ```
108
 
109
  ## 🔄 Response Examples
110
 
111
  ### Success Response
112
  ```
113
  HTTP/1.1 200 OK
114
+ Content-Type: image/jpeg # or image/png
115
  Content-Length: 245760
116
 
117
+ [Binary image data]
118
  ```
119
 
120
+ ### Authentication Error
121
  ```json
122
  {
123
+ "error": "Unauthorized",
124
+ "message": "Valid API key required. Please provide API key in Authorization header or x-api-key header.",
125
+ "hint": "Use \"Authorization: Bearer YOUR_API_KEY\" or \"x-api-key: YOUR_API_KEY\""
126
  }
127
  ```
128
 
 
138
 
139
  ## 🛠️ Features
140
 
141
+ - ✅ **Full Page Screenshots** - Capture entire webpage length
142
+ - ✅ **Multiple Formats** - JPEG (compressed) and PNG (lossless) support
143
+ - ✅ **Flexible Authentication** - API key, open access, or HF token
144
+ - ✅ **Global Font Support** - Renders CJK, Arabic, Emoji fonts correctly
145
  - ✅ **Queue Management** - Handles concurrent requests efficiently
146
  - ✅ **CPU Monitoring** - Automatic load balancing
147
+ - ✅ **Rate Limiting** - Prevents abuse (100 req/15min)
 
148
  - ✅ **Error Handling** - Comprehensive error responses
149
+ - ✅ **Demo Interface** - Built-in testing UI with auth detection
150
  - ✅ **Health Monitoring** - Status endpoint for monitoring
151
 
152
+ ## 🔧 Setup Instructions
153
+
154
+ ### Step 1: Configure Authentication (Optional)
155
+ ```bash
156
+ # In HuggingFace Space Settings → Variables
157
+ API_KEY=sk-your-secure-random-key-here
158
+ ```
159
+
160
+ ### Step 2: Deploy to HuggingFace Spaces
161
+ 1. Create new Space with Docker SDK
162
+ 2. Upload all files to Space repository
163
+ 3. Set environment variables if needed
164
+ 4. Space will auto-deploy
165
+
166
+ ### Step 3: Test the API
167
+ Visit the demo page: `https://your-space.hf.space/demo`
168
+
169
+ ## 📈 Monitoring Endpoints
170
 
171
  ### Health Check
172
  ```bash
173
  curl https://your-space.hf.space/
174
+ # Returns API info and authentication status
175
  ```
176
 
177
  ### Server Status
178
  ```bash
179
  curl https://your-space.hf.space/status
180
+ # Returns CPU usage, active requests, queue status
181
  ```
182
 
183
+ ## 🚨 Rate Limits & Performance
184
+
185
+ | Metric | Limit | Notes |
186
+ |--------|-------|-------|
187
+ | Requests | 100/15min | Per IP address |
188
+ | Concurrent | 3 requests | Server queue management |
189
+ | CPU Threshold | 95% | Auto-rejects when overloaded |
190
+ | Timeout | 15 seconds | Per screenshot request |
191
+ | Max Dimensions | 1600x1200 | Viewport size limits |
192
+
193
+ ## 🔒 Security & License
194
+
195
+ - **Proprietary License**: Commercial use requires separate license
196
+ - **Non-Commercial Use**: Educational and personal use permitted
197
+ - **API Security**: Optional API key authentication
198
+ - **Resource Protection**: Built-in rate limiting and queue management
199
+
200
+ ## 🌍 Global Font Support
201
 
202
+ Optimized for international websites with support for:
203
+ - **CJK Languages**: Chinese, Japanese, Korean
204
+ - **RTL Languages**: Arabic, Hebrew
205
+ - **Emoji & Symbols**: Full Unicode emoji support
206
+ - **Latin Scripts**: European languages with proper rendering
207
 
208
+ ## 🛡️ Production Recommendations
209
 
210
+ 1. **Enable API Key**: Set `API_KEY` environment variable for production
211
+ 2. **Use Private Space**: For sensitive or commercial use
212
+ 3. **Implement Retry Logic**: Handle busy server responses
213
+ 4. **Monitor Usage**: Use `/status` endpoint for health checks
214
+ 5. **Choose Format Wisely**: JPEG for photos, PNG for graphics/text
 
215
 
216
+ ## 📚 Documentation
217
 
218
+ - [API Authentication Guide](API_GUIDE.md)
219
+ - [Private Space Setup](PRIVATE_SPACE_GUIDE.md)
220
+ - [Environment Variables](HF_SPACES_ENV_GUIDE.md)
221
+ - [Deployment Guide](DEPLOYMENT_GUIDE.md)
222
 
223
  ## 📄 License
224
 
225
+ **Proprietary Non-Commercial License** - See [LICENSE](LICENSE) for full terms.
226
+ - ✅ Educational and personal use
227
+ - ❌ Commercial use without license
228
+ - ❌ Redistribution or modification
229
 
230
  ## 🤝 Support
231
 
232
+ For commercial licensing, technical support, or feature requests, please contact the administrator.
package.json CHANGED
@@ -1,16 +1,16 @@
1
  {
2
  "name": "page-screenshot-api",
3
- "version": "1.4.0",
4
- "description": "Professional web page screenshot API service for Hugging Face Spaces",
5
  "main": "server.js",
6
  "scripts": {
7
  "start": "node server.js",
8
  "dev": "nodemon server.js",
9
  "build": "echo 'No build step required'"
10
  },
11
- "keywords": ["screenshot", "api", "puppeteer", "huggingface", "spaces"],
12
  "author": "",
13
- "license": "UNLICENSED",
14
  "private": true,
15
  "dependencies": {
16
  "express": "^4.18.2",
 
1
  {
2
  "name": "page-screenshot-api",
3
+ "version": "1.5.0",
4
+ "description": "Professional web page screenshot API service for Hugging Face Spaces with full-page support",
5
  "main": "server.js",
6
  "scripts": {
7
  "start": "node server.js",
8
  "dev": "nodemon server.js",
9
  "build": "echo 'No build step required'"
10
  },
11
+ "keywords": ["screenshot", "api", "puppeteer", "huggingface", "spaces", "fullpage"],
12
  "author": "",
13
+ "license": "SEE LICENSE IN LICENSE",
14
  "private": true,
15
  "dependencies": {
16
  "express": "^4.18.2",
server.js CHANGED
@@ -171,6 +171,13 @@ app.get('/demo', (req, res) => {
171
  <input type="number" id="height" value="720" min="100" max="1200">
172
  <label>Quality:</label>
173
  <input type="number" id="quality" value="75" min="10" max="100">
 
 
 
 
 
 
 
174
  </div>
175
 
176
  <button onclick="takeScreenshot()">📸 Take Screenshot</button>
@@ -195,6 +202,8 @@ app.get('/demo', (req, res) => {
195
  const width = parseInt(document.getElementById('width').value);
196
  const height = parseInt(document.getElementById('height').value);
197
  const quality = parseInt(document.getElementById('quality').value);
 
 
198
  const apiKey = document.getElementById('apiKey') ? document.getElementById('apiKey').value : '';
199
 
200
  if (!url) {
@@ -225,7 +234,7 @@ app.get('/demo', (req, res) => {
225
  const response = await fetch('/screenshot', {
226
  method: 'POST',
227
  headers: headers,
228
- body: JSON.stringify({ url, width, height, quality })
229
  });
230
 
231
  if (response.ok) {
@@ -237,7 +246,7 @@ app.get('/demo', (req, res) => {
237
  '<h3 class="success">✅ Screenshot Success!</h3>' +
238
  '<p>Size: ' + size + ' KB | Dimensions: ' + width + 'x' + height + '</p>' +
239
  '<img src="' + imageUrl + '" alt="Screenshot"><br><br>' +
240
- '<a href="' + imageUrl + '" download="screenshot.jpg">💾 Download Image</a>';
241
  } else {
242
  const error = await response.json();
243
  document.getElementById('result').innerHTML =
@@ -256,7 +265,7 @@ app.get('/demo', (req, res) => {
256
 
257
  // 截图端点
258
  app.post('/screenshot', authenticate, async (req, res) => {
259
- const { url, width = 1280, height = 720, quality = 75 } = req.body;
260
 
261
  // 验证参数
262
  if (!url) {
@@ -267,6 +276,11 @@ app.post('/screenshot', authenticate, async (req, res) => {
267
  return res.status(400).json({ error: 'URL must start with http:// or https://' });
268
  }
269
 
 
 
 
 
 
270
  const cpuUsage = getCpuUsage();
271
  if (cpuUsage > 95) {
272
  return res.status(503).json({
@@ -339,13 +353,22 @@ app.post('/screenshot', authenticate, async (req, res) => {
339
  timeout: 15000
340
  });
341
 
342
- const screenshot = await page.screenshot({
343
- type: 'jpeg',
344
- quality: parseInt(quality),
345
- fullPage: false
346
- });
 
 
 
 
 
 
 
347
 
348
- res.set('Content-Type', 'image/jpeg');
 
 
349
  res.send(screenshot);
350
 
351
  } catch (error) {
 
171
  <input type="number" id="height" value="720" min="100" max="1200">
172
  <label>Quality:</label>
173
  <input type="number" id="quality" value="75" min="10" max="100">
174
+ <label>Full Page:</label>
175
+ <input type="checkbox" id="fullPage">
176
+ <label>Format:</label>
177
+ <select id="format">
178
+ <option value="jpeg" selected>JPEG</option>
179
+ <option value="png">PNG</option>
180
+ </select>
181
  </div>
182
 
183
  <button onclick="takeScreenshot()">📸 Take Screenshot</button>
 
202
  const width = parseInt(document.getElementById('width').value);
203
  const height = parseInt(document.getElementById('height').value);
204
  const quality = parseInt(document.getElementById('quality').value);
205
+ const fullPage = document.getElementById('fullPage').checked;
206
+ const format = document.getElementById('format').value;
207
  const apiKey = document.getElementById('apiKey') ? document.getElementById('apiKey').value : '';
208
 
209
  if (!url) {
 
234
  const response = await fetch('/screenshot', {
235
  method: 'POST',
236
  headers: headers,
237
+ body: JSON.stringify({ url, width, height, quality, fullPage, format })
238
  });
239
 
240
  if (response.ok) {
 
246
  '<h3 class="success">✅ Screenshot Success!</h3>' +
247
  '<p>Size: ' + size + ' KB | Dimensions: ' + width + 'x' + height + '</p>' +
248
  '<img src="' + imageUrl + '" alt="Screenshot"><br><br>' +
249
+ '<a href="' + imageUrl + '" download="screenshot.' + format + '">💾 Download Image</a>';
250
  } else {
251
  const error = await response.json();
252
  document.getElementById('result').innerHTML =
 
265
 
266
  // 截图端点
267
  app.post('/screenshot', authenticate, async (req, res) => {
268
+ const { url, width = 1280, height = 720, quality = 75, fullPage = false, format = 'jpeg' } = req.body;
269
 
270
  // 验证参数
271
  if (!url) {
 
276
  return res.status(400).json({ error: 'URL must start with http:// or https://' });
277
  }
278
 
279
+ // 验证图片格式
280
+ if (!['jpeg', 'png'].includes(format.toLowerCase())) {
281
+ return res.status(400).json({ error: 'Format must be either "jpeg" or "png"' });
282
+ }
283
+
284
  const cpuUsage = getCpuUsage();
285
  if (cpuUsage > 95) {
286
  return res.status(503).json({
 
353
  timeout: 15000
354
  });
355
 
356
+ // 配置截图选项
357
+ const screenshotOptions = {
358
+ type: format.toLowerCase(),
359
+ fullPage: Boolean(fullPage)
360
+ };
361
+
362
+ // 只有 JPEG 格式才支持 quality 参数
363
+ if (format.toLowerCase() === 'jpeg') {
364
+ screenshotOptions.quality = parseInt(quality);
365
+ }
366
+
367
+ const screenshot = await page.screenshot(screenshotOptions);
368
 
369
+ // 设置正确的 Content-Type
370
+ const mimeType = format.toLowerCase() === 'png' ? 'image/png' : 'image/jpeg';
371
+ res.set('Content-Type', mimeType);
372
  res.send(screenshot);
373
 
374
  } catch (error) {