diff --git a/std/mime/multipart.ts b/std/mime/multipart.ts index 75d418c92e..7f7d0c8eef 100644 --- a/std/mime/multipart.ts +++ b/std/mime/multipart.ts @@ -252,11 +252,13 @@ function skipLWSPChar(u: Uint8Array): Uint8Array { } export interface MultipartFormData { - file(key: string): FormFile | undefined; + file(key: string): FormFile | FormFile[] | undefined; value(key: string): string | undefined; - entries(): IterableIterator<[string, string | FormFile | undefined]>; + entries(): IterableIterator< + [string, string | FormFile | FormFile[] | undefined] + >; [Symbol.iterator](): IterableIterator< - [string, string | FormFile | undefined] + [string, string | FormFile | FormFile[] | undefined] >; /** Remove all tempfiles */ removeAll(): Promise; @@ -282,7 +284,7 @@ export class MultipartReader { * @param maxMemory maximum memory size to store file in memory. bytes. @default 10485760 (10MB) * */ async readForm(maxMemory = 10 << 20): Promise { - const fileMap = new Map(); + const fileMap = new Map(); const valueMap = new Map(); let maxValueBytes = maxMemory + (10 << 20); const buf = new Buffer(new Uint8Array(maxValueBytes)); @@ -307,7 +309,7 @@ export class MultipartReader { continue; } // file - let formFile: FormFile | undefined; + let formFile: FormFile | FormFile[] | undefined; const n = await copyN(p, buf, maxValueBytes); const contentType = p.headers.get("content-type"); assert(contentType != null, "content-type must be set"); @@ -343,7 +345,16 @@ export class MultipartReader { maxValueBytes -= n; } if (formFile) { - fileMap.set(p.formName, formFile); + const mapVal = fileMap.get(p.formName); + if (mapVal !== undefined) { + if (Array.isArray(mapVal)) { + mapVal.push(formFile); + } else { + fileMap.set(p.formName, [mapVal, formFile]); + } + } else { + fileMap.set(p.formName, formFile); + } } } return multipatFormData(fileMap, valueMap); @@ -411,17 +422,17 @@ export class MultipartReader { } function multipatFormData( - fileMap: Map, + fileMap: Map, valueMap: Map ): MultipartFormData { - function file(key: string): FormFile | undefined { + function file(key: string): FormFile | FormFile[] | undefined { return fileMap.get(key); } function value(key: string): string | undefined { return valueMap.get(key); } function* entries(): IterableIterator< - [string, string | FormFile | undefined] + [string, string | FormFile | FormFile[] | undefined] > { yield* fileMap; yield* valueMap; @@ -429,8 +440,15 @@ function multipatFormData( async function removeAll(): Promise { const promises: Array> = []; for (const val of fileMap.values()) { - if (!val.tempfile) continue; - promises.push(Deno.remove(val.tempfile)); + if (Array.isArray(val)) { + for (const subVal of val) { + if (!subVal.tempfile) continue; + promises.push(Deno.remove(subVal.tempfile)); + } + } else { + if (!val.tempfile) continue; + promises.push(Deno.remove(val.tempfile)); + } } await Promise.all(promises); } @@ -440,7 +458,7 @@ function multipatFormData( entries, removeAll, [Symbol.iterator](): IterableIterator< - [string, string | FormFile | undefined] + [string, string | FormFile | FormFile[] | undefined] > { return entries(); }, diff --git a/std/mime/multipart_test.ts b/std/mime/multipart_test.ts index b7c0cb969c..07f27b39d6 100644 --- a/std/mime/multipart_test.ts +++ b/std/mime/multipart_test.ts @@ -225,7 +225,10 @@ test({ try { assertEquals(form.value("deno"), "land"); assertEquals(form.value("bar"), "bar"); - const file = form.file("file"); + let file = form.file("file"); + if (Array.isArray(file)) { + file = file[0]; + } assert(file != null); assert(file.tempfile != null); assertEquals(file.size, size); @@ -249,7 +252,10 @@ test({ "--------------------------434049563556637648550474" ); const form = await mr.readForm(20); - const file = form.file("file"); + let file = form.file("file"); + if (Array.isArray(file)) { + file = file[0]; + } assert(file != null); const { tempfile, content } = file; assert(tempfile != null);