interface hadChunkProps {
  cur: number
  file: ArrayBuffer
}

接口请求获得文件分片结果,推入数组后获得chunkArr,对数组排序;

之前的方法是:

try {
  const blobFile = new buffer.Blob(sortChunks.map((item) => item.file), { type: 'application/octet-stream' } as ESObject)
  const ab = await blobFile.arrayBuffer()

  let file = await fs.open(filePath, fs.OpenMode.READ_WRITE | fs.OpenMode.CREATE);
  logUtil.info(['new File: ', JSON.stringify(file)]);

  try {
    const writeLen = await fs.write(file.fd, ab);
    logUtil.info(["write data to file succeed and size is:", writeLen.toString()]);
  } catch (err){
    logUtil.error(['Error in file creation or writing 1: ', err.message]);
  }
  finally {
    fs.closeSync(file);
  }

  return filePath;
} catch (error) {
  logUtil.error(['Error in file creation or writing 2: ', error.message]);
  return '';

但此方法会与较小文件(约30MB以下)无问题,若文件再大一些出现报错:

OutOfMemory when trying to allocate 209715224 bytes function name: Heap::AllocateHugeObject
  Cannot get SourceMap info, dump raw stack

故使用文件流处理文件下载:

          let curSize: number = 0
          let file1 = fs.openSync(filePath,fs.OpenMode.READ_WRITE|fs.OpenMode.CREATE)  //注意不能对同一文件重复修改!!!  =>分片下载时可对同名文件做断点续传
          const stream1 = await fs.fdopenStream(file1.fd,"a+")

          for (let chunk of sortChunks){
            let option : WriteOptions = {
              length:chunk.file.byteLength,
              offset:curSize
            }
            const num:number = stream1.writeSync(chunk.file, option)
            console.log(`片段${chunk.cur}终索引:`,curSize,'-',num)
            curSize += num
          }
          stream1.close();
          return filePath

方法使用不难,但花费了半天时间处理出问题没找到原因,最后发现原因在于中间文件(file1:存放沙箱,下载过渡用)在下载完成后需要删除,否则遇同名文件会对该文件进行写入流处理,导致测试下载的文件始终大于源文件。

额外问题:

1.文件覆盖写入问题:待覆盖的文件内容长度比原内容短,会导致新内容长度以后的缓存区维持原内容,所以要截断后续多与内容:

  async save() {
    try{
      // 保存时加文件锁处理并发
      logUtil.info(['chartRecord save: ', this.fileUrl])
      const file = await fs.open(this.fileUrl, fs.OpenMode.WRITE_ONLY | fs.OpenMode.CREATE)  //只写:清空原内容
      file.tryLock(true); //共享锁   ==》13900010,文件暂不可用

      // const buf = buffer.from(JSON.stringify(this.records),'utf-8')
      // console.log('待写入的缓冲区长度:',buf.length)

      fs.write(file.fd, JSON.stringify(this.records)).then((writeLen: number) => {
        fs.truncateSync(file.fd,writeLen)
      }).catch((err: BusinessError) => {
      }).finally(() => {
        file.unlock(); //解锁
        fs.closeSync(file);
      });
    }catch(e){
    }
  }

Logo

讨论HarmonyOS开发技术,专注于API与组件、DevEco Studio、测试、元服务和应用上架分发等。

更多推荐