文件下载场景,APP启动后首次网络切换(wifi-->4G)之后1min内,http.requestInStream(xxx)请求一直报错2300028(HarmonyOS 鸿蒙Next)

文件下载场景,APP启动后首次网络切换(wifi–>4G)之后1min内,http.requestInStream(xxx)请求一直报错2300028(HarmonyOS 鸿蒙Next) 场景:文件下载场景,APP冷启动之后,进行网络切换,将网络由WIFI–>4G流量;

问题描述:在WIFI第一次切换到4G时,1~3s左右可以检查到网络为4G。但是在切换1min左右的时间内,使用http.requestInStream(xxx)接口发起网络请求时,会报错2300028,此时requestInStream不可用。但是在网络切换1min后,再次进行网络切换时,http.requestInStream(xxx)表现正常,随后多次切换均表现正常。

核心网络请求代码如下:

private createOption(entity: HttpRequestEntity): http.HttpRequestOptions {
  let options: http.HttpRequestOptions = {
    method: http.RequestMethod.GET,
    usingCache: true,
    header: {
      'Range': 'bytes=' + entity.downloadSize + '-',
      'Connection': 'keep-alive',
      'Keep-Alive': 'timeout=' + 60000 + ', max=' + 1000
    },
    readTimeout: 3600000,
    connectTimeout: 10000,
    usingProxy: true
  };

  return options;
}
public sendRequest(entity: HttpRequestEntity, listener: IRequestListener) {
  if (this.state != DownloadRequestState.IDLE) {
    return;
  }
  let downloadError = new DownloadError(0, "");
  if (StringUtil.isEmpty(entity.url)) { // 非法url
    downloadError.code = SdkStatusCode.DOWNLOAD_INVALID_URL;
    downloadError.message = "request invalid url";
    listener.onFailed(downloadError);
    return;
  }

  let fullPath = entity.downloadDir + DownloadConstants.FILE_SEPARATOR + entity.localPath;
  let file: fs.File|null = DownloadFileUtil.createFileWithPath(fullPath, fs.OpenMode.READ_WRITE | fs.OpenMode.CREATE | fs.OpenMode.APPEND);

  if (file == null) {
    DownloadLogger.error(DownloadRequest.TAG, `sendRequest file = null, path=${entity.path}`);
    downloadError.code = SdkStatusCode.DOWNLOAD_FILE_IO_ERROR;
    downloadError.message = "DownloadRequest create file failed";
    listener.onFailed(downloadError);
    return;
  }

  let option = this.createOption(entity);

  this.httpRequest.on("dataReceive", (data: ArrayBuffer) => {
    try {
      if (file != null) {
        fs.writeSync(file.fd, data);
      }
      entity.downloadSize += data.byteLength;
      listener.updateProgress(data.byteLength);
    } catch (e) {
      DownloadLogger.error(DownloadRequest.TAG, `sendRequest dataReceive errCode=${e.code}`)
      DownloadFileUtil.closeFileSafely(file);
      this.resetHttpRequest();
      // 文件写入发生IO错误
      let code: Any = e.code;
      if (code == HttpErrorCode.NO_SPACE) {
        // 磁盘空间不足
        downloadError.code = SdkStatusCode.DOWNLOAD_SPACE_NOT_ENOUGH;
        downloadError.message = "No Space";
      } else {
        downloadError.code = SdkStatusCode.DOWNLOAD_FILE_IO_ERROR;
        downloadError.message = "request write file error";
      }
    }
  });

  this.httpRequest.on("dataEnd", () => {
    DownloadLogger.debug(DownloadRequest.TAG, `sendRequest dataEnd`)
    if (entity.downloadSize == entity.size) {
      listener.onSuccess();
    } else {
      if (downloadError.code != 0) { // 写入过程中发生错误
        if (downloadError.code == HttpErrorCode.NO_SPACE) {
          // 错误&异常,暂停下载
          listener.onError(downloadError);
        } else {
          // 失败重试
          listener.onFailed(downloadError);
        }
      } else { // 完整性校验失败,暂停下载
        downloadError.code = SdkStatusCode.DOWNLOAD_INTEGRITY_VERIFICATION_FAILED;
        downloadError.message = "download integrity verification failed";
        listener.onError(downloadError);
      }
    }
    DownloadFileUtil.closeFileSafely(file);
    this.resetHttpRequest();
  })

  this.state = DownloadRequestState.RUNNING;
  listener.onStart();
  this.httpRequest.requestInStream(url.URL.parseURL(entity.url).toString(), option)
    .then(() => {
      DownloadLogger.debug(DownloadRequest.TAG, `sendRequest finished`);
      DownloadFileUtil.closeFileSafely(file);
    }).catch((err: BusinessError) => {
      DownloadLogger.error(DownloadRequest.TAG, `sendRequest exception path=${entity.path}, err=${err.code}`)
      switch (err.code) {
        case HttpErrorCode.OPERATION_TIMEOUT:
          downloadError.code = SdkStatusCode.DOWNLOAD_TIME_OUT;
          downloadError.message = "request download operation timeout";
          break;
        case HttpErrorCode.URL_ERROR:
          downloadError.code = SdkStatusCode.DOWNLOAD_INVALID_URL;
          downloadError.message = "request url error";
          break;
        default:
          downloadError.code = SdkStatusCode.DOWNLOAD_NETWORK_ERROR;
          downloadError.message = "request net error";
          break;
      }
      this.destroyRequest();
      listener.onFailed(downloadError);
      DownloadFileUtil.closeFileSafely(file);
  });
}

更多关于文件下载场景,APP启动后首次网络切换(wifi-->4G)之后1min内,http.requestInStream(xxx)请求一直报错2300028(HarmonyOS 鸿蒙Next)的实战教程也可以访问 https://www.itying.com/category-93-b0.html

6 回复

2300028 操作超时 : 一般是TCP连接超时或读写超时。 您需要排查网络问题
您可以参考如下链接:https://developer.huawei.com/consumer/cn/doc/harmonyos-references-V5/errorcode-net-http-V5#section2300028-

我这边根据官方提供的requestInStream相关demo:https://developer.huawei.com/consumer/cn/doc/harmonyos-guides-V5/http-request-V5#requestinstream 接口开发步骤

并无法复现你说的问题,这边可否方便提供可以复现问题的demo来帮忙排查原因

更多关于文件下载场景,APP启动后首次网络切换(wifi-->4G)之后1min内,http.requestInStream(xxx)请求一直报错2300028(HarmonyOS 鸿蒙Next)的实战系列教程也可以访问 https://www.itying.com/category-93-b0.html


麻烦提供一个邮箱,我把Demo发送给你哈,

Hello,请问我怎么将Demo提供给你?方便提供一个邮箱么?

当connectionTime设置为60000ms的时候,2300028错误会减少或消失。

但是又会出现多次2300007错误码,也会在1min左右之后,http.requestInStream接口恢复正常。

注:网络切换之后,在1~3s左右,网络会恢复正常,目前只是发现http.requestInStream接口表现异常。

然后其他一些特别的现象是:

  1. 在同样的操作下,如果WIFI连接了Charles代理,在APP冷启动之后首次WIFI切换到4G之后,http.requestInStream(xxx)表现是正常的,不会出现2300028错误。
  2. APP冷启动之后,4G网络下进行下载,切换到WIFI,表现正常。随后任意进行网络切换也表现正常。

在HarmonyOS鸿蒙Next中,http.requestInStream(xxx)请求报错2300028通常与网络切换后的连接问题有关。该错误码可能表示网络连接不稳定或切换过程中出现的临时故障。在网络从WiFi切换到4G时,系统可能需要时间重新建立稳定的网络连接,导致短时间内请求失败。

具体原因可能包括:

  • 网络切换后,系统未及时更新网络状态,导致请求仍尝试使用旧网络。
  • 4G网络连接尚未完全建立,导致请求无法正常发送或接收数据。
  • 网络切换过程中,DNS解析或路由表更新延迟,影响请求的正常处理。

解决方法:

  • 在网络切换后,延迟一段时间再发起请求,确保网络稳定。
  • 监听网络状态变化,在检测到网络切换时重新初始化网络连接。
  • 增加请求重试机制,在遇到网络错误时自动重试。

请注意,以上方法需根据具体场景和需求进行调整,确保应用的稳定性和用户体验。

回到顶部