You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Vue3中onbeforeunload触发时无法通过预签名URL保存文件至S3

问题原因分析
  1. axios.put失效:页面卸载阶段(onbeforeunload)中,浏览器会优先终止未完成的异步请求,axios默认的异步请求会被直接中断;即使强制设置同步请求,现代浏览器也会限制主线程阻塞操作,导致请求无法完成。
  2. navigator.sendBeacon失效:sendBeacon仅支持POST请求,且无法自定义请求方法和多数请求头,而你的S3预签名URL是针对PUT方法生成的,请求方法不匹配会被S3直接拒绝。
解决方案

方案一:使用Fetch API + keepalive参数(推荐)

Fetch API支持自定义请求方法,且keepalive: true参数会告诉浏览器在页面卸载后继续完成请求,完美适配S3 PUT预签名URL的场景。

window.addEventListener('beforeunload', async (event) => {
  const presignedUrl = store.getters["vocabularyGameStore/getCustomerDashboardPresignedUrl"];
  const payload = JSON.stringify(customerDashboard);

  try {
    await fetch(presignedUrl, {
      method: 'PUT',
      body: payload,
      headers: {
        'Content-Type': 'application/json'
      },
      keepalive: true
    });
  } catch (error) {
    console.error('S3保存失败:', error);
  }
});

关键注意事项:

  • 确保后端生成预签名URL时,指定的请求方法为PUT,且Content-Type设置为application/json,与前端请求完全一致,否则S3会返回403权限错误。
  • S3 Bucket的CORS配置需允许PUT方法,以及你的应用域名的跨域请求。

方案二:改用S3预签名POST + sendBeacon

如果必须使用sendBeacon,需要后端生成S3预签名POST的表单参数(而非PUT URL),通过表单数据的方式上传。

前端代码示例:

window.addEventListener('beforeunload', (event) => {
  // 从store获取预签名POST的配置:包含上传地址postUrl和签名字段fields
  const { postUrl, fields } = store.getters["vocabularyGameStore/getCustomerDashboardPresignedPost"];
  const formData = new FormData();

  // 添加S3要求的签名字段
  Object.entries(fields).forEach(([key, value]) => {
    formData.append(key, value);
  });

  // 添加要上传的JSON内容为Blob
  const blob = new Blob([JSON.stringify(customerDashboard)], { type: 'application/json' });
  formData.append('file', blob, 'customer-dashboard.json'); // 文件名可自定义

  // 触发sendBeacon请求
  const isSent = navigator.sendBeacon(postUrl, formData);
  console.log('sendBeacon请求触发状态:', isSent);
});

后端要求:

后端需使用AWS SDK生成S3预签名POST的参数(包含policy、signature、key等字段),确保参数与S3的POST上传规则匹配。


内容的提问来源于stack exchange,提问作者israelk

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.20 20:52:32