Is there any way to handle File Input Dialogs?
When I click an element on the page, it opens up the upload file dialog.
I can not use elementHandle.uploadFile as it is not an input[type="file"]. Plus, #1376 will not help as, dragging and dropping in the file upload field does not work, instead, dragging and dropping opens up the file in the browser tab.
I am using Windows, so there won't be the problem where, file dialog behavior is different across operating systems.
So, can you provide some example code on how would I go about doing that? Thanks!
If there is something like which could keyboard.type into the file dialog and press enter, that would do the trick. We can accomplish this using different node packages that generate keyboard events at operating system level, but, that requires the browser to always be in focus.
So, is there something like this possible in Puppeteer?
So, is there something like this possible in Puppeteer?
@KJ1i Puppeteer generally operates on the web page level; we don't support the fileinput dialog and instead "override" it with elementHandle.uploadFile.
How's the file input dialog opened? Maybe I'll be able to come up with a workaround for your case.
@aslushnikov Thanks for replying!
Here is the image of the website upload button:-

When we click on Browse button, it opens up the file dialog and, then, after selecting the file in the file dialog, it fills the <input type="text"> which is at the left side of the button.
The following is the website:- http://www.createspace.com
If you want, I can create an account for you here and message you its login details.
I have asked this question on StackOverflow also:- https://stackoverflow.com/questions/51491928/uploading-a-file-on-non-input-type-file
It contains more info about the question in hand.
Please let me know if more details are needed.
Thanks a lot for replying!
Awaiting your reply.
I have a similar problem.
I use a custom plugin ng-file-upload in my project, when I click a element like button and trigger a event, this plugin will create a <input type="file"> and click it. so I can't get <input type="file"> in my page. The elementHandle.uploadFile also has no help for me.
I think this is a very common practice to upload file, but I can't use puppeteer to resolve it. Please give some help for me.
Also having the same problem as @KJ1i where clicking on an element opens a native dialog (and it's not input[type="file"]).
@KJ1i @cloudZQY @HawkiesZA this is indeed poorly supported atm; I failed to come up with any reasonable workaround for you guys.
For this to work properly, we need to expose more events from DevTools procol, similarly how we did it with javascript dialogs.
Please upvote the issue to bump its priority. We rely on "likes" to figure what's most important to do next.
sounds like a must have feature, most sites these days tend to use alternative file upload controls instead of the common file input
I would really like to see this feature supported soon !
This support is something which I am in need too, any plan to provide a fix on this?
Seems that for my specific case, I was able to work it out:
input[type="file"] and upload your file over there.Here's a naive example:
await page.waitForSelector('.file-dialog-trigger')
await page.click('.file-dialog-trigger')
const input = await page.$('input[type="file"]')
await input.uploadFile('./content.csv')
need this feature badly!
Hi Team,
The above solution works partially, the file is uploaded but the content of the file is not update any input on this please help me, following was the image
image

my selector:
var findelement = await bs.page.$("#upload-used-car-photo > span > div.ant-upload.ant-upload-drag > span >input[type='file']");
await findelement.uploadFile(absoultepath);
@nuc
I also work it out using your way.
But problem is the file dialog is still opened even after upload file succeed.
How can you close file dialog?
Looking forward for this feature. Also have this issue!
Any progress on this?
I second the need for this. I am writing a fuzz tester for our app. Works great, but I'd love to be able to upload a generic image whenever a file dialog appears.
This would be a sweet API:
page.on('filedialog', async input => {
await input.uploadFile('./foo.jpg')
})
I confirm this is much needed
Is there any progress on this? me and my team would love for this feature to be implemented.
Agreed, this would be nice for testing server google cloud server deployments of Drupal, Wordpress, and others just to make sure files can be uploaded properly.
await this.core.bot.emulate(iPhone);
let selector = "#react-root section nav div div header div.b5itu div button";
await this.core.bot.waitForSelector(selector, {timeout: 5000});
let button = await this.core.bot.$(selector);
await button.click();
let select = "input[type=\"file\"]"; //input.tb_sK
await this.core.bot.waitForSelector(select, {timeout: 5000});
let input = await this.core.bot.$(select);
let filePath = path.relative(process.cwd(), __dirname + '/assets/ByaFCAwApsN.jpg');
await input.uploadFile(filePath);
Actions are performed, but the file is not loaded. Why not working?
@Ermolaev-Nikolay try using another selector for select variable, e.g.: #react-root input[type=\"file\"]". I saw an issue before when it didn't work with the input[type=file] selector even though it was a valid one.
@slmgc, thank you for the answer, but seems the problem in another. It seems the photo is loaded, but instead of the edit window goes to main page.
Anybody solve it? Thanks
@aslushnikov is there any documentation on file chooser api?
Many thanks for this! Right on time.
@aslushnikov is there any documentation on file chooser api?
@OmarKhattab it just was just released in 1.19.0: https://pptr.dev/#?product=Puppeteer&version=v1.19.0&show=api-class-filechooser
Thank you @aslushnikov!
I'm trying to use the file chooser but my program hangs on await fileChooser.accept. For example, the code below never prints the last line! Am I missing something?
Thank you!
const [fileChooser] = await Promise.all([
page.waitForFileChooser(),
page.click('#upload-file-button'), // some button that triggers file selection
]);
await fileChooser.accept(['/tmp/myfile.pdf']);
console.log("never print this!!!")
The new file chooser does not work for me. I get the "File chooser handling does not work with multiple connections to the same page" error no matter what, despite only having a simple example with a single page connection. See #4783.
@sekreiner I have the same problem.
Is it solved?
I'm having the same issue. I cannot send an image to a facebook input [type=file]. Did anyone figured it out ?
if you you youse some kind of upload library (react-dropzone in my case) you can try to trigger a change event on the input after uploading the file.
await page.waitForSelector('input[type=file]');
const fileInput = await page.$(''input[type=file]');
await fileInput.uploadFile("./testfile.pdf");
await fileInput.evaluate(upload => upload.dispatchEvent(new Event('change', { bubbles: true })));
this did the trick for me
@robinjoerke 's solution works like a charm for me. Thanks for sharing!
@robinjoerke , thanks! At last somebody found a solution that is working.
@aslushnikov maybe that should be fixed on puppeteer/playwrite API level? Because it's the same on both of libraries - it does attach file to element, but upload event isn't triggered. Same cases are working with the help of webdriver with no issues.
phpmyadmin form import not working.
if you you youse some kind of upload library (react-dropzone in my case) you can try to trigger a change event on the input after uploading the file.
await page.waitForSelector('input[type=file]');
const fileInput = await page.$(''input[type=file]');
await fileInput.uploadFile("./testfile.pdf");
await fileInput.evaluate(upload => upload.dispatchEvent(new Event('change', { bubbles: true })));this did the trick for me
Thanks, it works.
if you you youse some kind of upload library (react-dropzone in my case) you can try to trigger a change event on the input after uploading the file.
await page.waitForSelector('input[type=file]');
const fileInput = await page.$(''input[type=file]');
await fileInput.uploadFile("./testfile.pdf");
await fileInput.evaluate(upload => upload.dispatchEvent(new Event('change', { bubbles: true })));this did the trick for me
if you you youse some kind of upload library (react-dropzone in my case) you can try to trigger a change event on the input after uploading the file.
await page.waitForSelector('input[type=file]');
const fileInput = await page.$(''input[type=file]');
await fileInput.uploadFile("./testfile.pdf");
await fileInput.evaluate(upload => upload.dispatchEvent(new Event('change', { bubbles: true })));this did the trick for me
This code works very well thanks, but I have a problem, event object received by my event listener doesn't have a file type when I trigger a change event. Like this event.target.files[0].type = "". Normally, event.target.files[0].type should have a value like event.target.files[0].type = "image/png".
What should i do.
@robinjoerke's code looks a bit hackish but has anyone actually managed to use the fileChooser API (waitForFileChooser and accept) or is it broken?
This code works very well thanks, but I have a problem, event object received by my event listener doesn't have a file type when I trigger a change event. Like this event.target.files[0].type = "". Normally, event.target.files[0].type should have a value like event.target.files[0].type = "image/png".
What should i do.
As I said I was using an upload library, I was not noticing this issue (library somehow just ignored this). But backend always recieved contentType "application/octet-stream". Should have been something as "image/png" as well. This might be an effect of the issue you have. What I do to fix this is just guess the content type from the file extension part of the filename. Not a nice solution but works for my testing scenarios.
I think the biggest problem is that the file will be sent as application/octet-stream which would break the upload on the server side that wants to treat the upload depending on the content-type (I know it shouldn't rely on it, but I'm not at a liberty to modify the receiving end's server side code) being sent from the browser which is a very different behavior from a natural browser.
I have searched around a lot but I cannot figure out how to set content-type for the multipart header. Even tried to upload via XHR after setting the file with uploadFile but no luck and applying input.files[0].type = 'image/jpeg' won't change the content-type.
if you you youse some kind of upload library (react-dropzone in my case) you can try to trigger a change event on the input after uploading the file.
await page.waitForSelector('input[type=file]');
const fileInput = await page.$(''input[type=file]');
await fileInput.uploadFile("./testfile.pdf");
await fileInput.evaluate(upload => upload.dispatchEvent(new Event('change', { bubbles: true })));this did the trick for me
Thanks a lot!!! It works for me.
await page.waitForSelector('input[type=file]');
await page.waitFor(1000);
const input = await page.$('input[type="file"]');
await input.uploadFile(filepath);
this works without click on the button and without a remaining open windows from the browser
Seems that for my specific case, I was able to work it out:
- Click on the button which triggers the native file input dialog.
- Look for
input[type="file"]and upload your file over there.Here's a naive example:
await page.waitForSelector('.file-dialog-trigger') await page.click('.file-dialog-trigger') const input = await page.$('input[type="file"]') await input.uploadFile('./content.csv')
You saved my life man!!!!
This works for me:
const [fileChooser] = await Promise.all([
page.waitForFileChooser(),
page.click('.file-dialog-triger'),
]);
await fileChooser.accept([./content.csv']);
How do you close the dialog?
How do you close the dialog?
using that code, the dialog there is no pop up dialog appear. it automatically upload the file without open file dialog
Simplest example:
const fileInput = await page.$('#file-input')
await fileInput.uploadFile(filename)
If a button spawns the input dialog:
const [fileInput] = await Promise.all([page.waitForFileChooser(), page.click("#file-input")])
await fileInput.accept([filename])
Most helpful comment
@KJ1i @cloudZQY @HawkiesZA this is indeed poorly supported atm; I failed to come up with any reasonable workaround for you guys.
For this to work properly, we need to expose more events from DevTools procol, similarly how we did it with javascript dialogs.
Please upvote the issue to bump its priority. We rely on "likes" to figure what's most important to do next.