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

Angular集成DuckDB-Wasm无法加载查询Parquet文件求助

在Angular中使用DuckDB-Wasm加载Parquet文件时"找不到文件"错误的解决方法

我在Angular中尝试用DuckDB-Wasm加载并查询Parquet文件,已经成功建立连接,但加载文件时触发以下错误:

Error: Uncaught (in promise): Error: IO Error: No files found that match the pattern "test.parquet" Error: IO Error: No files found that match the pattern "test.parquet" at O.onMessage (duckdb-browser.mjs:1:11169) at _ZoneDelegate.invokeTask (zone.js:402:31) at core.mjs:10757:55 at AsyncStackTaggingZoneSpec.onInvokeTask (core.mjs:10757:36) at _ZoneDelegate.invokeTask (zone.js:401:60) at Object.onInvokeTask (core.mjs:11070:33) at _ZoneDelegate.invokeTask (zone.js:401:60) at Zone.runTask (zone.js:173:47) at ZoneTask.invokeTask [as invoke] (zone.js:483:34) at invokeTask (zone.js:1631:18) at resolvePromise (zone.js:1193:31) at zone.js:1100:17 at zone.js:1116:33 at asyncGeneratorStep (asyncToGenerator.js:6:1) at _throw (asyncToGenerator.js:25:1) at _ZoneDelegate.invoke (zone.js:368:26) at Object.onInvoke (core.mjs:11083:33) at _ZoneDelegate.invoke (zone.js:367:52) at Zone.run (zone.js:129:43) at zone.js:1257:36

我的服务代码如下:

import { Injectable } from '@angular/core';
import * as duckdb from '@duckdb/duckdb-wasm';
@Injectable({
providedIn: 'root',
})
export class DuckdbService {
constructor() {
this.makeConnection();
}
async makeConnection() {
const JSDELIVR_BUNDLES = duckdb.getJsDelivrBundles();
// Select a bundle based on browser checks
const bundle = await duckdb.selectBundle(JSDELIVR_BUNDLES);

const worker_url = URL.createObjectURL(
  new Blob([`importScripts("${bundle.mainWorker}");`], {
    type: 'text/javascript',
  })
);

// Instantiate the asynchronus version of DuckDB-Wasm
const worker = new Worker(worker_url);
const logger = new duckdb.ConsoleLogger();
const db = new duckdb.AsyncDuckDB(logger, worker);
await db.instantiate(bundle.mainModule, bundle.pthreadWorker);
console.log(db);
const conn = await db.connect();
const results = conn.query(`SELECT * FROM read_parquet('test.parquet')`);
console.log(results);
URL.revokeObjectURL(worker_url);
}
}

问题核心原因

DuckDB-Wasm运行在浏览器沙箱环境中,无法直接访问本地文件系统或Angular项目中的文件路径。你直接传入的test.parquet字符串没有指向任何DuckDB可识别的虚拟文件系统位置,因此触发找不到文件的错误。同时原代码中conn.query缺少await,会导致异步操作未正确处理。

解决方法

1. 加载用户上传的本地Parquet文件

通过浏览器文件上传控件获取用户本地的Parquet文件,再将其注册到DuckDB的虚拟文件系统中:

修改后的服务代码

import { Injectable } from '@angular/core';
import * as duckdb from '@duckdb/duckdb-wasm';

@Injectable({
  providedIn: 'root',
})
export class DuckdbService {
  private db: duckdb.AsyncDuckDB | null = null;
  private conn: duckdb.AsyncDuckDBConnection | null = null;

  constructor() {
    this.initDuckDB();
  }

  // 单独封装初始化逻辑,避免构造函数异步调用问题
  async initDuckDB() {
    const JSDELIVR_BUNDLES = duckdb.getJsDelivrBundles();
    const bundle = await duckdb.selectBundle(JSDELIVR_BUNDLES);

    const worker_url = URL.createObjectURL(
      new Blob([`importScripts("${bundle.mainWorker}");`], {
        type: 'text/javascript',
      })
    );

    const worker = new Worker(worker_url);
    const logger = new duckdb.ConsoleLogger();
    this.db = new duckdb.AsyncDuckDB(logger, worker);
    await this.db.instantiate(bundle.mainModule, bundle.pthreadWorker);
    this.conn = await this.db.connect();
    URL.revokeObjectURL(worker_url);
  }

  async loadAndQueryUserFile(file: File) {
    if (!this.db || !this.conn) {
      throw new Error('DuckDB连接未初始化完成');
    }

    // 将文件注册到DuckDB虚拟文件系统
    await this.db.registerFileHandle('test.parquet', file, duckdb.FileAccessMode.READ);
    // 异步执行查询并返回结果
    const results = await this.conn.query(`SELECT * FROM read_parquet('test.parquet')`);
    return results;
  }
}

配套组件代码

import { Component } from '@angular/core';
import { DuckdbService } from './duckdb.service';

@Component({
  selector: 'app-parquet-loader',
  template: `<input type="file" accept=".parquet" (change)="onFileSelected($event)">`,
})
export class ParquetLoaderComponent {
  constructor(private duckdbService: DuckdbService) {}

  async onFileSelected(event: Event) {
    const file = (event.target as HTMLInputElement).files?.[0];
    if (file) {
      try {
        const queryResults = await this.duckdbService.loadAndQueryUserFile(file);
        // 在这里处理查询结果,比如渲染到页面
        console.log('查询结果:', queryResults);
      } catch (err) {
        console.error('加载查询失败:', err);
      }
    }
  }
}

2. 加载Angular Assets目录中的Parquet文件

如果文件放在项目的assets目录下,需要先通过HTTP请求获取文件Blob,再注册到虚拟文件系统:

服务中添加加载Assets文件的方法

async loadAndQueryAssetsFile() {
  if (!this.db || !this.conn) {
    throw new Error('DuckDB连接未初始化完成');
  }

  // 从Assets目录获取文件
  const response = await fetch('assets/test.parquet');
  const blob = await response.blob();
  const file = new File([blob], 'test.parquet');

  // 注册并查询
  await this.db.registerFileHandle('test.parquet', file, duckdb.FileAccessMode.READ);
  const results = await this.conn.query(`SELECT * FROM read_parquet('test.parquet')`);
  return results;
}

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.21 17:02:17