HarmonyOS 鸿蒙Next ArKTS中HttpResponse.result类型如何为ArrayBuffer,默认为string

HarmonyOS 鸿蒙Next ArKTS中HttpResponse.result类型如何为ArrayBuffer,默认为string

利用http下载图片并显示,API8

1. httpRequest.request("网址", {
   method: http.RequestMethod.GET,
   connectTimeout: 60000,
   readTimeout: 60000,
   header: {
      'Content-Type': 'application/octet-stream'
   }
}).then((jiguo)=> {
   image.createPixelMap(
      jiguo.result, //result始终默认为string。无法作为ArrayBuffer
      { editable: true, size: { width: 256, height: 256 }, pixelFormat:3 }
   ).then ((tu) => { this.tuxiang = tu })
}
网址默认下载的为jpg图片

更多关于HarmonyOS 鸿蒙Next ArKTS中HttpResponse.result类型如何为ArrayBuffer,默认为string的实战教程也可以访问 https://www.itying.com/category-93-b0.html

10 回复

开发者您好,图片上传下载可参考以下地址:https://gitee.com/openharmony/app_samples/tree/master/Network/UploadDownload

更多关于HarmonyOS 鸿蒙Next ArKTS中HttpResponse.result类型如何为ArrayBuffer,默认为string的实战系列教程也可以访问 https://www.itying.com/category-93-b0.html


为什么不能使用’Content-Type’: ‘application/octet-stream’ 下载为ArrayBuffer直接使用呢,我访问的网站下载的直接是jpg图片。

版主你好,请问ark网络请求回调中无法执行一些系统方法比如setTimeOut,router.push等等,是什么原因?是arkui的bug吗?

我在API9使用了一个叫ImageKnife的三方组件,可以直接下载并缓存网络图片 ,不需要关心ArrayBuffer细节,https://gitee.com/openharmony-tpc/ImageKnife,你也可以试试。另外setTimeout是全局方法,应该没问题,是不是拼错了。但是router.push需要导入import router from '@system.router';,你可以试试。

我也在研究这个问题,你试试直接用data.result作为ArrayBuffer。但根据JS相关的资料,说的是ArrayBuffer是不能被操作和访问的,比如foreach遍历的,又要用DataView封装一遍。但其实我只是想参考官方给的网络图片加载而已。

官方代码如下:

// 先创建一个PixelMap状态变量用于接收网络图片  
@State image: PixelMap = undefined  
build() {    
  Column({space: 10}) {      
    Button("获取网络图片")        
      .onClick(() => {          
        this.httpRequest();        
      })      
    Image(this.image).height(100).width(100)    
  }    
  .width('100%')    
  .height('100%')    
  .padding(10)  
}  
// 网络图片请求方法  
private httpRequest() {    
  let httpRequest = http.createHttp();        
  httpRequest.request(      
    "https://www.example.com/xxx.png",   // 请填写一个具体的网络图片地址      
    (error, data) => {        
      if(error) {          
        console.log("error code: " + error.code + ", msg: " + error.message)        
      } else {          
        let code = data.responseCode          
        if(ResponseCode.ResponseCode.OK == code) {            
          let imageSource = image.createImageSource(data.result)            
          let options = {alphaType: 0,                     
                         // 透明度                           
                         editable: false,                  
                         // 是否可编辑                           
                         pixelFormat: 3,                   
                         // 像素格式                           
                         scaleMode: 1,                     
                         // 缩略值                           
                         size: {height: 100, width: 100}}  // 创建图片大小            
          imageSource.createPixelMap(options).then((pixelMap) => {              
            this.image = pixelMap            
          })          
        } else {            
          console.log("response code: " + code);          
        }        
      }      
    }    
  )  
}

但这段代码有个问题就是

let imageSource = image.createImageSource(data.result)

使用API8,这个createImageSource方法的提示是要传入一个url:string,但其实http直接访问图片网址,请求到的data.result是这样的

如果直接在控制台打印data.result作为字符串,是可以看到和图上TEXT相同的乱码文本的。但这个文本显然是Image组件无法直接使用的

因此我又查看了giee上官方提供的图片处理相关API

https://gitee.com/openharmony/docs/blob/master/zh-cn/application-dev/reference/apis/js-apis-image.md#imagecreatepixelmap8

按照我的理解,核心逻辑是要构建一个 pixelMapImage 组件直接绑定该 pixelMap,然后把请求到的图像数据写入 pixelMap 中。

写了一段,还是没跑通,代码如下:

这张网络图片的一些属性如下:

  • 图片大小66.5 KB
  • 网络请求返回的Content-Length=68107
  • 分辨率 1125x750
struct Index {
  // 先创建一个PixelMap状态变量用于接收网络图片  
  @State imageMy: PixelMap = undefined  
  build() {    
    Column({ space: 10 }) {      
      Button("获取网络图片")        
        .onClick(() => {          
          this.httpRequest();        
        })      
      Image(this.image)        
        .height(100)        
        .width(100)        
        .alt($r('app.media.ic_launcher'))        
        .objectFit(ImageFit.Contain)    
    }    
    .width('100%')    
    .height('100%')    
    .padding(10)  
  }  
  // 网络图片请求方法  
  private httpRequest() {    
    let httpRequest = http.createHttp();    
    httpRequest.request(      
      "https://images.pexels.com/photos/7858743/pexels-photo-7858743.jpeg?auto=compress&cs=tinysrgb&w=1260&h=750&dpr=1", // 请填写一个具体的网络图片地址      
      {        
        method: http.RequestMethod.GET, // 可选,默认为http.RequestMethod.GET        
        // 开发者根据自身业务需要添加header字段        
        header: {},        
        connectTimeout: 60000, // 可选,默认为60s        
        readTimeout: 60000, // 可选,默认为60s      
      },      
      (error, data) => {        
        if (error) {          
          console.log("error code: " + error.code + ", msg: " + error.message)        
        } else {          
          // data.header为http响应头,可根据业务需要进行解析          
          console.info('header:' + JSON.stringify(data.header));          
          let code = data.responseCode          
          if (ResponseCode.ResponseCode.OK == code) {            
            console.info("ResponseCode.ResponseCode.OK=" + ResponseCode.ResponseCode.OK)            
            console.info("code=" + ResponseCode.ResponseCode.OK)            
            let resultArrayBuffer = data.result as ArrayBuffer            
            let resultArrayBufferLength = new ArrayBuffer(3375000)            
            console.info("resultArrayBuffer=" + resultArrayBuffer.length)            
            let options = {              
              alphaType: 0, // 透明度              
              editable: true, // 是否可编辑              
              pixelFormat: 2, // 像素格式              
              scaleMode: 1, // 缩略值              
              size: { height: 750, width: 1125 }            
            } // 创建图片大小            
            image.createPixelMap(resultArrayBufferLength, options).then((pixelMap) => {              
              pixelMap.writeBufferToPixels(resultArrayBuffer).then(() => {                
                console.log("Succeeded in writing data from a buffer to a PixelMap.");                
                this.imageMy=pixelMap//                
                pixelMap.getImageInfo().then((data) => {//                  
                  console.info("data.size.width=" + data.size.width)//                  
                  console.info("data.size.height=" + data.size.height)//                  
                  data.size.height//                
                })              
              }).catch((err) => {                
                console.error("Failed to write data from a buffer to a PixelMap."+err);              
              })            
            })          
          } else {            
            console.log("response code: " + code);          
          }        
        }      
      }    
    )  
  }

关键点有几个:

  1. createPixelMap函数第一个参数需要接收一个ArrayBuffer,最开始我以为这个地方可以直接传入data.result作为ArrayBuffer这种形式,发现会提示错误。
  2. 于是手动确定图片大小后,按照上述图片处理API所述,根据图片分辨率1125x720x4创建了ArrayBuffer
  3. createPixelMap第二个参数options中的 size: { height: 750, width: 1125 }
  4. 使用writeBufferToPixels方法将传入的data.result作为ArrayBuffer写入pixelMap中。

一切看起来好像没问题,看日志似乎createPixelMap也成功了,但一个报错又给我整不会了。

Failed to write data from a buffer to a PixelMap.Error: Failed to napi_get_arraybuffer_info!
import http from '@ohos.net.http';

@Entry
@Preview
@Component
struct Splash {
  aboutToAppear() {
    let httpRequest = http.createHttp()
    let url = 'http://apis.juhe.cn/simpleWeather/query?key=397c9db4cb0621ad0313123dab416668&city=北京'
    httpRequest.request(url, (err, data) => {
      console.log("请求结果>>" + JSON.stringify(err) + "," + JSON.stringify(data))
      setTimeout(() => {
        console.log("111")
      }, 100)
    })
    setTimeout(() => {
      console.log("222")
    }, 200)
  }

  build() {
    Column() {
      Text("Hello World").fontSize(30)
    }
    .justifyContent(FlexAlign.Center)
    .width('100%')
    .height('100%')
    .backgroundColor("#FFFFFF")
  }
}

打印结果:

请求回调里的setTimeOut就不执行…

setTimeout没问题的,我看到222输出了,111 可能部分log日志被过滤了,建议用@State绑定数据放到UI上Text组件展示,这样能直观看到结果,另外网络请求失败,可以看看是不是网络权限问题,

用State绑定试了,一样没效果,因为请求回调里的setTimeout就没执行,回调外没问题,只要放在回调里就不执行,请求失败那个不是重点,重点在于回调,不知道啥原因0.0,很无语啊…,你试过没?写个最简单的网络请求,然后回调里放个setTimeout试试,我现在不清楚的是arkui本身的问题,还是我自己的环境问题?

试过fetch,以及封装为Promise,都不行,只要写在回调里就不执行,

在HarmonyOS鸿蒙系统的Next ArKTS(Ark TypeScript)环境中,HttpResponse.result 类型默认是 string。如果你希望将其类型改为 ArrayBuffer,可以通过处理响应数据来实现,因为原生 HttpResponse 对象并不直接支持将结果解析为 ArrayBuffer

你可以通过以下步骤来手动处理响应数据,将其转换为 ArrayBuffer

  1. 获取响应的二进制数据:使用 HttpResponse 对象的 arrayBuffer() 方法来获取响应数据的 ArrayBuffer 表示。

  2. 处理 ArrayBuffer:一旦你有了 ArrayBuffer,你可以使用 TypeScript 中的 DataView 或其他相关 API 来进一步处理这些数据。

示例代码(伪代码,具体实现可能需根据实际API调整):

async function fetchData(): Promise<ArrayBuffer> {
    const response = await fetch('your-url-here');
    if (!response.ok) {
        throw new Error('Network response was not ok');
    }
    return response.arrayBuffer();
}

fetchData().then((buffer) => {
    // 在这里处理你的 ArrayBuffer
    console.log(buffer);
}).catch((error) => {
    console.error('Fetch error:', error);
});

注意,上述代码示例使用了 fetch API,这是基于Web标准的API,在鸿蒙系统中可能有所不同,具体实现需参考鸿蒙系统的文档。

如果问题依旧没法解决请联系官网客服,官网地址是 https://www.itying.com/category-93-b0.html

回到顶部