Skip to content

Commit f9160ad

Browse files
committed
fix: uid conflict when multiple upload components paste at same time
1 parent c0188c8 commit f9160ad

File tree

2 files changed

+125
-5
lines changed

2 files changed

+125
-5
lines changed

src/AjaxUploader.tsx

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -95,7 +95,12 @@ class AjaxUploader extends Component<UploadProps> {
9595
const { multiple, directory } = this.props;
9696

9797
const items: DataTransferItem[] = [...(dataTransfer.items || [])];
98-
let files: File[] = [...(dataTransfer.files || [])];
98+
let files: File[] = [...(dataTransfer.files || [])].map((file: File) => {
99+
return new File([file], file.name, {
100+
type: file.type,
101+
lastModified: file.lastModified,
102+
});
103+
});
99104

100105
if (files.length > 0 || items.some(item => item.kind === 'file')) {
101106
existFileCallback?.();
@@ -296,7 +301,6 @@ class AjaxUploader extends Component<UploadProps> {
296301
delete this.reqs[uid];
297302
},
298303
};
299-
300304
onStart(origin);
301305
this.reqs[uid] = request(requestOption, { defaultRequest });
302306
}

tests/uploader.spec.tsx

Lines changed: 119 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -318,7 +318,7 @@ describe('uploader', () => {
318318
Object.defineProperty(files, 'item', {
319319
value: i => files[i],
320320
});
321-
321+
322322
// Only can trigger once
323323
let triggerTimes = 0;
324324
handlers.onStart = () => {
@@ -345,7 +345,7 @@ describe('uploader', () => {
345345
fireEvent.drop(input, { dataTransfer: { files } });
346346

347347
setTimeout(() => {
348-
handlers.onSuccess!(['', files[0].name] as any, files[0] as any, null!);
348+
requests[0].respond(200, {}, `["","${files[0].name}"]`);
349349
}, 100);
350350
});
351351

@@ -432,7 +432,7 @@ describe('uploader', () => {
432432
fireEvent.paste(input, { clipboardData: { files } });
433433

434434
await sleep(100);
435-
handlers.onSuccess!(['', files[0].name] as any, files[0] as any, null!);
435+
requests[0].respond(200, {}, `["","${files[0].name}"]`);
436436
});
437437

438438
it('support action and data is function returns Promise', async () => {
@@ -524,6 +524,122 @@ describe('uploader', () => {
524524
expect(preventDefaultSpy).toHaveBeenCalledTimes(0);
525525
preventDefaultSpy.mockRestore();
526526
});
527+
528+
it('should prevent uid overwritten when multiple upload components paste simultaneously', async () => {
529+
const handlers1: UploadProps = {};
530+
const handlers2: UploadProps = {};
531+
532+
const props1: UploadProps = {
533+
...props,
534+
beforeUpload(file, fileList) {
535+
if (handlers1.beforeUpload) {
536+
return handlers1.beforeUpload(file, fileList);
537+
}
538+
return true;
539+
},
540+
onStart(file) {
541+
if (handlers1.onStart) {
542+
handlers1.onStart(file);
543+
}
544+
},
545+
onSuccess(ret, file) {
546+
if (handlers1.onSuccess) {
547+
handlers1.onSuccess(ret, file, null!);
548+
}
549+
},
550+
onError(err, result, file) {
551+
if (handlers1.onError) {
552+
handlers1.onError(err, result, file);
553+
}
554+
},
555+
};
556+
557+
const props2: UploadProps = {
558+
...props,
559+
beforeUpload(file, fileList) {
560+
if (handlers2.beforeUpload) {
561+
return handlers2.beforeUpload(file, fileList);
562+
}
563+
return true;
564+
},
565+
onStart(file) {
566+
if (handlers2.onStart) {
567+
handlers2.onStart(file);
568+
}
569+
},
570+
onSuccess(ret, file) {
571+
if (handlers2.onSuccess) {
572+
handlers2.onSuccess(ret, file, null!);
573+
}
574+
},
575+
onError(err, result, file) {
576+
if (handlers2.onError) {
577+
handlers2.onError(err, result, file);
578+
}
579+
},
580+
};
581+
582+
let uid1: string | undefined;
583+
handlers1.beforeUpload = (file, fileList) => {
584+
expect(file).toHaveProperty('uid');
585+
uid1 = file.uid;
586+
return true;
587+
};
588+
handlers1.onStart = file => {
589+
expect(file).toHaveProperty('uid');
590+
expect(file.uid).toEqual(uid1);
591+
};
592+
handlers1.onSuccess = (ret, file) => {
593+
expect(ret[1]).toEqual(file.name);
594+
expect(file).toHaveProperty('uid');
595+
expect(file.uid).toEqual(uid1);
596+
};
597+
handlers1.onError = (err, result, file) => {
598+
expect(file).toHaveProperty('uid');
599+
expect(file.uid).toEqual(uid1);
600+
throw err;
601+
};
602+
603+
let uid2: string | undefined;
604+
handlers2.beforeUpload = (file, fileList) => {
605+
expect(file).toHaveProperty('uid');
606+
uid2 = file.uid;
607+
return true;
608+
};
609+
handlers2.onStart = file => {
610+
expect(file).toHaveProperty('uid');
611+
expect(file.uid).toEqual(uid2);
612+
};
613+
handlers2.onSuccess = (ret, file) => {
614+
expect(ret[1]).toEqual(file.name);
615+
expect(file).toHaveProperty('uid');
616+
expect(file.uid).toEqual(uid2);
617+
};
618+
handlers2.onError = (err, result, file) => {
619+
expect(file).toHaveProperty('uid');
620+
expect(file.uid).toEqual(uid2);
621+
throw err;
622+
};
623+
624+
const { container: container } = render(<Upload {...props1} pastable />);
625+
render(<Upload {...props2} pastable />);
626+
627+
const input = container.querySelector('input')!;
628+
629+
const files = [
630+
new File([''], 'success.png', { type: 'image/png' }),
631+
];
632+
Object.defineProperty(files, 'item', {
633+
value: i => files[i],
634+
});
635+
636+
fireEvent.paste(input, {
637+
clipboardData: { files },
638+
});
639+
640+
await sleep(100);
641+
requests[0].respond(200, {}, `["","${files[0].name}"]`);
642+
});
527643
});
528644

529645
describe('directory uploader', () => {

0 commit comments

Comments
 (0)