浏览器批量下载,下载文件缺失。

一次性下载一百多个文件,每次都只能下载一部分。网上查是因为“导出速度过快,浏览器出现阻塞问题,导致文件丢失”。网上的解决方法是添加一个同步定时器,但我的同步定时器不能使用,调用 waitTime前面加await,显示'await' expressions are only allowed within async functions and at the top levels of modules。怎么能使用定时器或者有什么其他方法能解决上述问题呢?感谢。

<!DOCTYPE html>
<html lang="zh">
 
<head>
  <meta charset="UTF-8" />
  <title>FileReader</title>
</head>
 
<body>
  <div>
    <input type="file" name="file" multiple="multiple" id="files" onchange="choosefile()" />
    <div id="name"></div>
    <textarea id="text" cols="100" rows="50"></textarea>
  </div>
  <script type="text/javascript">

  function choosefile () {
    var fileList = document.getElementById('files').files;
    var nameStr = '';
    for (var i = 0; i < fileList.length; i++) {
        nameStr += `${i === 0 ? '' : ', '}${fileList[i].name}`;
        var reader = new FileReader();
        reader.readAsText(fileList[i], "UTF-8");
        reader.onload = function (e) {
            var content = e.target.result;
            const textAreaVal = document.getElementById('text').value;
            document.getElementById('text').value = textAreaVal + content;

            var str = content.match(/https:\/\/img.dota2.com.cn\/dota2static\/herostatic(\S*)\.png/g);
            var heroname = content.match(/npc_dota_hero(\S*)\.png/g);
            console.log("result:", str);
            console.log("name:", heroname);

            const waitTime = async (milliseconds) => await new Promise((resolve) => setTimeout(resolve, milliseconds));
            
            for(var j = 0; j < str.length; j++){

              console.log(j);
              exportFile(str[j],heroname[j]);
              await waitTime(800);
            } 
        }
    }
    document.getElementById('name').append(nameStr);
  }

  const exportFile = (data, fileName, _this)=>{
  // 地址不存在时,禁止操作
  if(!data)return;
  // 下载文件并保存到本地
  const callback = (data) => {
  // 创建a标签,使用 html5 download 属性下载,
    const link = document.createElement('a');
    // 创建url对象
    const objectUrl = window.URL.createObjectURL(new Blob([data]));
    link.style.display='none';
    link.href=objectUrl;
    // 自定义文件名称, fileName
    link.download = fileName; 
    document.body.appendChild(link); 
    link.click();
    // 适当释放url
    window.URL.revokeObjectURL(objectUrl);
  };
  // 把接口返回的url地址转换为 blob
  const xhr = new XMLHttpRequest();
  xhr.open('get', data, true);
  xhr.responseType = 'blob';
  xhr.onload = ()=> {
// 返回文件流,进行下载处理
    callback(xhr.response);
  };
  xhr.send(); // 不要忘记发送
};
 
// ie和浏览器兼容模式会有问题,可以用下面代码调试。
  </script>
</body>
 
</html>

这种情况可能需要将文件打包成一个压缩包,最后下载整个压缩包

不知道你这个问题是否已经解决, 如果还没有解决的话:
  • 这篇文章:async导致函数结果出乎意料,改变原来代码的意图;await is only valid in async functions and the top level bodies of modules 也许能够解决你的问题,你可以看下
  • 以下回答来自chatgpt:

    针对这个问题,除了添加同步定时器外,还可以尝试以下解决方法:

    1. 增大浏览器下载并行数量 可以通过修改浏览器的配置参数,增大浏览器可以同时下载的文件数量,从而提高下载效率和减少丢失的概率。具体方法请自行搜索相关资料。

    2. 使用第三方下载工具 使用专门的下载工具,如IDM等,可以避免浏览器下载的丢失问题,并且支持高速并发下载。

    3. 使用断点续传下载 如果下载过程中出现了某些文件丢失的问题,可以考虑使用断点续传下载的方式,可以有效避免文件的丢失问题,并且可以在下载失败的地方重新开始下载,从而提高下载成功率。

    以上为几种常见的解决方案,具体可根据实际情况具体选择,希望能够帮到你。

    补充说明: 针对使用同步定时器时出现的错误,提示'await' expressions are only allowed within async functions and at the top levels of modules,这是因为await只能在async函数中使用,如果在普通函数中使用会报错。所以,解决方法是将包含await的代码封装到async函数中或者使用Promise来实现异步操作。以下是示例代码:

    // 使用async函数 async function downloadFiles() { for (let i = 1; i <= 100; i++) { await downloadFile(i); // 使用await等待异步操作 } }

    async function downloadFile(index) { return new Promise((resolve, reject) => { // 下载文件的代码 // ...

    // 下载完成后resolve
    resolve();
    

    }); }

    downloadFiles();

    // 使用Promise function downloadFiles() { let promise = Promise.resolve(); for (let i = 1; i <= 100; i++) { promise = promise.then(() => downloadFile(i)); } }

    function downloadFile(index) { return new Promise((resolve, reject) => { // 下载文件的代码 // ...

    // 下载完成后resolve
    resolve();
    

    }); }

    downloadFiles();


如果你已经解决了该问题, 非常希望你能够分享一下解决方案, 写成博客, 将相关链接放在评论区, 以帮助更多的人 ^-^