我如何确保在使用puppeteer提交之前等待文件完成上传?



我需要使用puppeteer上传文件,然后在文件完成上传后按下提交按钮。现在它马上按下提交,这太快了。

我以为puppeteer handle.uploadFile('file_path.ext')会等待上传完成后再解析,但看起来它没有。

编辑:澄清一下,根据@ggorlen的评论,我们正在使用https://github.com/kartik-v/bootstrap-fileinput包来处理输入字段的行为。

我一直在尝试寻找哪些事件或响应来侦听以知道文件已完成上传,但没有找到任何有用的。以下是我想到的最好的方法,到目前为止,它对我的情况很有效:

// Get the input
let selector = `input[type=file]`;
let file_input_handle = await page.waitForSelector( selector );
// This comes before the upload starts
// Notice `await` is missing. Don't wait for this to finish now.
// This will be working in the background so we can use it later.
let disabled_selector = `${ selector }[disabled]`;
let wait_for_disabled = page.waitForSelector( disabled_selector );
// Upload
await handle.uploadFile(...paths);
// Stop to wait for the input to be disabled. If it already happened by now
// then this will be done already and it won't wait.
await wait_for_disabled;
// Now DO use `await` to wait for the input to be enabled again.
// On the webpage I'm working with, that means the files are done uploading.
let enabled_selector = `${ selector }:not([disabled])`;
await page.waitForSelector( enabled_selector );
// Do the next thing, like submitting the form
console.log( `Done uploading!` );

编辑:

正如我所说的,这是我的具体情况。我们正在使用https://github.com/kartik-v/bootstrap-fileinput库,它在上传发生时禁用输入。

另外,根据@ggorlen的建议,我做了一个例子。我将把代码放在这里,但是您可以在https://jsfiddle.net/tgfp4x6h/3/上看到它。我不确定puppeteer是否能在jsfiddle中工作,我也不确定如何在jsfiddle上存储文件以便加载,所以我决定只使用我自己的承诺作为示例。

这意味着你必须手动上传文件看到它在工作。在这个过程中,你可以看到背景从红色到绿色的变化。打开浏览器控制台,查看操作发生的日志。一定要上传一堆图片或其他东西,以便你花足够长的时间看到变化的发生。

<!-- bootstrap 5.x or 4.x is supported. You can also use the bootstrap css 3.3.x versions -->
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/bootstrap@5.0.1/dist/css/bootstrap.min.css" crossorigin="anonymous">
<!-- default icons used in the plugin are from Bootstrap 5.x icon library (which can be enabled by loading CSS below) -->
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/bootstrap-icons@1.5.0/font/bootstrap-icons.min.css" crossorigin="anonymous">
<!-- alternatively you can use the font awesome icon library if using with `fas` theme (or Bootstrap 4.x) by uncommenting below. -->
<!-- link rel="stylesheet" href="https://use.fontawesome.com/releases/v5.15.3/css/all.css" crossorigin="anonymous" -->
<!-- the fileinput plugin styling CSS file -->
<link href="https://cdn.jsdelivr.net/gh/kartik-v/bootstrap-fileinput@5.2.2/css/fileinput.min.css" media="all" rel="stylesheet" type="text/css" />
<!-- if using RTL (Right-To-Left) orientation, load the RTL CSS file after fileinput.css by uncommenting below -->
<!-- link href="https://cdn.jsdelivr.net/gh/kartik-v/bootstrap-fileinput@5.2.2/css/fileinput-rtl.min.css" media="all" rel="stylesheet" type="text/css" /-->
<!-- the jQuery Library -->
<script src="https://code.jquery.com/jquery-3.6.0.min.js" crossorigin="anonymous"></script>
<!-- piexif.min.js is needed for auto orienting image files OR when restoring exif data in resized images and when you
    wish to resize images before upload. This must be loaded before fileinput.min.js -->
<script src="https://cdn.jsdelivr.net/gh/kartik-v/bootstrap-fileinput@5.2.2/js/plugins/piexif.min.js" type="text/javascript"></script>
<!-- sortable.min.js is only needed if you wish to sort / rearrange files in initial preview. 
    This must be loaded before fileinput.min.js -->
<script src="https://cdn.jsdelivr.net/gh/kartik-v/bootstrap-fileinput@5.2.2/js/plugins/sortable.min.js" type="text/javascript"></script>
<!-- bootstrap.bundle.min.js below is needed if you wish to zoom and preview file content in a detail modal
    dialog. bootstrap 5.x or 4.x is supported. You can also use the bootstrap js 3.3.x versions. -->
<script src="https://cdn.jsdelivr.net/npm/bootstrap@5.0.1/dist/js/bootstrap.bundle.min.js" crossorigin="anonymous"></script>
<!-- the main fileinput plugin script JS file -->
<script src="https://cdn.jsdelivr.net/gh/kartik-v/bootstrap-fileinput@5.2.2/js/fileinput.min.js"></script>
<!-- following theme script is needed to use the Font Awesome 5.x theme (`fas`). Uncomment if needed. -->
<!-- script src="https://cdn.jsdelivr.net/gh/kartik-v/bootstrap-fileinput@5.2.2/themes/fas/theme.min.js"></script -->
<!-- optionally if you need translation for your language then include the locale file as mentioned below (replace LANG.js with your language locale) -->
<script src="https://cdn.jsdelivr.net/gh/kartik-v/bootstrap-fileinput@5.2.2/js/locales/LANG.js"></script>
<input id="input_id" name="file_data" type="file" multiple>
<script>
$(document).ready(function() {
    // initialize with defaults
    $("#input_id").fileinput();
    // with plugin options
    $("#input_id").fileinput({'uploadUrl': '/path/to/your-upload-api', 'previewFileType': 'any'});
});
</script>
// Bootstrap input from https://github.com/kartik-v/bootstrap-fileinput
let waitForDisabled = function (resolve, reject) {
    console.log('waiting for disabled');
    let disabled_node = document.querySelector('input#input_id[disabled]');
  
  if ( disabled_node ) {
    // If node is found, finish
    resolve()
    console.log( disabled_node );
    
  } else {
    // otherwise, loop
    setTimeout(function() {
        waitForDisabled( resolve, reject );
    }, 100);
  }
}
let waitForEnabled = function (resolve, reject) {
    console.log('waiting for enabled');
    let enabled_node = document.querySelector('input#input_id:not([disabled])');
  
  if ( enabled_node ) {
    // If node is found, finish
    resolve()
    console.log( enabled_node );
    
  } else {
    // otherwise, loop
    setTimeout(function() {
        waitForEnabled( resolve, reject );
    }, 100);
  }
}
let uploadFile = function ( resolve, reject ) {
    // This would be uploading the file, but you should do it by hand
  resolve();
};

let wait_for_it = async function () {
  
  let waiting_for_disabled = new Promise( waitForDisabled );
  
  await new Promise( uploadFile );
  
  await waiting_for_disabled;
  await new Promise( waitForEnabled );
  console.log( 'Done uploading!' );
}
wait_for_it();

最新更新