marriedtermiteblyi commited on
Commit
8147070
·
verified ·
1 Parent(s): 67b1438

Update server.js

Browse files
Files changed (1) hide show
  1. server.js +25 -34
server.js CHANGED
@@ -3,69 +3,68 @@
3
  import express from 'express';
4
  import cors from 'cors';
5
  import multer from 'multer';
6
- import { commit } from '@huggingface/hub'; // Use 'commit' for batch operations
7
  import path from 'path';
8
  import { fileURLToPath } from 'url';
9
 
10
- // Fix __dirname for ES Modules
11
  const __filename = fileURLToPath(import.meta.url);
12
  const __dirname = path.dirname(__filename);
13
 
14
  const app = express();
15
- // Hugging Face Spaces requires port 7860
16
  const port = process.env.PORT || 3001;
17
 
18
- // Middleware
19
  app.use(cors());
20
- app.use(express.json());
 
 
21
 
22
- // Configure Multer for memory storage
23
- // No limit on file count here, but we limit payload size via express/nginx usually
24
  const storage = multer.memoryStorage();
25
- const upload = multer({ storage: storage });
 
 
 
 
 
 
26
 
27
- // SERVER CONFIGURATION
28
  const SERVER_CONFIG = {
29
  TOKEN: process.env.HF_TOKEN || '',
30
  REPO: process.env.HF_REPO || 'TwanAPI/DataTwan',
31
  TYPE: 'dataset'
32
  };
33
 
34
- // --- API ROUTES ---
35
-
36
- // Batch Upload Endpoint
37
- // Accepts multiple files in the 'files' field
38
  app.post('/api/upload', upload.array('files'), async (req, res) => {
39
  try {
40
  const files = req.files;
41
- // req.body.paths can be a string (if 1 file) or array (if multiple)
42
- // We normalize it to an array
43
- const paths = [].concat(req.body.paths || []);
 
 
 
44
 
45
  if (!files || files.length === 0) {
46
  return res.status(400).json({ error: 'No files provided' });
47
  }
48
 
49
  if (files.length !== paths.length) {
50
- return res.status(400).json({ error: 'Mismatch between file count and path count' });
51
  }
52
 
53
- // Security Check
54
  if (!SERVER_CONFIG.TOKEN) {
55
- console.error('[SERVER] Upload Failed: HF_TOKEN missing');
56
  return res.status(500).json({ error: 'Server misconfiguration: HF_TOKEN secret is missing.' });
57
  }
58
 
59
  console.log(`[SERVER] Processing batch of ${files.length} files...`);
60
 
61
- // Prepare operations for Hugging Face 'commit'
62
  const operations = files.map((file, index) => ({
63
  operation: 'addOrUpdate',
64
  path: paths[index],
65
  content: new Blob([file.buffer])
66
  }));
67
 
68
- // Execute single commit for all files
69
  const response = await commit({
70
  credentials: {
71
  accessToken: SERVER_CONFIG.TOKEN,
@@ -75,16 +74,14 @@ app.post('/api/upload', upload.array('files'), async (req, res) => {
75
  name: SERVER_CONFIG.REPO
76
  },
77
  operations: operations,
78
- title: `Upload batch of ${files.length} files via DataTwan`
79
  });
80
 
81
- const commitHash = response.oid; // 'commit' returns { oid: string, ... }
82
  const urlPrefix = "https://huggingface.co/datasets";
83
-
84
- // Generate public URLs for response
85
  const urls = paths.map(p => `${urlPrefix}/${SERVER_CONFIG.REPO}/blob/${commitHash}/${p}`);
86
 
87
- console.log(`[SERVER] Batch Success: ${files.length} files committed (Hash: ${commitHash})`);
88
 
89
  res.json({
90
  success: true,
@@ -93,7 +90,7 @@ app.post('/api/upload', upload.array('files'), async (req, res) => {
93
  });
94
 
95
  } catch (error) {
96
- console.error('[SERVER] Batch Upload Error:', error);
97
  res.status(500).json({
98
  success: false,
99
  error: error.message || 'Internal Server Error'
@@ -101,18 +98,12 @@ app.post('/api/upload', upload.array('files'), async (req, res) => {
101
  }
102
  });
103
 
104
- // --- SERVE FRONTEND (Production) ---
105
-
106
  app.use(express.static(path.join(__dirname, 'dist')));
107
 
108
  app.get('*', (req, res) => {
109
  res.sendFile(path.join(__dirname, 'dist', 'index.html'));
110
  });
111
 
112
- // Start Server
113
  app.listen(port, () => {
114
- console.log(`--------------------------------------------------`);
115
- console.log(`✅ Server running on port ${port}`);
116
- console.log(` Target Repo: ${SERVER_CONFIG.REPO}`);
117
- console.log(`--------------------------------------------------`);
118
  });
 
3
  import express from 'express';
4
  import cors from 'cors';
5
  import multer from 'multer';
6
+ import { commit } from '@huggingface/hub';
7
  import path from 'path';
8
  import { fileURLToPath } from 'url';
9
 
 
10
  const __filename = fileURLToPath(import.meta.url);
11
  const __dirname = path.dirname(__filename);
12
 
13
  const app = express();
 
14
  const port = process.env.PORT || 3001;
15
 
 
16
  app.use(cors());
17
+ // Increase body limit for large batch JSON/Form data
18
+ app.use(express.json({ limit: '500mb' }));
19
+ app.use(express.urlencoded({ limit: '500mb', extended: true }));
20
 
21
+ // Configure Multer with higher limits
 
22
  const storage = multer.memoryStorage();
23
+ const upload = multer({
24
+ storage: storage,
25
+ limits: {
26
+ fileSize: 500 * 1024 * 1024, // 500MB per file max
27
+ fieldSize: 500 * 1024 * 1024, // 500MB per field
28
+ }
29
+ });
30
 
 
31
  const SERVER_CONFIG = {
32
  TOKEN: process.env.HF_TOKEN || '',
33
  REPO: process.env.HF_REPO || 'TwanAPI/DataTwan',
34
  TYPE: 'dataset'
35
  };
36
 
 
 
 
 
37
  app.post('/api/upload', upload.array('files'), async (req, res) => {
38
  try {
39
  const files = req.files;
40
+ let paths = req.body.paths;
41
+
42
+ // Normalize paths to array if it's a single string
43
+ if (!Array.isArray(paths)) {
44
+ paths = [paths].filter(Boolean);
45
+ }
46
 
47
  if (!files || files.length === 0) {
48
  return res.status(400).json({ error: 'No files provided' });
49
  }
50
 
51
  if (files.length !== paths.length) {
52
+ return res.status(400).json({ error: `Mismatch: ${files.length} files vs ${paths.length} paths` });
53
  }
54
 
 
55
  if (!SERVER_CONFIG.TOKEN) {
 
56
  return res.status(500).json({ error: 'Server misconfiguration: HF_TOKEN secret is missing.' });
57
  }
58
 
59
  console.log(`[SERVER] Processing batch of ${files.length} files...`);
60
 
 
61
  const operations = files.map((file, index) => ({
62
  operation: 'addOrUpdate',
63
  path: paths[index],
64
  content: new Blob([file.buffer])
65
  }));
66
 
67
+ // Using commit is atomic and faster for datasets than individual LFS uploads for small-medium files
68
  const response = await commit({
69
  credentials: {
70
  accessToken: SERVER_CONFIG.TOKEN,
 
74
  name: SERVER_CONFIG.REPO
75
  },
76
  operations: operations,
77
+ title: `Batch upload of ${files.length} files`
78
  });
79
 
80
+ const commitHash = response.oid;
81
  const urlPrefix = "https://huggingface.co/datasets";
 
 
82
  const urls = paths.map(p => `${urlPrefix}/${SERVER_CONFIG.REPO}/blob/${commitHash}/${p}`);
83
 
84
+ console.log(`[SERVER] Batch Committed: ${commitHash}`);
85
 
86
  res.json({
87
  success: true,
 
90
  });
91
 
92
  } catch (error) {
93
+ console.error('[SERVER] Error:', error);
94
  res.status(500).json({
95
  success: false,
96
  error: error.message || 'Internal Server Error'
 
98
  }
99
  });
100
 
 
 
101
  app.use(express.static(path.join(__dirname, 'dist')));
102
 
103
  app.get('*', (req, res) => {
104
  res.sendFile(path.join(__dirname, 'dist', 'index.html'));
105
  });
106
 
 
107
  app.listen(port, () => {
108
+ console.log(`✅ Server running on port ${port} | Repo: ${SERVER_CONFIG.REPO}`);
 
 
 
109
  });