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

如何在React(Next.js)客户端浏览器中检查本地文件是否存在

浏览器端音频文件本地存在性检查方案

因为浏览器环境无法直接访问本地文件系统,你可以通过以下几种客户端存储方案实现需求:

方案1:使用IndexedDB存储并检查音频文件

IndexedDB是浏览器原生的大容量存储方案,适合持久化二进制音频文件,支持按唯一标识检索。

实现步骤

  1. 封装IndexedDB操作工具类,包含文件检查、存储、读取方法
  2. 调用API前,通过音频文件的唯一标识(比如API返回的文件ID、文件名)查询IndexedDB
  3. 存在则直接读取本地文件,不存在则请求API并将文件存入IndexedDB

示例代码

// 封装IndexedDB操作类
class AudioLocalStorage {
  constructor() {
    this.dbName = 'AudioStoreDB';
    this.storeName = 'audioFiles';
    this.dbInstance = null;
    this.initDB();
  }

  initDB() {
    return new Promise((resolve, reject) => {
      const request = indexedDB.open(this.dbName, 1);
      
      request.onupgradeneeded = (e) => {
        this.dbInstance = e.target.result;
        if (!this.dbInstance.objectStoreNames.contains(this.storeName)) {
          this.dbInstance.createObjectStore(this.storeName, { keyPath: 'fileId' });
        }
      };

      request.onsuccess = (e) => {
        this.dbInstance = e.target.result;
        resolve();
      };

      request.onerror = (e) => reject(e.target.error);
    });
  }

  // 检查文件是否存在
  async isFileExist(fileId) {
    await this.initDB();
    return new Promise((resolve) => {
      const transaction = this.dbInstance.transaction(this.storeName, 'readonly');
      const store = transaction.objectStore(this.storeName);
      const request = store.get(fileId);

      request.onsuccess = () => resolve(!!request.result);
      request.onerror = () => resolve(false);
    });
  }

  // 存储音频Blob
  async saveAudio(fileId, audioBlob) {
    await this.initDB();
    return new Promise((resolve, reject) => {
      const transaction = this.dbInstance.transaction(this.storeName, 'readwrite');
      const store = transaction.objectStore(this.storeName);
      const request = store.put({ fileId, blob: audioBlob });

      request.onsuccess = () => resolve();
      request.onerror = (e) => reject(e.target.error);
    });
  }

  // 获取本地音频Blob
  async getAudio(fileId) {
    await this.initDB();
    return new Promise((resolve, reject) => {
      const transaction = this.dbInstance.transaction(this.storeName, 'readonly');
      const store = transaction.objectStore(this.storeName);
      const request = store.get(fileId);

      request.onsuccess = () => resolve(request.result?.blob);
      request.onerror = (e) => reject(e.target.error);
    });
  }
}

// 在Next.js客户端组件中使用
const audioStorage = new AudioLocalStorage();

async function loadAudio(fileId, apiEndpoint) {
  const exists = await audioStorage.isFileExist(fileId);
  if (exists) {
    const blob = await audioStorage.getAudio(fileId);
    return URL.createObjectURL(blob);
  } else {
    // 调用API获取音频
    const res = await fetch(apiEndpoint);
    const blob = await res.blob();
    await audioStorage.saveAudio(fileId, blob);
    return URL.createObjectURL(blob);
  }
}

方案2:使用Cache API(适配PWA场景)

如果你的网站是PWA,Cache API可以配合Service Worker自动缓存API响应,实现请求级别的缓存检查。

示例代码(Service Worker)

const AUDIO_CACHE_NAME = 'audio-cache-v1';
const AUDIO_API_PREFIX = '/api/audio/'; // 匹配你的音频API路径

self.addEventListener('fetch', (event) => {
  if (event.request.url.includes(AUDIO_API_PREFIX)) {
    event.respondWith(
      caches.match(event.request).then(cachedRes => {
        // 优先返回缓存,无缓存则请求网络并缓存
        return cachedRes || fetch(event.request).then(networkRes => {
          caches.open(AUDIO_CACHE_NAME).then(cache => {
            cache.put(event.request, networkRes.clone());
          });
          return networkRes;
        });
      })
    );
  }
});

注意事项

  • 确保API请求URL是唯一标识音频文件的(比如带fileId参数)
  • 可通过更新缓存版本号清理旧缓存

方案3:LocalStorage存储文件元数据(辅助检查)

LocalStorage适合存储小体积的文件标识(如文件ID、哈希值),快速判断是否需要请求API,音频文件本身仍存在IndexedDB或Cache中。

实现思路

  1. 首次获取音频后,将文件ID存入LocalStorage
  2. 下次请求前先检查LocalStorage中是否有对应ID
  3. 有记录则读取本地存储的文件,无则调用API

通用注意事项

  • 浏览器存储有配额限制,需处理存储满的异常情况
  • 可给存储的文件添加过期时间,定期清理无效文件
  • Next.js中需在客户端组件内执行这些逻辑(比如用useEffect触发)

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.21 03:55:19