Replace Upload class with PutObjectCommand for RustFS compatibility
The @aws-sdk/lib-storage Upload class internally uses CreateMultipartUploadCommand for files over the part size threshold, which returns non-standard XML from RustFS causing UnknownError. PutObjectCommand does a simple single PUT request that RustFS handles correctly. Fixed in both /api/upload and /api/link/:id/upload endpoints. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
parent
d5192e8847
commit
44c22bd95e
1 changed files with 13 additions and 14 deletions
27
server.js
27
server.js
|
|
@ -535,14 +535,14 @@ app.post("/api/upload", requireAuth, upload.array("files", 50), async (req, res)
|
||||||
const key = prefix ? `${prefix.replace(/[-\/]+$/, "")}--${file.originalname}` : file.originalname;
|
const key = prefix ? `${prefix.replace(/[-\/]+$/, "")}--${file.originalname}` : file.originalname;
|
||||||
const contentType = getMimeType(file.originalname, file.mimetype);
|
const contentType = getMimeType(file.originalname, file.mimetype);
|
||||||
console.log(`Uploading: ${key} (${file.size} bytes, ${contentType})`);
|
console.log(`Uploading: ${key} (${file.size} bytes, ${contentType})`);
|
||||||
const uploadPromise = new Upload({
|
// Use PutObjectCommand (single PUT) — compatible with RustFS/MinIO/generic S3.
|
||||||
client: s3Client,
|
// The @aws-sdk/lib-storage Upload class uses CreateMultipartUpload internally
|
||||||
params: { Bucket: bucket, Key: key, Body: fs.createReadStream(file.path), ContentType: contentType },
|
// which returns non-standard XML from RustFS and causes UnknownError.
|
||||||
queueSize: 4,
|
const fileBuffer = fs.readFileSync(file.path);
|
||||||
partSize: 10 * 1024 * 1024,
|
const putPromise = s3Client.send(new PutObjectCommand({
|
||||||
leavePartsOnError: false,
|
Bucket: bucket, Key: key, Body: fileBuffer, ContentType: contentType,
|
||||||
}).done();
|
}));
|
||||||
const result = await withTimeout(uploadPromise, UPLOAD_TIMEOUT_MS, key);
|
const result = await withTimeout(putPromise, UPLOAD_TIMEOUT_MS, key);
|
||||||
if (result?.assumed) console.log(`Assumed success (timeout): ${key}`);
|
if (result?.assumed) console.log(`Assumed success (timeout): ${key}`);
|
||||||
else console.log(`Confirmed success: ${key}`);
|
else console.log(`Confirmed success: ${key}`);
|
||||||
try { fs.unlinkSync(file.path); } catch (_) {}
|
try { fs.unlinkSync(file.path); } catch (_) {}
|
||||||
|
|
@ -841,12 +841,11 @@ app.post("/api/sharelinks/:token/upload", upload.array("files", 50), async (req,
|
||||||
for (const file of req.files) {
|
for (const file of req.files) {
|
||||||
const key = prefix ? `${prefix.replace(/[-\/]+$/, "")}--${file.originalname}` : file.originalname;
|
const key = prefix ? `${prefix.replace(/[-\/]+$/, "")}--${file.originalname}` : file.originalname;
|
||||||
const contentType = getMimeType(file.originalname, file.mimetype);
|
const contentType = getMimeType(file.originalname, file.mimetype);
|
||||||
const uploadPromise = new Upload({
|
const fileBuffer = fs.readFileSync(file.path);
|
||||||
client: s3Client,
|
const putPromise = s3Client.send(new PutObjectCommand({
|
||||||
params: { Bucket: bucket, Key: key, Body: fs.createReadStream(file.path), ContentType: contentType },
|
Bucket: bucket, Key: key, Body: fileBuffer, ContentType: contentType,
|
||||||
queueSize: 4, partSize: 10 * 1024 * 1024, leavePartsOnError: false,
|
}));
|
||||||
}).done();
|
await withTimeout(putPromise, UPLOAD_TIMEOUT_MS, key);
|
||||||
await withTimeout(uploadPromise, UPLOAD_TIMEOUT_MS, key);
|
|
||||||
try { fs.unlinkSync(file.path); } catch (_) {}
|
try { fs.unlinkSync(file.path); } catch (_) {}
|
||||||
results.push({ originalName: file.originalname, key, size: file.size });
|
results.push({ originalName: file.originalname, key, size: file.size });
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue