HarmonyOS 鸿蒙Next中如何利用axios进行文件上传、下载?

HarmonyOS 鸿蒙Next中如何利用axios进行文件上传、下载? 请问各位大神,如何利用axios进行文件的上传、下载,我是小白一枚,请讲解细节,感谢,感谢!!!

7 回复

下载安装

ohpm install [@ohos](/user/ohos)/axios

【如何安装 OpenHarmony ohpm 包】

权限申请

【模块module.json5】

{
  "module" : {
    "requestPermissions":[
      {
        "name" : "ohos.permission.INTERNET",
      },
    ]
  }
}

具体使用可参考以下官方案例及说明,更为详细~

[【OpenHarmony三方库:@ohos/axios】](https://ohpm.openharmony.cn/#/cn/detail/@ohos%2Faxios)

【ohos_axios:git代码仓】

更多关于HarmonyOS 鸿蒙Next中如何利用axios进行文件上传、下载?的实战系列教程也可以访问 https://www.itying.com/category-93-b0.html


最近刚好也在做这个, 踩了各种坑也只简单实现了,

重点是相关api和npm上的axios不一样,

鸿蒙上传下载不支持流式传输处理,必须直接指定filePath,必须在内部私有目录里的文件路径,比如 context.cacheDir

文件上传

说明:在 Harmony/OpenHarmony 中,上传时常见问题是沙箱内的 uri 不能直接被服务器读取,要先把文件复制/移动到 app 的缓存/可访问路径再上传。下面给出两种通用方法。

A. 方法一 — 如果支持 FormData(简单,和浏览器环境一样)

import axios from '@ohos/axios';

// 假设 fileObj 是通过文件选择 API 得到的可被 FormData 识别的对象
export async function uploadWithFormData(fileObj: any) {
  const fd = new FormData();
  // `file` 名称按后端接口要求
  fd.append('file', fileObj, fileObj.name ?? 'upload.bin');

  const res = await axios.post('https://example.com/upload', fd, {
    headers: {
      // 注意:在不少运行时不需要手动设置 boundary;若需要,浏览器/环境会自动处理
      'Content-Type': 'multipart/form-data',
    },
    timeout: 60000,
  });
  return res.data;
}

B. 方法二 — 读取文件为二进制,然后直接上传(通用)

这个方法在平台受限(没有 FormData 支持或需要从沙箱路径转为缓存文件)时常用:先用文件 API 读取字节(ArrayBuffer / Buffer),然后以 application/octet-stream 或后端约定的 Content-Type 上传。

示例(读取应用目录的文件并上传):

// pages/upload.ets
import axios from '@ohos/axios';
import fs from '@ohos.file.fs';    // 官方文件操作模块(示例)
import { common } from '@ohos.abilityKit'; // 若需要获取 context
// 注:不同 SDK 版本 modules 名称可能有差别,请以你的 SDK 文档为准。

async function readFileToArrayBuffer(path: string): Promise<ArrayBuffer> {
  // 这里用同步 API 示例(可改成 stream)
  const fd = fs.openSync(path, fs.OpenMode.READ);
  const stat = fs.fstatSync(fd.fd);
  const len = stat.size;
  const buf = new ArrayBuffer(len);
  fs.readSync(fd.fd, buf, { offset: 0, length: len });
  fs.closeSync(fd.fd);
  return buf;
}

export async function uploadBinaryFile(filePath: string) {
  const dataBuffer = await readFileToArrayBuffer(filePath);
  const res = await axios.post('https://example.com/upload-bin', dataBuffer, {
    headers: {
      'Content-Type': 'application/octet-stream',
      'Content-Length': String(dataBuffer.byteLength),
      // 其他自定义头(如 token)...
    },
    timeout: 60000,
  });
  return res.data;
}

注意点:

  • 如果文件来自系统或"沙箱URI",可能需要先把它复制到 filesDir 或缓存目录,再读取上传(这是常见的兼容性解决方案)。
  • 对较大文件,建议使用流式上传(若 SDK/axios 适配支持),避免内存峰值。

文件下载(下载到应用目录)

常见需求:用 axios 下载二进制文件,保存到应用私有目录供回放 / 打开。

步骤:

  1. axios.get(url, { responseType: ‘arraybuffer’ })(或 stream,视适配而定)获取二进制。
  2. 使用平台文件 API 将内容写入到 filesDir(或缓存目录)。

示例:

import axios from '@ohos/axios';
import fs from '@ohos.file.fs';
import { common } from '@ohos.abilityKit';

// 假设你能拿到 ability context(视页面/ability 实现)
function getAppFilesDir(context: any): string {
  return context.filesDir || '/data/accounts/...'; // 仅示意,实际请用 context.filesDir
}

export async function downloadToFile(url: string, outFileName: string, context: any) {
  // 1) 下载二进制
  const resp = await axios.get(url, { responseType: 'arraybuffer', timeout: 60000 });
  const arrayBuffer = resp.data as ArrayBuffer;

  // 2) 写文件到应用目录
  const filesDir = getAppFilesDir(context);
  const fullPath = `${filesDir}/${outFileName}`;

  // 写入示例(简单同步写,真实项目请用分块/stream 写入以节省内存)
  const fd = fs.openSync(fullPath, fs.OpenMode.CREATE | fs.OpenMode.WRITE);
  fs.writeSync(fd.fd, arrayBuffer, { length: arrayBuffer.byteLength });
  fs.closeSync(fd.fd);

  return fullPath;
}

注意:

  • 使用 responseType: ‘arraybuffer’ 能在大多数环境中获得二进制,然后用文件 API 写入磁盘。若你看到 responseType: ‘blob’,那是浏览器风格(在 ArkTS 环境中可能不可用)。
  • 写入大文件时推荐使用文件流或分块下载(减少内存占用)。

常见问题 & 注意事项

  • 没有权限/网络失败:确认 ohos.permission.INTERNET 已声明并通过运行环境的权限检查。
  • 上传时后端收不到文件 / 文件为空:检查你是不是把沙箱 URI直接当文件路径上传了;很多情况下需要把系统 URI 复制到 app 的缓存/可访问路径(或使用平台提供的文件选择器获得可上传对象)。
  • 内存溢出:一次性读入整文件到内存(ArrayBuffer)适合中小文件;对于大文件请用流式读写(若 SDK/axios 适配支持)或分块上传/下载。
  • Content-Type 设置:对 FormData,通常不手动设置 Content-Type(因为 boundary 需要自动生成);对二进制上传,使用 application/octet-stream 或后端要求的类型。

上传文件:

当上传的内容为ArrayBuffer时,用法如下:

import axios from '@ohos/axios'
import { FormData } from '@ohos/axios'
import fs from '@ohos.file.fs';

// ArrayBuffer
let formData = new FormData()
let cacheDir = getContext(this).cacheDir
try {
  // 写入
  let path = cacheDir + '/hello.txt';
  let file = fs.openSync(path, fs.OpenMode.CREATE | fs.OpenMode.READ_WRITE)
  fs.writeSync(file.fd, "hello, world"); // 以同步方法将数据写入文件
  fs.fsyncSync(file.fd); // 以同步方法同步文件数据。
  fs.closeSync(file.fd);

  // 读取
  let file2 = fs.openSync(path, 0o2);
  let stat = fs.lstatSync(path);
  let buf2 = new ArrayBuffer(stat.size);
  fs.readSync(file2.fd, buf2); // 以同步方法从流文件读取数据。
  fs.fsyncSync(file2.fd);
  fs.closeSync(file2.fd);

  formData.append('file', buf2);
  // formData.append('file', buf2, { filename: 'text.txt', type: 'text/plain'}); 设置多部分表单数据的数据名称和数据类型类型
} catch (err) {
  console.info('err:' + JSON.stringify(err));
}
// 发送请求
axios.post<string, AxiosResponse<string>, FormData>(this.uploadUrl, formData, {
  headers: { 'Content-Type': 'multipart/form-data' },
  context: getContext(this),
  onUploadProgress: (progressEvent: AxiosProgressEvent): void => {
  console.info(progressEvent && progressEvent.loaded && progressEvent.total ? Math.ceil(progressEvent.loaded / progressEvent.total * 100) + '%' : '0%');
},
}).then((res: AxiosResponse) => {
  console.info("result" + JSON.stringify(res.data));
}).catch((error: AxiosError) => {
  console.error("error:" + JSON.stringify(error));
})

当上传的uri时,用法如下:

import axios from '@ohos/axios'
import { FormData } from '@ohos/axios'

let formData = new FormData()
formData.append('file', 'internal://cache/blue.jpg')
// formData.append('file', cacheDir + '/hello.txt'); uri支持传入沙箱路径

// 发送请求
axios.post<string, AxiosResponse<string>, FormData>('https://www.xxx.com/upload', formData, {
  headers: { 'Content-Type': 'multipart/form-data' },
  context: getContext(this),
  onUploadProgress: (progressEvent: AxiosProgressEvent): void => {
    console.info(progressEvent && progressEvent.loaded && progressEvent.total ? Math.ceil(progressEvent.loaded / progressEvent.total * 100) + '%' : '0%');
  },
}).then((res: AxiosResponse<string>) => {
  console.info("result" + JSON.stringify(res.data));
}).catch((err: AxiosError) => {
  console.error("error:" + JSON.stringify(err));
})

下载文件:

FormData对象是axios内部自定义的类型,用以将数据编译成键值对,以便用来发送数据。其主要用于发送表单数据,但亦可用于发送带键数据 (keyed data)。

import { FormData } from '@ohos/axios'

let formData: FormData = new FormData();

formData.append("username", "Groucho");
formData.append("accountnum", "123456");
formData.append("accountnum", "123456");
formData.append("file", "internal://cache/xx/file.txt", { filename: "text.txt", type: "text/plain"});

上面的示例创建了一个 FormData 实例,包含"username"、"accountnum"字段。使用 append() 方法时,可以通过第三个可选参数设置多部分表单数据的数据名称和数据类型

下载文件示例:

1、设置下载路径filePath(默认在’internal://cache/'路径下)。

2、当前版本只支持 Stage 模型,使用AbilityContext 类获取文件路径。

3、下载文件时,如果filePath已存在该文件则下载失败,下载之前需要先删除文件

4、不支持自动创建目录,若下载路径中的目录不存在,则下载失败。

let filePath = getContext(this).cacheDir + '/blue.jpg'
// 下载。如果文件已存在,则先删除文件。
try {
  fs.accessSync(filePath);
  fs.unlinkSync(filePath);
} catch(err) {}

axios({
  url: 'https://www.xxx.com/blue.jpg',
  method: 'get',
  filePath: filePath ,
  onDownloadProgress: (progressEvent: AxiosProgressEvent): void => {
    console.info("progress: " + progressEvent && progressEvent.loaded && progressEvent.total ? Math.ceil(progressEvent.loaded / progressEvent.total * 100) : 0)
  }
}).then((res)=>{
  console.info("result: " + JSON.stringify(res.data));
}).catch((error)=>{
  console.error("error:" + JSON.stringify(error));
})

在HarmonyOS Next中,可通过axios库实现文件上传与下载。上传文件时,使用FormData对象封装文件数据,通过axios.post方法发送multipart/form-data请求。下载文件时,调用axios.get获取文件流,结合文件管理接口保存至本地。需注意配置请求头中的Content-Type,并处理响应数据格式。具体实现需参考鸿蒙官方文档中关于网络请求和文件操作的API。

在HarmonyOS Next中,可以通过axios结合文件API实现文件上传和下载功能。以下是具体实现方法:

文件上传

  1. 使用@ohos.file.fs模块读取本地文件
  2. 通过FormData构造表单数据
  3. 配置axios请求头为multipart/form-data
  4. 发送POST请求

示例代码:

import axios from '@ohos/axios';
import fs from '@ohos/file.fs';

async function uploadFile(fileUri) {
  const file = fs.openSync(fileUri, fs.OpenMode.READ_ONLY);
  const stat = await fs.stat(fileUri);
  const buffer = new ArrayBuffer(stat.size);
  fs.readSync(file.fd, buffer);
  
  const formData = new FormData();
  formData.append('file', new Blob([buffer]));
  
  const config = {
    headers: {
      'Content-Type': 'multipart/form-data'
    }
  };
  
  return axios.post('/upload', formData, config);
}

文件下载

  1. 发送GET请求获取文件数据
  2. 使用@ohos.file.fs保存文件到本地
  3. 设置responseType为’arraybuffer’

示例代码:

async function downloadFile(url, savePath) {
  const response = await axios.get(url, {
    responseType: 'arraybuffer'
  });
  
  const file = fs.openSync(savePath, fs.OpenMode.CREATE | fs.OpenMode.READ_WRITE);
  fs.writeSync(file.fd, response.data);
  fs.closeSync(file);
}

注意:需要申请ohos.permission.READ_MEDIA和ohos.permission.WRITE_MEDIA权限,并在module.json5中声明。

回到顶部