npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

@wisdomgarden/cloak-plugin-file-transfer

v0.0.1

Published

A FileTransfer Plugin of Cloak framework(A Hybrid Development Framework for HarmonyOS)

Readme

中文版 | English Version

FileTransfer 插件

用于在 Cloak 应用中下载、上传文件,过程中按需上报进度。落盘范围限于应用自己的沙箱,需要声明网络权限。

安装

ohpm install @wisdomgarden/cloak-plugin-file-transfer

# 可选,用于 TypeScript 类型
npm install @wisdomgarden/cloak-plugin-file-transfer

entry/src/main/module.json5 中声明网络权限:

"requestPermissions": [
  {
    "name": "ohos.permission.INTERNET",
    "reason": "$string:permission_internet_reason",
    "usedScene": { "abilities": ["EntryAbility"], "when": "inuse" }
  }
]

EntryAbility.ets 中注册:

import { CloakPluginFileTransfer } from '@wisdomgarden/cloak-plugin-file-transfer';

onCreate(want: Want, launchParam: AbilityConstant.LaunchParam): void {
  const cloak = new Cloak(this);
  cloak.addPlugins([
    // ... 其他插件
    new CloakPluginFileTransfer()
  ]);
}

使用方法

const transfer = Cloak.plugins.FileTransfer;

// 落盘路径用 Filesystem 生成,两个插件都认 file:// 形态
const { uri } = await Cloak.plugins.Filesystem.getUri({ path: 'downloads/a.pdf', directory: 'DATA' });

// 订阅进度,payload 里的 id 用来区分是哪个任务
const handlerId = transfer.addEventListener('progress', (p) => {
  if (!p.lengthComputable) {
    console.log(p.id, `已传 ${p.bytes} 字节,总大小未知`);
    return;
  }
  console.log(p.id, `${Math.floor((p.bytes / p.contentLength) * 100)}%`);
});

// id 是取消句柄,由调用方自己起名,用目标路径或自己的业务 id 都行。
// 多个任务同时跑就一定要传 id:进度事件靠它认领,abort 也靠它定位。

// 下载,不传 progress 就不发进度事件
const result = await transfer.downloadFile({
  id: 'a.pdf',
  url: 'https://example.com/a.pdf',
  path: uri,
  progress: true,
  headers: { Authorization: 'Bearer ...' },
});
console.log(result.path); // file:///data/.../downloads/a.pdf

// 上传,默认 POST + multipart,文件字段名默认 file
const uploaded = await transfer.uploadFile({
  id: 'report',
  url: 'https://example.com/upload',
  path: uri,
  fileKey: 'attachment',
  data: { courseId: '42' },
  progress: true,
});
console.log(uploaded.responseCode, uploaded.response);

// 并发多个任务,进度事件靠 id 区分
await Promise.all([
  transfer.downloadFile({ id: 'first', url: url1, path: path1, progress: true }),
  transfer.downloadFile({ id: 'second', url: url2, path: path2, progress: true }),
]);

// 取消单个任务,被取消的那个 Promise 以 OS-PLUG-FLTR-0012 拒绝
await transfer.abort({ id: 'first' });

// 不传 id 则取消全部在传任务
await transfer.abort();

transfer.removeEventListener('progress', handlerId);

// 失败时 reject 一个带 code 的错误
try {
  await transfer.downloadFile({ url: 'https://example.com/nope', path: uri });
} catch (e) {
  console.error(e.code, e.httpStatus, e.body); // OS-PLUG-FLTR-0010 404 ...
}

API

方法失败时 reject 的错误见错误码

downloadFile

downloadFile(options: DownloadFileOptions): Promise<DownloadFileResult>;

下载文件到指定路径,目标的父目录缺失时自动创建。

| 参数 | 类型 | 必填 | 说明 | |---|---|---|---| | options | DownloadFileOptions | 是 | 下载参数 |

返回值Promise<DownloadFileResult>


uploadFile

uploadFile(options: UploadFileOptions): Promise<UploadFileResult>;

以 multipart 表单上传文件,源文件必须已存在。

| 参数 | 类型 | 必填 | 说明 | |---|---|---|---| | options | UploadFileOptions | 是 | 上传参数 |

返回值Promise<UploadFileResult>


abort

abort(options?: AbortOptions): Promise<void>;

取消在传的任务。传 id 只取消那一个,不传则全部取消。被取消的任务各自以 OS-PLUG-FLTR-0012 拒绝。取消一个并不在传的任务不算错误。

下载和上传的"取消"含义不同:取消下载是干净的——写了一半的文件被删掉,目标路径上原有的文件不受影响,等同于这次下载没发生过。取消上传只是断开连接,已经发出去的那部分请求体,服务端留不留、算不算一次失败的提交,插件既不知道也无法回滚,更不会替你去调撤销接口。要做到"取消即无痕",需要服务端配合(分片上传 + 显式 commit,或者取消后自行调用删除接口)。

| 参数 | 类型 | 必填 | 说明 | |---|---|---|---| | options | AbortOptions | 否 | 要取消的任务 |

返回值Promise<void>

接口

DownloadFileOptions

| 字段 | 类型 | 必填 | 默认值 | 说明 | |---|---|---|---|---| | url | string | 是 | — | 下载地址 | | path | string | 是 | — | 落盘路径,file:// uri 与绝对沙箱路径都收。同一个 path 不能同时有两个下载在传,后来的直接失败 | | id | string | 否 | — | 取消句柄,自己起名(目标路径、业务 id 都行)。进度事件回显它,abort 按它定位。不传则只能被 abort() 全量取消;同一个 id 还在传时再发起会失败 | | progress | boolean | 否 | false | 是否上报进度 | | method | string | 否 | 'GET' | 请求方法,只接受 GET / POSTHEADOPTIONS 按定义不返回响应体,会落一个空文件,所以直接拒绝 | | params | Record<string, string | string[]> | 否 | — | 拼到 URL 查询串,数组值展开成重复的 key | | headers | Record<string, string> | 否 | — | 请求头 | | overwrite | boolean | 否 | true | 目标文件已存在时是否覆盖,关掉则改为失败 | | connectTimeout | number | 否 | 60000 | 建立连接的超时,毫秒 | | readTimeout | number | 否 | 60000 | 传输中等待下一段数据的超时,毫秒,每次收到数据后重新计时 | | shouldEncodeUrlParams | boolean | 否 | true | 是否对 params 做百分号编码,值已编码过时关掉,避免二次编码 |

DownloadFileResult

| 字段 | 类型 | 说明 | |---|---|---| | path | string | 落盘文件的完整 uri,以 file:// 开头 |

UploadFileOptions

| 字段 | 类型 | 必填 | 默认值 | 说明 | |---|---|---|---|---| | url | string | 是 | — | 上传地址 | | path | string | 是 | — | 待上传的文件,file:// uri 与绝对沙箱路径都收,文件必须存在。同一个文件可以同时传给多个地址 | | id | string | 否 | — | 取消句柄,规则同下载 | | progress | boolean | 否 | false | 是否上报进度 | | method | string | 否 | 'POST' | 请求方法,只接受 POST / PUT(S3 预签名、WebDAV 用 PUT)| | params | Record<string, string | string[]> | 否 | — | 拼到 URL 查询串 | | headers | Record<string, string> | 否 | — | 请求头。multipart 的 Content-Type 由插件生成,自己覆盖会破坏请求体 | | fileKey | string | 否 | 'file' | 文件部分的表单字段名 | | fileName | string | 否 | path 的最后一段 | 文件部分的文件名 | | mimeType | string | 否 | — | 文件部分的类型,从文件名推断不出来时才用得上 | | data | Record<string, string> | 否 | — | 同一个表单里附带的文本字段 | | connectTimeout | number | 否 | 60000 | 建立连接的超时,毫秒 | | readTimeout | number | 否 | 60000 | 传输中等待下一段数据的超时,毫秒,每次收到数据后重新计时 | | shouldEncodeUrlParams | boolean | 否 | true | 是否对 params 做百分号编码 |

UploadFileResult

| 字段 | 类型 | 说明 | |---|---|---| | bytesSent | number | 实际上传的字节数 | | responseCode | string | HTTP 状态码,字符串形式 | | response | string | 响应体,服务端给了才有 | | headers | Record<string, string> | 响应头,key 统一小写 |

AbortOptions

| 字段 | 类型 | 必填 | 说明 | |---|---|---|---| | id | string | 否 | 要取消的任务标识,不传则取消全部在传任务 |

ProgressStatus

progress 事件的 payload。

| 字段 | 类型 | 必填 | 说明 | |---|---|---|---| | id | string | 否 | 发起时传的 id,没传就没有。多任务并发时靠它认领,别指望用其它字段替代 | | type | 'download' \| 'upload' | 是 | 这条进度属于下载还是上传 | | url | string | 是 | 传输涉及的地址 | | path | string | 是 | 发起时传的 path原样回显,不做归一化。主要用于展示"正在传哪个文件"(签名 url 通常没法看) | | bytes | number | 是 | 已传字节数 | | contentLength | number | 是 | 总字节数,服务端没给时为 0 | | lengthComputable | boolean | 是 | contentLength 是否可信,服务端没给 Content-Length 时为 false |

FileTransferError

所有方法失败时 reject 的对象。

| 字段 | 类型 | 必填 | 说明 | |---|---|---|---| | code | string | 是 | 见错误码 | | message | string | 是 | 可读的失败原因 | | source | string | 否 | 数据来源:下载是 url,上传是文件路径 | | target | string | 否 | 数据去向:下载是文件路径,上传是 url | | httpStatus | number | 否 | 服务端状态码,请求走到那一步才有 | | headers | Record<string, string> | 否 | 响应头 | | body | string | 否 | 错误响应体 | | exception | string | 否 | 鸿蒙侧的原始错误信息 |

事件

addEventListener 订阅,返回的 handler id 可以传给 removeEventListener 精确移除;不传 id 则移除该事件的全部 handler。

| 事件 | payload | 说明 | |---|---|---| | progress | ProgressStatus | 只有 progress: true 的任务才发。每个任务各自 100ms 节流一次,完成时补发一次全量;多个任务并发时靠 payload 里的 id 区分,所以并发场景务必给每个任务传 id |

错误码

| code | 说明 | |---|---| | OS-PLUG-FLTR-0004 | 参数非法:缺 url/path,或 id 与在传任务重名,或下载的目标 path 已被在传任务占用 | | OS-PLUG-FLTR-0005 | URL 为空或解析不了 | | OS-PLUG-FLTR-0006 | 网络权限被拒,通常是没声明 ohos.permission.INTERNET | | OS-PLUG-FLTR-0007 | 上传的源文件不存在 | | OS-PLUG-FLTR-0008 | 连接不上服务器 | | OS-PLUG-FLTR-0009 | 服务端返回 HTTP 304,检查与缓存相关的请求头 | | OS-PLUG-FLTR-0010 | 其余 HTTP 错误,httpStatus / headers / body 里带响应详情 | | OS-PLUG-FLTR-0011 | 其余失败,exception 里带鸿蒙原始错误 | | OS-PLUG-FLTR-0012 | 任务被 abort 取消 | | OS-PLUG-FLTR-0013 | 文件读写被拒(沙箱外的路径、或没有权限的目录),message 里带出错路径 |

关于 Cloak

Cloak 是专为 HarmonyOS 设计的混合开发框架,类似 CordovaCapacitor,但具备 更轻量更高性能 的特性。

该框架可将 Web 应用快速转换为原生应用,同时通过插件机制访问 HarmonyOS 原生能力。

核心特性

  • 快速打包:将 H5 应用快速编译为 HarmonyOS 应用。
  • 原生能力访问:通过插件机制调用原生接口。
  • WebView 支持:提供高性能 WebView 容器,确保 H5 应用流畅运行。
  • 插件开发:支持开发者自定义插件以扩展原生功能。

更多关于 Cloak 框架信息,请查看: https://github.com/WisdomGardenInc/Cloak