@valentinkolb/filegate 2.3.3 → 2.3.5

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@valentinkolb/filegate",
3
- "version": "2.3.3",
3
+ "version": "2.3.5",
4
4
  "type": "module",
5
5
  "license": "MIT",
6
6
  "repository": {
@@ -113,20 +113,20 @@ const assembleFile = async (meta: UploadMeta): Promise<string | null> => {
113
113
 
114
114
  try {
115
115
  for (let i = 0; i < meta.totalChunks; i++) {
116
- // Stream each chunk instead of loading entirely into memory
117
- const chunkFile = Bun.file(chunkPath(meta.uploadId, i));
116
+ const chunkFilePath = chunkPath(meta.uploadId, i);
117
+ const chunkFile = Bun.file(chunkFilePath);
118
118
 
119
- // Verify chunk exists before streaming
119
+ // Verify chunk exists before reading
120
120
  if (!(await chunkFile.exists())) {
121
121
  writer.end();
122
122
  await rm(pathResult.realPath).catch(() => {});
123
123
  return `chunk ${i} not found during assembly`;
124
124
  }
125
125
 
126
- for await (const data of chunkFile.stream()) {
127
- hasher.update(data);
128
- writer.write(data);
129
- }
126
+ // Read chunk as buffer (more reliable than streaming)
127
+ const data = new Uint8Array(await chunkFile.arrayBuffer());
128
+ hasher.update(data);
129
+ writer.write(data);
130
130
  }
131
131
  await writer.end();
132
132
  } catch (e) {
@@ -272,32 +272,33 @@ app.post(
272
272
  return c.json({ error: `chunk index ${chunkIndex} exceeds total ${meta.totalChunks}` }, 400);
273
273
  }
274
274
 
275
- const body = c.req.raw.body;
276
- if (!body) return c.json({ error: "missing body" }, 400);
275
+ // Read body as ArrayBuffer (more reliable than streaming)
276
+ let bodyBuffer: ArrayBuffer;
277
+ try {
278
+ bodyBuffer = await c.req.arrayBuffer();
279
+ } catch {
280
+ return c.json({ error: "failed to read request body" }, 400);
281
+ }
277
282
 
278
- // Stream chunks to a temporary file to avoid memory accumulation
279
- const tempChunkPath = chunkPath(uploadId, chunkIndex) + ".tmp";
280
- let chunkSize = 0;
283
+ if (bodyBuffer.byteLength === 0) {
284
+ return c.json({ error: "missing body" }, 400);
285
+ }
286
+
287
+ if (bodyBuffer.byteLength > config.maxChunkBytes) {
288
+ return c.json({ error: `chunk size exceeds maximum (${config.maxChunkBytes / 1024 / 1024}MB)` }, 413);
289
+ }
290
+
291
+ const bodyData = new Uint8Array(bodyBuffer);
281
292
  const hasher = new Bun.CryptoHasher("sha256");
293
+ hasher.update(bodyData);
282
294
 
295
+ // Write chunk to temporary file
296
+ const tempChunkPath = chunkPath(uploadId, chunkIndex) + ".tmp";
283
297
  await mkdir(chunksDir(uploadId), { recursive: true });
284
- const tempFile = Bun.file(tempChunkPath);
285
- const writer = tempFile.writer();
286
298
 
287
299
  try {
288
- for await (const chunk of body) {
289
- chunkSize += chunk.length;
290
- if (chunkSize > config.maxChunkBytes) {
291
- writer.end();
292
- await rm(tempChunkPath).catch(() => {});
293
- return c.json({ error: `chunk size exceeds maximum (${config.maxChunkBytes / 1024 / 1024}MB)` }, 413);
294
- }
295
- hasher.update(chunk);
296
- writer.write(chunk);
297
- }
298
- await writer.end();
300
+ await Bun.write(tempChunkPath, bodyData);
299
301
  } catch (e) {
300
- writer.end();
301
302
  await rm(tempChunkPath).catch(() => {});
302
303
  throw e;
303
304
  }