Skip to content

Commit 71e2dff

Browse files
committed
fix: handle MPU filenames correctly
1 parent 7359694 commit 71e2dff

File tree

4 files changed

+14
-16
lines changed

4 files changed

+14
-16
lines changed

frontend/utils/uploader.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@ import type { PasteEditState } from "../components/PasteEditor.js"
33
import { APIUrl, ErrorWithTitle } from "./utils.js"
44
import type { PasteResponse } from "../../shared/interfaces.js"
55
import { encodeKey, encrypt, EncryptionScheme, genKey } from "./encryption.js"
6-
import { UploadError, uploadMPU, uploadNormal, UploadOptions } from "../../shared/uploadMPU.js"
6+
import { UploadError, uploadMPU, uploadNormal, UploadOptions } from "../../shared/uploadPaste.js"
77

88
async function genAndEncrypt(scheme: EncryptionScheme, content: string | Uint8Array) {
99
const key = await genKey(scheme)
@@ -64,7 +64,7 @@ export async function uploadPaste(
6464
const contentLength = typeof options.content === "string" ? options.content.length : options.content.size
6565

6666
try {
67-
if (contentLength < 5 * 1024 * 1024) {
67+
if (contentLength < 5 * 1024 * 1024 || typeof options.content === "string") {
6868
return await uploadNormal(APIUrl, options)
6969
} else {
7070
if (onProgress) onProgress(0)
Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -133,7 +133,7 @@ export async function uploadMPU(
133133
completeUrl.searchParams.set("name", createResp.name)
134134
completeUrl.searchParams.set("key", createResp.key)
135135
completeUrl.searchParams.set("uploadId", createResp.uploadId)
136-
completeFormData.set("c", JSON.stringify(uploadedParts))
136+
completeFormData.set("c", new File([JSON.stringify(uploadedParts)], content.name))
137137
if (expire !== undefined) {
138138
completeFormData.set("e", expire)
139139
}

worker/handlers/handleWrite.ts

Lines changed: 10 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,7 @@ function suggestUrl(short: string, baseUrl: string, filename?: string, contentAs
2828
type ParsedMultipartPart = {
2929
filename?: string
3030
content: ReadableStream | ArrayBuffer
31-
contentAsString?: string
31+
contentAsString: () => string
3232
contentLength: number
3333
}
3434

@@ -43,13 +43,14 @@ async function multipartToMap(req: Request, sizeLimit: number): Promise<Map<stri
4343
filename: part.filename,
4444
content: arrayBuffer,
4545
contentLength: arrayBuffer.byteLength,
46+
contentAsString: () => decode(arrayBuffer),
4647
})
4748
} else {
4849
const arrayBuffer = await part.arrayBuffer()
4950
partsMap.set(part.name, {
5051
filename: part.filename,
5152
content: arrayBuffer,
52-
contentAsString: decode(arrayBuffer),
53+
contentAsString: () => decode(arrayBuffer),
5354
contentLength: arrayBuffer.byteLength,
5455
})
5556
}
@@ -112,17 +113,14 @@ export async function handlePostOrPut(
112113
throw new WorkerError(400, "cannot find content in formdata")
113114
}
114115
const { filename, content, contentAsString, contentLength } = parts.get("c")!
115-
const nameFromForm = parts.get("n")?.contentAsString
116+
const nameFromForm = parts.get("n")?.contentAsString()
116117
const isPrivate = parts.has("p")
117-
const passwdFromForm = parts.get("s")?.contentAsString
118-
const expireFromForm: string | undefined = parts.get("e")?.contentAsString
119-
const encryptionScheme: string | undefined = parts.get("encryption-scheme")?.contentAsString
118+
const passwdFromForm = parts.get("s")?.contentAsString()
119+
const expireFromForm: string | undefined = parts.get("e")?.contentAsString()
120+
const encryptionScheme: string | undefined = parts.get("encryption-scheme")?.contentAsString()
120121
const expire = expireFromForm ? expireFromForm : env.DEFAULT_EXPIRATION
121122

122-
if (isMPUComplete && contentAsString === undefined) {
123-
throw new WorkerError(400, `field c in formdata mistakenly carries a filename for MPU complete`)
124-
}
125-
const uploadedParts = isMPUComplete ? (JSON.parse(contentAsString!) as R2UploadedPart[]) : undefined
123+
const uploadedParts = isMPUComplete ? (JSON.parse(contentAsString()) as R2UploadedPart[]) : undefined
126124

127125
// parse expiration
128126
let expirationSeconds = parseExpiration(expire)
@@ -212,7 +210,7 @@ export async function handlePostOrPut(
212210
return makeResponse(
213211
{
214212
url: accessUrl(pasteName),
215-
suggestedUrl: suggestUrl(pasteName, env.DEPLOY_URL, filename, contentAsString),
213+
suggestedUrl: suggestUrl(pasteName, env.DEPLOY_URL, filename, contentAsString()),
216214
manageUrl: manageUrl(pasteName, newPasswd),
217215
expirationSeconds,
218216
expireAt: new Date(now.getTime() + 1000 * expirationSeconds).toISOString(),
@@ -252,7 +250,7 @@ export async function handlePostOrPut(
252250
return makeResponse(
253251
{
254252
url: accessUrl(pasteName),
255-
suggestedUrl: suggestUrl(pasteName, env.DEPLOY_URL, filename, contentAsString),
253+
suggestedUrl: suggestUrl(pasteName, env.DEPLOY_URL, filename, contentAsString()),
256254
manageUrl: manageUrl(pasteName, password),
257255
expirationSeconds,
258256
expireAt: new Date(now.getTime() + 1000 * expirationSeconds).toISOString(),

worker/test/mpu.spec.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import { uploadMPU } from "../../shared/uploadMPU"
1+
import { uploadMPU } from "../../shared/uploadPaste"
22
import { vi, test, describe, it, expect, afterAll, beforeEach } from "vitest"
33
import { createExecutionContext } from "cloudflare:test"
44
import { areBlobsEqual, BASE_URL, genRandomBlob, workerFetch } from "./testUtils"

0 commit comments

Comments
 (0)