在Web应用中,有时我们需要让用户能够下载文件,并且希望用户能够看到有意义的文件名而不是默认的、可能难以理解的名字。例如,在一个业务系统中,当用户点击“导出”按钮时,我们可以生成一个带有时间戳的文件名,这样用户就能清楚地知道文件是什么时候创建的。

方法一:使用window.open下载文件

这种方法较为简单,但通常无法直接控制文件名。大多数情况下,浏览器会根据服务器提供的信息或文件的实际内容来决定下载文件的名称。

方法二:使用Blob对象和URL.createObjectURL

这种方法允许我们创建一个临时的URL,指向内存中的文件,从而让我们能够完全控制文件的内容和文件名。

下面是一个具体的示例,展示了如何使用Vue.js结合上述第二种方法实现文件下载,并自定义文件名。

<template>
  <div>
    <button @click="handleConfirm">导出Excel</button>
  </div>
</template>

<script>
export default {
  data() {
    return {
      asyncFile: null, // 这里应该包含文件的URL或者Blob
    };
  },
  methods: {
    generateTimestamp() {
      const now = new Date();
      const year = now.getFullYear().toString();
      const month = ('0' + (now.getMonth() + 1)).slice(-2); // 月份是从0开始的,所以加1
      const day = ('0' + now.getDate()).slice(-2);
      const hours = ('0' + now.getHours()).slice(-2);
      const minutes = ('0' + now.getMinutes()).slice(-2);
      const seconds = ('0' + now.getSeconds()).slice(-2);

      return `六粮液检验报告_${year}${month}${day}${hours}${minutes}${seconds}`;
    },
    handleConfirm() {
      if (!this.asyncFile) {
        console.error('文件URL未设置');
        return;
      }

      // 创建一个 Blob 对象
      fetch(this.asyncFile)
        .then((response) => response.blob())
        .then((blob) => {
          // 创建一个临时的 Blob URL
          const url = URL.createObjectURL(blob);

          // 创建一个隐藏的可点击链接
          const link = document.createElement('a');
          link.href = url;

          // 生成带有时间戳的文件名
          const timestamp = this.generateTimestamp();
          link.download = `${timestamp}.xlsx`;

          // 触发点击事件以下载文件
          link.click();

          // 清理临时 URL
          setTimeout(() => URL.revokeObjectURL(url), 0);
        })
        .catch((error) => {
          console.error('文件下载失败', error);
        });
    },
  },
};
</script>

解释与原理

  1. 生成时间戳
  • generateTimestamp 方法生成一个格式化的字符串,包含了当前日期和时间的信息。这个字符串被用来作为文件名的一部分,确保每次导出的文件都有唯一的名称。
  1. 处理确认
  • handleConfirm 方法首先检查是否有有效的文件URL或Blob。
  • 使用fetch API从给定的URL获取文件数据,并将其转换为Blob对象。
  • 利用URL.createObjectURL创建一个指向该Blob对象的临时URL。
  • 创建一个<a>标签,并设置其href属性为临时URL,同时设置download属性为自定义的文件名。
  • 通过模拟点击事件触发文件下载。
  • 使用setTimeout来延迟调用URL.revokeObjectURL,以释放由createObjectURL创建的资源。

为什么使用Blob URL来修改文件名?

  • 文件名控制:通过这种方式,我们可以自由地设置下载文件的名称,而不仅仅是依赖服务器返回的文件名。
  • 跨域安全:使用Blob URL可以避免跨域问题,因为它是基于客户端的,不涉及服务器端的直接通信。
  • 即时下载:这种方法可以立即触发下载,无需等待服务器响应。
  • 资源管理:使用URL.createObjectURLURL.revokeObjectURL可以有效地管理临时URL资源,防止内存泄漏。

这种方法适用于需要即时生成文件并提供给用户下载的应用场景,特别是当文件名需要动态生成时。