一个Capacitor应用的最佳cordova-plugin-file-transfer替代方案取决于一个问题:传输是否需要在应用切换到后台时继续? @capacitor/file-transfer 对于正常的上传和下载,带有进度的使用官方 @capgo/capacitor-uploader and @capgo/capacitor-downloader本指南将比较并映射这些插件,帮助您选择合适的替代方案。 FileTransfer call.
是否 Cordova-plugin-file-transfer 还处于弃用状态?
历史混乱,所以这里是事实:
- 2017 年,Apache Cordova 团队宣布计划弃用该插件并指向
XMLHttpRequest级别 2。 - The plugin was never flagged as deprecated on npm. Version 2.0.0 shipped in September 2023, and 2.0.1 in August 2026. The GitHub repository is active.
Capacitor 仓库仍然活跃。
- 依赖于
cordova-plugin-file依赖于cdvfile://和其file://和 - 不符合Capacitor的
Filesystem目录和URI转换 - 没有后台传输支持
- 使用回调样式API
如果您正在从Cordova迁移,使用nativeCapacitor插件替换它,会消除您保持 cordova-plugin-file.
为什么“只使用fetch”在大文件上会失败
Apache建议的替代方案,XHR,适用于小JSON和图片。它在混合应用中进行真正的文件传输工作时失败:
- 内存。
fetch或Blob在WebView中ArrayBuffer在WebView中500MB的视频意味着500MB的WebView内存,然后通过桥接写入。中档Android设备的渲染器会崩溃。 - 暂停。 当用户切换应用时,iOS会暂停WebView。在飞行中的请求会卡住或失败。
- 没有OS集成。 没有系统下载通知,没有Wi-Fi仅选项,没有断开连接后恢复。
原生插件直接在磁盘和网络之间流动,JavaScript被排除在数据路径之外。
比较的选项
| 需要 | cordova-plugin-file-transfer | @capacitor/文件传输 | @capgo/capacitor-上传工具 | @capgo/capacitor下载器 |
|---|---|---|---|---|
| 下载到磁盘 | 是 | 是 | 否 | 是 |
| 从磁盘上传 | 是 | 是 | 是 | 否 |
| 进度事件 | 是 | 是(progress 监听器) |
Yes (events) |
Yes (downloadProgress) |
| 多部分表单数据 | Yes | 是 (默认) | Yes | 无 |
| 原始二进制 PUT (预签名 URL) | Yes | 是 (设置 Content-Type) |
Yes (uploadType: 'binary') |
无 |
| 多个文件在一个请求中 | 否 | 否 | 是(files) |
n/a |
| 取消 | abort() |
否 | removeUpload |
stop |
| 暂停/恢复 | 否 | 否 | 否 | pause, resume |
| 重试 | 否 | 否 | maxRetries |
否 |
| 继续在后台 | 否 | 应用程序处于活动状态 | 是 | 是 |
| 仅 Wi-Fi | 否 | 否 | 否 | network: 'wifi-only' |
| HTTP错误详细信息 | http_status, body |
httpStatus, body |
状态code在事件中 | 错误字符串在事件中 |
| Web实现 | 否 | 是 | 是(基于fetch) | 否 |
大多数应用最终会使用 @capacitor/file-transfer 用于小型用户可见传输和Capgo插件的媒体上传队列和离线内容下载。
选项1:@capacitor/file-transfer
bun add @capacitor/file-transfer @capacitor/filesystem
bunx cap sync
该插件需要一个完整的本机路径。从 @capacitor/filesystem.
下载
import { FileTransfer } from '@capacitor/file-transfer';
import { Filesystem, Directory } from '@capacitor/filesystem';
export async function downloadReport(url: string) {
const { uri } = await Filesystem.getUri({
directory: Directory.Data,
path: 'reports/latest.pdf',
});
const progress = await FileTransfer.addListener('progress', (p) => {
if (p.type === 'download' && p.lengthComputable) {
console.log(`Downloaded ${Math.round((p.bytes / p.contentLength) * 100)}%`);
}
});
try {
const result = await FileTransfer.downloadFile({
url,
path: uri,
progress: true,
headers: { Authorization: 'Bearer <token>' },
});
return result.path;
} catch (error: any) {
if (error.code === 'OS-PLUG-FLTR-0010') {
console.error('HTTP error', error.data?.httpStatus, error.data?.body);
}
throw error;
} finally {
await progress.remove();
}
}
上传
export async function uploadAvatar(path: string) {
const result = await FileTransfer.uploadFile({
url: 'https://api.example.com/v1/avatar',
path,
fileKey: 'avatar',
mimeType: 'image/jpeg',
headers: { Authorization: 'Bearer <token>' },
progress: true,
});
console.log(result.responseCode, result.response);
}
上传默认为多部分。要将文件上传到一个预签名的S3 URL中,例如,设置 method: 'PUT' 并显式 Content-Type 头部,如 application/octet-stream.
错误代码遵循 OS-PLUG-FLTR-XXXX 格式。有用的错误代码包括: 0007 文件未找到 0008 连接失败 0010 HTTP错误状态码 httpStatus 和 body 在 error.data.
选项 2:使用@capgo/capacitor-uploader进行后台上传
bun add @capgo/capacitor-uploader
bunx cap sync
import { Uploader } from '@capgo/capacitor-uploader';
await Uploader.addListener('events', async (event) => {
switch (event.name) {
case 'uploading':
console.log(event.id, `${event.payload.percent}%`);
break;
case 'completed':
console.log(event.id, 'done', event.payload.statusCode);
break;
case 'failed':
console.error(event.id, event.payload.error);
break;
}
// Completed and failed events are cached natively until acknowledged
if (event.eventId) {
await Uploader.acknowledgeEvent({ eventId: event.eventId });
}
});
const { id } = await Uploader.startUpload({
filePath: 'file:///path/to/video.mp4',
serverUrl: 'https://api.example.com/v1/videos',
method: 'POST',
uploadType: 'multipart',
fileField: 'video',
parameters: { albumId: '7' },
headers: { Authorization: 'Bearer <token>' },
maxRetries: 3,
notificationTitle: 'Uploading video', // Android only
});
对于预签名 URL,请使用 method: 'PUT', 默认为二进制体:
await Uploader.startUpload({
filePath,
serverUrl: presignedUrl,
method: 'PUT',
headers: { 'Content-Type': 'video/mp4' },
mimeType: 'video/mp4',
});
多个文件在一个多部分请求中:
await Uploader.startUpload({
serverUrl: 'https://api.example.com/v1/photos',
method: 'POST',
uploadType: 'multipart',
files: [
{ filePath: photo1, fieldName: 'images[]', mimeType: 'image/jpeg' },
{ filePath: photo2, fieldName: 'images[]', mimeType: 'image/jpeg' },
],
headers: { Authorization: 'Bearer <token>' },
});
取消 Uploader.removeUpload({ id }).
为什么确认事件? 已完成和失败的事件存储在一个持久的本机缓存中,因此它们可以在应用程序关闭或后台之前处理它们之前重新传递。如果确认事件,则会移除事件,因此下次插件初始化时不会重新广播。
iOS 设置。 上传器使用后台 URLSession. 许多应用程序不需要额外的设置。如果上传必须在应用程序被挂起后继续,请添加 fetch 到 UIBackgroundModes。不要添加 processing 除非另一个功能使用 BGTaskScheduler, 因为 App Store Connect 拒绝声明它而没有 BGTaskSchedulerPermittedIdentifiers.
选项 3:使用 @capgo/capacitor-downloader 进行后台下载
bun add @capgo/capacitor-downloader
bunx cap sync
import { CapacitorDownloader } from '@capgo/capacitor-downloader';
await CapacitorDownloader.addListener('downloadProgress', ({ id, progress }) => {
console.log(id, `${progress}%`);
});
await CapacitorDownloader.addListener('downloadCompleted', ({ id }) => {
console.log(id, 'completed');
});
await CapacitorDownloader.addListener('downloadFailed', ({ id, error }) => {
console.error(id, error);
});
await CapacitorDownloader.download({
id: 'course-42',
url: 'https://cdn.example.com/courses/42.zip',
destination: 'courses/42.zip',
headers: { Authorization: 'Bearer <token>' },
network: 'wifi-only',
priority: 'normal',
notification: 'progress', // Android: remove the system notification when done
});
// Later
await CapacitorDownloader.pause({ id: 'course-42' });
await CapacitorDownloader.resume({ id: 'course-42' });
const status = await CapacitorDownloader.checkStatus({ id: 'course-42' });
console.log(status.state, status.progress);
一个相对路径 destination 指向 iOS 应用程序的文档目录和 Android 应用程序的外部文件目录。您还可以传递一个绝对路径或一个 file:// 使用 getFileInfo({ path }) 读取大小和 MIME 类型后下载,并 stop({ id }) 取消和删除部分数据。
从 cordova-plugin-file-transfer 迁移
下载
// Before
const ft = new FileTransfer();
ft.onprogress = (e) => e.lengthComputable && setProgress(e.loaded / e.total);
ft.download(
encodeURI(url),
cordova.file.dataDirectory + 'report.pdf',
(entry) => console.log(entry.toURL()),
(err) => console.error(err.code, err.http_status),
false,
{ headers: { Authorization: 'Bearer <token>' } },
);
// After
const { uri } = await Filesystem.getUri({ directory: Directory.Data, path: 'report.pdf' });
await FileTransfer.downloadFile({
url,
path: uri,
progress: true,
headers: { Authorization: 'Bearer <token>' },
});
上传
// Before
const options = new FileUploadOptions();
options.fileKey = 'file';
options.fileName = 'photo.jpg';
options.mimeType = 'image/jpeg';
options.params = { albumId: '7' };
options.headers = { Authorization: 'Bearer <token>' };
new FileTransfer().upload(fileUrl, encodeURI(serverUrl), onSuccess, onError, options);
// After, foreground
await FileTransfer.uploadFile({
url: serverUrl,
path: fileUrl,
fileKey: 'file',
mimeType: 'image/jpeg',
params: { albumId: '7' },
headers: { Authorization: 'Bearer <token>' },
});
// After, background
await Uploader.startUpload({
filePath: fileUrl,
serverUrl,
uploadType: 'multipart',
fileField: 'file',
parameters: { albumId: '7' },
headers: { Authorization: 'Bearer <token>' },
});
注意 params In @capacitor/file-transfer 是 URL 查询参数。如果您的服务器期望表单字段,请使用 Capgo 上传器的 parameters,它们将以多部分表单字段发送。
映射表
| cordova-plugin-file-transfer | @capacitor/文件传输 | Capgo 插件 |
|---|---|---|
download(source, target, ...) |
downloadFile({ url, path }) |
CapacitorDownloader.download({ id, url, destination }) |
upload(file, server, ...) |
uploadFile({ url, path }) |
Uploader.startUpload({ filePath, serverUrl }) |
onprogress |
addListener('progress') |
addListener('events') / addListener('downloadProgress') |
abort() |
不可用 | removeUpload({ id }) / stop({ id }) |
options.fileKey |
fileKey |
fileField 或 files[].fieldName |
options.params |
params (查询字符串) |
parameters (表单字段) |
options.httpMethod |
method |
method (POST 或 PUT) |
options.chunkedMode |
chunkedMode |
本地处理 |
cordova.file.dataDirectory |
Filesystem.getUri({ directory: Directory.Data }) |
相对路径或 file:// URL |
FileTransferError.http_status |
error.data.httpStatus |
event.payload.statusCode |
路径:导致迁移中断的部分
Cordova code 支持 cdvfile:// 或 cordova.file.* 路径到处都是。 在 Capacitor 中:
- 从本地获取路径
Filesystem.getUri()或从创建文件的插件(摄像头、文件选择器、录音器)中获取 - 要在 WebView 中显示下载的图像,使用 __CAPGO_KEEP_0__ 将本地路径转换为
Capacitor.convertFileSrc(path). - Capgo 有一个 文件插件 and a 文件选择器 如果
@capacitor/filesystem不适用于您的场景。
故障排除
Android 上的上传功能正常,但在 iOS 上会出现找不到文件的错误。 上传在 Android 上工作,但在 iOS 上失败,显示文件未找到错误。 capacitor:// 您传递了 file:// WebView URL 而不是一个本机 Filesystem.getUri().
路径。使用来自 服务器拒绝上传,返回 415。 PUT 多部分 vs raw 体积不匹配。对于预签名 URL 使用一个明确的 Content-Type.
iOS背景上传停止。 用户强制关闭了应用程序,这会取消背景会话,或者 fetch 背景模式在您需要它时缺失。
Android显示下载通知卡住。 设置 notification: 'progress' 或 'hidden' 在下载器上
iOS背景上传停止。 您仍然使用 fetch 或通过桥接读取文件作为base64。切换到本机下载到磁盘。
将迁移
交换本机插件需要一个新的商店构建,这 Capgo 构建 可以在 iOS 和 Android 中运行云端。 之后,驱动上传和下载的 JavaScript 可以通过 Capgo 实时更新. 对于 Cordova 的其余部分Capacitor 移动,请参见我们的 迁移指南,以及其他付费或遗留本机 SDK 的 Ionic 企业插件替代方案.