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

如何从C++编译的WebAssembly代码中触发浏览器下载?

我一直希望不通过JavaScript端实现该需求,目前还未找到满意的方案。Fetch API看起来是不错的方向,但我还没找到在浏览器中触发下载zip文件的方法。

以下是Emscripten代码片段,但它看起来仅适用于某种本地文件场景:

#include <stdio.h>
#include <string.h>
#include <emscripten/fetch.h>

void downloadSucceeded(emscripten_fetch_t *fetch) {
  printf("Finished downloading %llu bytes from URL %s.\n", fetch->numBytes, fetch->url);
  // The data is now available at fetch->data[0] through fetch->data[fetch->numBytes-1];
  emscripten_fetch_close(fetch); // Free data associated with the fetch.
}

void downloadFailed(emscripten_fetch_t *fetch) {
  printf("Downloading %s failed, HTTP failure status code: %d.\n", fetch->url, fetch->status);
  emscripten_fetch_close(fetch); // Also free data on failure.
}

int main() {
  emscripten_fetch_attr_t attr;
  emscripten_fetch_attr_init(&attr);
  strcpy(attr.requestMethod, "GET");
  attr.attributes = EMSCRIPTEN_FETCH_LOAD_TO_MEMORY;
  attr.onsuccess = downloadSucceeded;
  attr.onerror = downloadFailed;
  emscripten_fetch(&attr, "myfile.dat");
}

解决方案

你可以通过在Emscripten的fetch成功回调中嵌入内联JS逻辑实现浏览器触发下载,不需要额外编写独立的前端JS代码,符合你不想在JS侧单独实现需求的预期,修改后的代码如下:

#include <stdio.h>
#include <string.h>
#include <emscripten/fetch.h>
#include <emscripten/em_asm.h>

void downloadSucceeded(emscripten_fetch_t *fetch) {
  printf("已完成从URL %s 下载%llu字节。\n", fetch->url, fetch->numBytes);
  // 内联JS逻辑触发浏览器下载,无需额外维护独立JS文件
  EM_ASM(
    {
      // 读取C侧传递的二进制数据、长度和文件名
      const uint8_t* data = $0;
      size_t dataLen = $1;
      const char* fileName = UTF8ToString($2);
      
      // 生成可下载的Blob对象,指定zip类型
      const blob = new Blob([new Uint8Array(Module.HEAPU8.buffer, data, dataLen)], { type: 'application/zip' });
      const objUrl = URL.createObjectURL(blob);
      
      // 创建临时a标签触发下载
      const downloadLink = document.createElement('a');
      downloadLink.href = objUrl;
      downloadLink.download = fileName;
      document.body.appendChild(downloadLink);
      downloadLink.click();
      
      // 异步清理临时资源
      setTimeout(() => {
        document.body.removeChild(downloadLink);
        URL.revokeObjectURL(objUrl);
      }, 0);
    },
    fetch->data,
    fetch->numBytes,
    "output.zip" // 可自定义下载保存的文件名
  );
  emscripten_fetch_close(fetch); // 释放fetch关联的内存数据
}

void downloadFailed(emscripten_fetch_t *fetch) {
  printf("下载 %s 失败,HTTP错误状态码:%d。\n", fetch->url, fetch->status);
  emscripten_fetch_close(fetch);
}

int main() {
  emscripten_fetch_attr_t attr;
  emscripten_fetch_attr_init(&attr);
  strcpy(attr.requestMethod, "GET");
  attr.attributes = EMSCRIPTEN_FETCH_LOAD_TO_MEMORY;
  attr.onsuccess = downloadSucceeded;
  attr.onerror = downloadFailed;
  emscripten_fetch(&attr, "your_target_file.zip"); // 替换为实际的zip文件请求地址
}

补充说明

  • 编译时直接使用常规emcc命令即可,不需要额外引入外部JS文件,所有逻辑都封装在C代码侧
  • 触发下载的逻辑符合浏览器安全规范,不会被常规的弹窗拦截规则拦截
  • 如果需要下载非zip格式的文件,只需要修改Blob的type参数和下载文件名后缀即可

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.30 13:54:01