fix: should be able to upload multiple large files (#23360)
Fixes https://github.com/microsoft/playwright/issues/23258
This commit is contained in:
parent
1f7223eb21
commit
2710fd8d6f
|
|
@ -266,13 +266,13 @@ export async function convertInputFiles(files: string | FilePayload | string[] |
|
|||
const items: (string | FilePayload)[] = Array.isArray(files) ? files.slice() : [files];
|
||||
|
||||
const sizeLimit = 50 * 1024 * 1024;
|
||||
const hasLargeBuffer = items.find(item => typeof item === 'object' && item.buffer && item.buffer.byteLength > sizeLimit);
|
||||
if (hasLargeBuffer)
|
||||
const totalBufferSizeExceedsLimit = items.reduce((size, item) => size + ((typeof item === 'object' && item.buffer) ? item.buffer.byteLength : 0), 0) > sizeLimit;
|
||||
if (totalBufferSizeExceedsLimit)
|
||||
throw new Error('Cannot set buffer larger than 50Mb, please write it to a file and pass its path instead.');
|
||||
|
||||
const stats = await Promise.all(items.filter(isString).map(item => fs.promises.stat(item as string)));
|
||||
const hasLargeFile = !!stats.find(s => s.size > sizeLimit);
|
||||
if (hasLargeFile) {
|
||||
const totalFileSizeExceedsLimit = stats.reduce((acc, stat) => acc + stat.size, 0) > sizeLimit;
|
||||
if (totalFileSizeExceedsLimit) {
|
||||
if (context._connection.isRemote()) {
|
||||
const streams: channels.WritableStreamChannel[] = await Promise.all(items.map(async item => {
|
||||
assert(isString(item));
|
||||
|
|
|
|||
12
tests/assets/input/fileupload-multi.html
Normal file
12
tests/assets/input/fileupload-multi.html
Normal file
|
|
@ -0,0 +1,12 @@
|
|||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<title>File upload test</title>
|
||||
</head>
|
||||
<body>
|
||||
<form action="/upload" method="post" enctype="multipart/form-data">
|
||||
<input type="file" multiple name="file1">
|
||||
<input type="submit">
|
||||
</form>
|
||||
</body>
|
||||
</html>
|
||||
|
|
@ -85,6 +85,44 @@ it('should upload large file', async ({ page, server, browserName, isMac, isAndr
|
|||
await Promise.all([uploadFile, file1.filepath].map(fs.promises.unlink));
|
||||
});
|
||||
|
||||
it('should upload multiple large files', async ({ page, server, browserName, isMac, isAndroid }, testInfo) => {
|
||||
it.skip(browserName === 'webkit' && isMac && parseInt(os.release(), 10) < 20, 'WebKit for macOS 10.15 is frozen and does not have corresponding protocol features.');
|
||||
it.skip(isAndroid);
|
||||
it.slow();
|
||||
const filesCount = 10;
|
||||
await page.goto(server.PREFIX + '/input/fileupload-multi.html');
|
||||
const uploadFile = testInfo.outputPath('50MB_1.zip');
|
||||
const str = 'A'.repeat(1024);
|
||||
const stream = fs.createWriteStream(uploadFile);
|
||||
// 49 is close to the actual limit
|
||||
for (let i = 0; i < 49 * 1024; i++) {
|
||||
await new Promise<void>((fulfill, reject) => {
|
||||
stream.write(str, err => {
|
||||
if (err)
|
||||
reject(err);
|
||||
else
|
||||
fulfill();
|
||||
});
|
||||
});
|
||||
}
|
||||
await new Promise(f => stream.end(f));
|
||||
const input = page.locator('input[type="file"]');
|
||||
const uploadFiles = [uploadFile];
|
||||
for (let i = 2; i <= filesCount; i++) {
|
||||
const dstFile = testInfo.outputPath(`50MB_${i}.zip`);
|
||||
fs.copyFileSync(uploadFile, dstFile);
|
||||
uploadFiles.push(dstFile);
|
||||
}
|
||||
const fileChooserPromise = page.waitForEvent('filechooser');
|
||||
await input.click();
|
||||
const fileChooser = await fileChooserPromise;
|
||||
await fileChooser.setFiles(uploadFiles);
|
||||
const filesLen = await page.evaluate('document.getElementsByTagName("input")[0].files.length');
|
||||
expect(fileChooser.isMultiple()).toBe(true);
|
||||
expect(filesLen).toEqual(filesCount);
|
||||
await Promise.all(uploadFiles.map(path => fs.promises.unlink(path)));
|
||||
});
|
||||
|
||||
it('should upload large file with relative path', async ({ page, server, browserName, isMac, isAndroid }, testInfo) => {
|
||||
it.skip(browserName === 'webkit' && isMac && parseInt(os.release(), 10) < 20, 'WebKit for macOS 10.15 is frozen and does not have corresponding protocol features.');
|
||||
it.skip(isAndroid);
|
||||
|
|
|
|||
Loading…
Reference in a new issue