fix: prepare jsHandle.uploadFile for CDP Page.handleFileChooser removal (#5196)
* fix: prepare jsHandle.uploadFile for CDP Page.handleFileChooser removal https://chromium-review.googlesource.com/c/chromium/src/+/1935410 removes Page.handleFileChooser from the CDP. * fix: improve binary file support UTF-8-decoding the input file could fail for binary files, and so we now read the raw file buffer and base64-encode it. To base64-decode it within the page context, we use the Fetch API in combination with a data URL. This requires knowing the proper MIME type for the input file, which we now figure out using the new mime-types dependency.
This commit is contained in:
parent
8b49dc62a6
commit
6091a34a36
@ -15,7 +15,6 @@
|
||||
*/
|
||||
|
||||
const {helper, assert, debugError} = require('./helper');
|
||||
const path = require('path');
|
||||
|
||||
function createJSHandle(context, remoteObject) {
|
||||
const frame = context.frame();
|
||||
@ -302,8 +301,8 @@ class ElementHandle extends JSHandle {
|
||||
if (option.selected && !element.multiple)
|
||||
break;
|
||||
}
|
||||
element.dispatchEvent(new Event('input', { 'bubbles': true }));
|
||||
element.dispatchEvent(new Event('change', { 'bubbles': true }));
|
||||
element.dispatchEvent(new Event('input', { bubbles: true }));
|
||||
element.dispatchEvent(new Event('change', { bubbles: true }));
|
||||
return options.filter(option => option.selected).map(option => option.value);
|
||||
}, values);
|
||||
}
|
||||
@ -312,9 +311,35 @@ class ElementHandle extends JSHandle {
|
||||
* @param {!Array<string>} filePaths
|
||||
*/
|
||||
async uploadFile(...filePaths) {
|
||||
const files = filePaths.map(filePath => path.resolve(filePath));
|
||||
const objectId = this._remoteObject.objectId;
|
||||
await this._client.send('DOM.setFileInputFiles', { objectId, files });
|
||||
// These imports are only needed for `uploadFile`, so keep them
|
||||
// scoped here to avoid paying the cost unnecessarily.
|
||||
const path = require('path');
|
||||
const mime = require('mime-types');
|
||||
const fs = require('fs');
|
||||
const readFileAsync = helper.promisify(fs.readFile);
|
||||
|
||||
const promises = filePaths.map(filePath => readFileAsync(filePath));
|
||||
const files = [];
|
||||
for (let i = 0; i < filePaths.length; i++) {
|
||||
const buffer = await promises[i];
|
||||
const filePath = path.basename(filePaths[i]);
|
||||
const file = {
|
||||
name: filePath,
|
||||
content: buffer.toString('base64'),
|
||||
mimeType: mime.lookup(filePath),
|
||||
};
|
||||
files.push(file);
|
||||
}
|
||||
await this.evaluateHandle(async(element, files) => {
|
||||
const dt = new DataTransfer();
|
||||
for (const item of files) {
|
||||
const response = await fetch(`data:${item.mimeType};base64,${item.content}`);
|
||||
const file = new File([await response.blob()], item.name);
|
||||
dt.items.add(file);
|
||||
}
|
||||
element.files = dt.files;
|
||||
element.dispatchEvent(new Event('input', { bubbles: true }));
|
||||
}, files);
|
||||
}
|
||||
|
||||
async tap() {
|
||||
|
@ -30,10 +30,12 @@
|
||||
"author": "The Chromium Authors",
|
||||
"license": "Apache-2.0",
|
||||
"dependencies": {
|
||||
"@types/mime-types": "^2.1.0",
|
||||
"debug": "^4.1.0",
|
||||
"extract-zip": "^1.6.6",
|
||||
"https-proxy-agent": "^3.0.0",
|
||||
"mime": "^2.0.3",
|
||||
"mime-types": "^2.1.25",
|
||||
"progress": "^2.0.1",
|
||||
"proxy-from-env": "^1.0.0",
|
||||
"rimraf": "^2.6.1",
|
||||
|
Loading…
Reference in New Issue
Block a user