HarmonyOS使用@ohos.request文件下载操作后持有大量header中设入的字符串数据未释放?

@ohos.reques downloadFile文件下载操作,通过在header中设置相应字符串,下载完成之后这些header的字符串一直被长期持有,下载执行的次数越多,被保留的字符串数据就越多。通过hidebug.dumpJsHeapData 虚拟机堆导出,查看到的结果。

代码如下:

import fs from '@ohos.file.fs';
import hidebug from '@ohos.hidebug';
import request from '@ohos.request';
import { BusinessError } from '@kit.BasicServicesKit';
@Entry
@Component
struct Index {
  scroller: Scroller = new Scroller()
  @State status: string | number = ''
  @State message: string = ''
  @State performanceTiming: string = '';
  @State filename: string = 'blue.jpg'
  @State progress: string = ''
  @State downloadProgress: number = 0
  @State uploadProgress: number = 0
  @State showUrl: string = '';
  @State connectTimeout: number = 0;
  @State readTimeout: number = 0;
  @State startTime: number = 0;
  @State endTime: number = 0;
  @State maxBodyLength: number = -1;
  @State maxContentLength: number = -1;
  controller: TextInputController = new TextInputController()
  aboutToAppear(): void {
    AppStorage.setOrCreate("KEY_ENVIRONMENT","abc");
  }
  build() {
    Scroll(this.scroller) {
      Column() {
        //请求按钮
        Flex({ direction: FlexDirection.Row, alignItems: ItemAlign.Start, wrap: FlexWrap.Wrap }) {
          Button('下载').width(100).margin({
            bottom: 10,
            right: 10
          }).onClick((e) => {
            this.download()
          })
          Button('dump').width(100).margin({
            bottom: 10,
            right: 10
          }).onClick((e) => {
            hidebug.dumpJsHeapData('dump_prev_chapter_' + Date.now())
          })
        }
        //请求结果
        Column() {
          Text('请求结果')
            .fontSize(18)
            .fontWeight(FontWeight.Bold)
            .margin({ bottom: 10 })
            .textAlign(TextAlign.Start)
          Text('下载进度')
          Progress({ value: this.downloadProgress, type: ProgressType.Linear })
            .color('#009BE8').width('100%')
            .margin({ top: 8, right: 10 })
            .style({ strokeWidth: 10 })
          // 展示请求内容
          Flex({ direction: FlexDirection.Column, alignItems: ItemAlign.Start, }) {
            Text("请求开始时间: " + this.startTime)
              .width('100%')
              .fontSize(16)
              .fontWeight(700)
              .fontColor('#000000')
            Text("请求结束时间: " + this.endTime)
              .width('100%')
              .fontSize(16)
              .fontWeight(700)
              .fontColor('#000000')
            Text("请求响应时间: " + (this.endTime - this.startTime))
              .width('100%')
              .fontSize(16)
              .fontWeight(700)
              .fontColor('#000000')
            Text("Status: " + this.status)
              .width('100%')
              .fontSize(16)
              .fontWeight(700)
              .fontColor('#000000')
            Text("performanceTiming: " + this.performanceTiming)
              .width('100%')
              .fontSize(16)
              .fontWeight(700)
              .fontColor('#000000')
            Text("Data: " + this.message)
              .width('100%')
              .fontSize(16)
              .fontWeight(700)
              .fontColor('#000000')
              .maxLines(7)
          }
          .width('100%')
          .padding({ top: 20, bottom: 20, right: 15, left: 10 })
          .margin({ right: 10 })
          .borderStyle(BorderStyle.Solid)
          .borderWidth(1)
          .borderColor('#E6E7E8')
        }
        .margin({ top: 10, bottom: 20 })
        .alignItems(HorizontalAlign.Start)

        Button('清空输入框内容').width(120).onClick((e) => {
          this.clear()
        })
      }
    }
    .scrollable(ScrollDirection.Vertical) // 滚动方向纵向
    .scrollBar(BarState.On) // 滚动条常驻显示
    .margin({ left: 10, right: 10 })
  }
  // 下载
  download() {
    this.clear()
    let filePath = getContext(this).cacheDir + '/blue.jpg'
    // 下载。如果文件已存在,则先删除文件。
    try {
      fs.accessSync(filePath);
      fs.unlinkSync(filePath);
    } catch (err) {
    }
    let downloadTask: request.DownloadTask;
    try {
      let header: ESObject = {
        'content-type': 'text/plain'
      }
      let config : ESObject= {
        headers: header
      }
      request.downloadFile(getContext(), {
        url: 'http://1xx9.9xx.xxx.99:30xxx00/tpc/download/blue.jpg',
        filePath: filePath,
        header:createHttpRequestConfig_test<ESObject>(config).headers
      }, (err: BusinessError, data: request.DownloadTask) => {
        if (err) {
          console.error(`[axios] Failed to request the download. Code: ${err.code}, message: ${err.message}`);
          return;
        }
        downloadTask = data;
        // 下载失败
        downloadTask.on('fail',  (err)=> {
          console.info('[axios] ' + JSON.stringify(err))
        });
        // 完成下载
        downloadTask.on('complete', () => {
          console.info('[axios] complete' )
          this.message = 'complete'
        })
        downloadTask.on('progress', (loaded, total) => {
          this.progress = Math.round(loaded/total * 100) + '%'
          console.info('[axios] progress, loaded=' + loaded + ', total= ' + total )
        })
      });
    } catch (err) {
      console.error(`[axios]Failed to request the download. err: ${JSON.stringify(err)}`);
    }
  }
  clear() {
    this.performanceTiming = '';
    this.uploadProgress = 0;
    this.downloadProgress = 0
    this.message = '';
    this.status = '';
    this.startTime = 0;
    this.endTime = 0;
  }
}
export function createHttpRequestConfig_test<D>(config: ESObject) : ESObject {
  let encryptQdInfoStr = "111111aaaaabbbbccccddddeeeefffgggghhhh111111aaaaabbbbccccddddeeeefffgggghhhh111111"
  // config.headers.set('QDInfo', encryptQdInfoStr,true)
  // config.headers.set('Cookie', getCookies(encryptQdInfoStr),true)
  config.headers['QDInfo'] = encryptQdInfoStr
  config.headers['Cookie'] =  getCookies(encryptQdInfoStr)
  return config
}
function getCookies(encryptQDInfo:string) : string {
  let instance = QDNetWorkEnvironment.getInstance().getAppInfoModel();
  let cookieStr:string = ''
  cookieStr += 'appId=xx'
  cookieStr += '; '
  cookieStr += 'areaId=yy'
  cookieStr += '; '
  cookieStr += 'lang=cn'
  cookieStr += '; '
  cookieStr += 'mode=normal'
  cookieStr += '; '
  cookieStr += 'bar=104'
  cookieStr += '; '
  cookieStr += 'qid='+instance
  cookieStr += '; '
  return cookieStr
}
export class QDNetWorkEnvironment {
  private static instance: QDNetWorkEnvironment;
  private constructor() {
    // 私有构造函数,防止外部实例化
  }
  public static getInstance(): QDNetWorkEnvironment {
    if (!QDNetWorkEnvironment.instance) {
      QDNetWorkEnvironment.instance = new QDNetWorkEnvironment();
    }
    return QDNetWorkEnvironment.instance;
  }
  public getAppInfoModel(): string | undefined {
    let appInfo:string | undefined = AppStorage.get("KEY_ENVIRONMENT");
    return appInfo
  }
}
阅读 646
1 个回答

header 里面字符串的生命周期和 downloadTask 绑定,可以考虑在任务完成或失败时调用 delete 接口移除该任务对象。

参考文档:delete

撰写回答
你尚未登录,登录后可以
  • 和开发者交流问题的细节
  • 关注并接收问题和回答的更新提醒
  • 参与内容的编辑和改进,让解决方法与时俱进