Browse Source

web button点击弹出相册,相册选择图片上传服务器。

jiaxiaoqiang 9 months ago
parent
commit
f7148b85ba

+ 2 - 2
build-profile.json5

@@ -22,9 +22,9 @@
         "name": "default",
         "material": {
           "certpath": "C:/Users/Administrator/.ohos/config/openharmony/default_common-station-web_RYQhOtG3oPpAUMsnAlEeKMLDDcU6Dxe3sz7pow0GVEQ=.cer",
-          "storePassword": "0000001BA48FC8B717FE11F8FAD5FE5D2E48E86E65E7AC295F6247025CA544AEE7FBC3E82A572EFC9B6E00",
+          "storePassword": "0000001AA22B3872C196E0E68F876789073DB734D98E385061515171EB6B4D122CDFE61062E1B2C9A724",
           "keyAlias": "debugKey",
-          "keyPassword": "0000001B1F1C43099C9DD60B22877D018B9CDBB66926D6F0ED4832CF4BE0DCE4A2CCAC505CA95CAE427044",
+          "keyPassword": "0000001A00539E6C3C1BDF580730B26B0E934586A504A2501E116A7CB12C091792BBE45B3617842AC252",
           "profile": "C:/Users/Administrator/.ohos/config/openharmony/default_common-station-web_RYQhOtG3oPpAUMsnAlEeKMLDDcU6Dxe3sz7pow0GVEQ=.p7b",
           "signAlg": "SHA256withECDSA",
           "storeFile": "C:/Users/Administrator/.ohos/config/openharmony/default_common-station-web_RYQhOtG3oPpAUMsnAlEeKMLDDcU6Dxe3sz7pow0GVEQ=.p12"

+ 20 - 0
entry/src/main/ets/components/ProgressDialog.ets

@@ -0,0 +1,20 @@
+@CustomDialog
+export struct ProgressDialog {
+  cancel?: () => void
+  confirm?: () => void
+  controller: CustomDialogController
+
+  build() {
+    Column() {
+      Text('正在上传中...').fontSize(24).margin({ top: 10, bottom: 10 })
+      LoadingProgress()
+        .color(Color.Blue)
+        .layoutWeight(1)
+
+    }
+    .height(300)
+    .width(340)
+    .backgroundColor(Color.White)
+    .borderRadius(10)
+  }
+}

+ 1 - 0
entry/src/main/ets/entryability/EntryAbility.ets

@@ -41,6 +41,7 @@ export default class EntryAbility extends UIAbility {
 
       windowClass.setWindowLayoutFullScreen(true)
     })
+    // =================================
     windowStage.loadContent('pages/Index', (err) => {
       if (err.code) {
         hilog.error(0x0000, 'testTag', 'Failed to load the content. Cause: %{public}s', JSON.stringify(err) ?? '');

+ 175 - 0
entry/src/main/ets/pages/Base64Page.ets

@@ -0,0 +1,175 @@
+import common from '@ohos.app.ability.common';
+import abilityAccessCtrl from '@ohos.abilityAccessCtrl';
+import bundleManager from '@ohos.bundle.bundleManager';
+import picker from '@ohos.file.picker';
+import fs from '@ohos.file.fs';
+import image from '@ohos.multimedia.image';
+import { BusinessError } from '@ohos.base';
+import fileUri from '@ohos.file.fileuri';
+import { FormData, File, FileUpload } from "@ohos/commons-fileupload"
+import http from '@ohos.net.http';
+
+@Entry
+@Component
+export struct MinePage {
+  @State profileSrc: Resource = $r('app.media.icon')
+  @State profileImage: PixelMap = new Object() as PixelMap
+  @State uri: string = ''
+  @State flag: number = 0
+
+  // 选择头像图片
+  // 定义一个函数用于点击头像时拉起用户图库
+  async pickProfile1() {
+    const photoSelectOptions = new picker.PhotoSelectOptions();
+    // 设置选择的文件类型为图片类型
+    photoSelectOptions.MIMEType = picker.PhotoViewMIMETypes.IMAGE_TYPE;
+    // 一次只能选择一张图片
+    photoSelectOptions.maxSelectNumber = 1;
+    let uri = "";
+    const photoViewPicker = new picker.PhotoViewPicker();
+    // 拉起图库,获取选中图片的uri
+    photoViewPicker.select(photoSelectOptions).then((photoSelectResult) => {
+      // 获取选中图片的uri
+      uri = photoSelectResult.photoUris[0];
+      this.uri = uri
+      this.flag = 1
+      console.info('photoViewPicker.select to file succeed and uris are:' + uri)
+    }).catch((err: BusinessError) => {
+      console.error(`Invoke photoViewPicker.select failed, code is ${err.code}, message is ${err.message}`);
+    })
+    this.getPixelMap()
+  }
+
+  // 定义一个函数用于点击头像时拉起用户图库
+  async pickProfile() {
+    const photoSelectOptions = new picker.PhotoSelectOptions();
+    // 设置选择的文件类型为图片类型
+    photoSelectOptions.MIMEType = picker.PhotoViewMIMETypes.IMAGE_TYPE;
+    // 一次只能选择一张图片
+    photoSelectOptions.maxSelectNumber = 1;
+    const photoViewPicker = new picker.PhotoViewPicker();
+    // 拉起图库,获取选中图片的uri,并将选择图片拷贝至应用沙箱指定位置
+    photoViewPicker.select(photoSelectOptions)
+      .then((photoSelectResult: picker.PhotoSelectResult) => {
+        // 获取选中图片的uri
+        let imageUri = photoSelectResult.photoUris[0];
+        console.info('photoViewPicker.select to file succeed and uris are:' + imageUri);
+        let context = getContext(this)
+        //获取应用通用文件路径
+        let filesDir = context.filesDir
+        let fileName = "userProfileImage"
+        //获取沙箱中文件路径
+        let path = filesDir + "/" + fileName + "." + imageUri.split(".")[1]
+        let file = fs.openSync(imageUri, fs.OpenMode.READ_ONLY)
+        let file2 = fs.openSync(path, fs.OpenMode.READ_WRITE | fs.OpenMode.CREATE)
+        //完成图片拷贝
+        fs.copyFileSync(file.fd, file2.fd)
+        fs.closeSync(file.fd)
+        fs.closeSync(file2.fd)
+        //获取图片沙箱路径对应的uri
+        this.uri = fileUri.getUriFromPath(path)
+        console.log("ddddddd this.url", this.uri)
+        //获取图片对应的PixelMap
+        this.getPixelMap()
+      })
+      .catch((err: BusinessError) => {
+        console.error('MinePage', `Invoke photoViewPicker.select failed, code is ${err.code}, message is ${err.message}`);
+      })
+  }
+
+  // 获取图片的pixelmap
+  getPixelMap() {
+    // 通过uri打开图片文件,获取文件fd
+    let file = fs.openSync(this.uri, fs.OpenMode.READ_WRITE);
+    const imageSourceApi = image.createImageSource(file.fd);
+
+
+    try {
+      // 将图片解码为pixelmap
+      imageSourceApi.createPixelMap().then(pixelmap => {
+        this.profileImage = pixelmap
+        console.log('ddddddddd Succeeded in creating pixelmap object through image decoding parameters.');
+      }).catch((err: BusinessError) => {
+        console.log('ddddddddd Failed to create pixelmap object through image decoding parameters.');
+      })
+    }
+    catch (e) {
+      console.log('ddddddddd Failed')
+    }
+  }
+
+  private async openGallery() {
+    let context = getContext(this) as common.UIAbilityContext;
+    let atManager = abilityAccessCtrl.createAtManager();
+    let info = await bundleManager.getBundleInfoForSelf(0);
+    // if (info && info.appInfo) {
+    //   let result = atManager.verifyAccessTokenSync(info.appInfo.accessTokenId, "ohos.permission.READ_MEDIA");
+    //   if (abilityAccessCtrl.GrantStatus.PERMISSION_GRANTED == result) {
+    //     console.log("has permission")
+    //   }
+    // } else {
+    atManager.requestPermissionsFromUser(context, ["ohos.permission.READ_MEDIA", "ohos.permission.WRITE_MEDIA"], (error, result) => {
+      if (result) {
+        console.log("result: " + JSON.stringify(result));
+        if (result.authResults[0] == abilityAccessCtrl.GrantStatus.PERMISSION_GRANTED) {
+          // 用户授予权限
+          this.pickProfile1();
+        } else {
+          // 用户拒绝权限
+          console.log("permission denied")
+        }
+      } else {
+        console.log("error: " + JSON.stringify(error));
+      }
+    });
+    // }
+  }
+
+  aboutToAppear() {
+
+  }
+
+  build() {
+    Column() {
+      Image(this.profileImage)
+        .border({ width: 3, color: Color.Blue })
+        .width(108)
+        .height(108)
+        .objectFit(ImageFit.Cover)
+        .borderRadius(54)
+        .onClick(() => {
+          // this.openGallery()
+
+          let fileUpload = new FileUpload({
+            baseUrl: "http://10.88.11.200:8078",
+            readTimeout: 60000,
+            connectTimeout: 60000
+          })
+
+          // fileUpload.get({ url: "http://10.88.11.200:8078/api/v1/sys/dept/orgList" }).then((res: http.HttpResponse) => {
+          //   console.info("ddddddddd" + JSON.stringify(res));
+          // })
+
+          const formData = new FormData();
+          formData.append("key", 1); //可以添加基本类型的值,目前支持string、number
+          formData.append("myFile", "File"); //也可以添加File类型的对象
+
+
+          fileUpload.post("/api/v1/base/upload", formData).then(res => {
+            console.log("ddddddd success", JSON.stringify(res));
+          }).catch((err: BusinessError) => {
+            console.error("ddddddd    fail", JSON.stringify(err));
+          })
+        })
+      if (!this.uri) {
+        Text('点击上传头像')
+          .fontSize(24)
+          .margin({ top: 10 })
+      }
+    }
+    .alignItems(HorizontalAlign.Center)
+    .justifyContent(FlexAlign.Center)
+    .width('100%')
+    .height('100%')
+  }
+}

+ 17 - 0
entry/src/main/ets/pages/CamerPage.ets

@@ -0,0 +1,17 @@
+@Entry
+@Component
+struct CamerPage {
+  @State message: string = 'Hello World';
+
+  build() {
+    Row() {
+      Column() {
+        Text(this.message)
+          .fontSize(50)
+          .fontWeight(FontWeight.Bold)
+      }
+      .width('100%')
+    }
+    .height('100%')
+  }
+}

+ 187 - 77
entry/src/main/ets/pages/Index.ets

@@ -1,9 +1,15 @@
 import web_webview from '@ohos.web.webview';
 import process from '@ohos.process'
+import common from '@ohos.app.ability.common';
+import abilityAccessCtrl from '@ohos.abilityAccessCtrl';
+import bundleManager from '@ohos.bundle.bundleManager';
 import picker from '@ohos.file.picker';
+import http from '@ohos.net.http';
 import { BusinessError } from '@ohos.base';
-import common from '@ohos.app.ability.common';
-import request from '@ohos.request'
+import { FormData, File, FileUpload } from "@ohos/commons-fileupload"
+import fs from '@ohos.file.fs';
+import { ProgressDialog } from '../components/ProgressDialog';
+
 
 interface DownStartModel {
   url: string;
@@ -13,20 +19,36 @@ interface DownStartModel {
   contentLength: number
 }
 
+interface FileResponseModel {
+  code?: string
+  data?: string
+  msg?: string
+}
+
 interface BridgeParams {
   path?: string
   token?: string
   method?: "get" | "post"
-  data?: Record<string, string> //其他参数
+  //   产线code。 id。
+  //   扫码开工的id
+  //   工序的id
 }
 
+interface FileSelectorEvent {
+  result: FileSelectorResult,
+  fileSelector: FileSelectorParam
+}
 
 const TAG = "openHarmonyBridge" //webview和vue沟通的名称
 const baseUrl = "http://10.88.11.200:10000"
 const proxyPrefix = "/mes-server"
 
+
 class BridgeModel {
-  constructor() {
+  context: common.UIAbilityContext
+
+  constructor(c: common.UIAbilityContext) {
+    this.context = c
   }
 
   // this.controller.registerJavaScriptProxy 这个里面要对应
@@ -35,6 +57,10 @@ class BridgeModel {
     // let downloadUrl: string = baseUrl + proxyPrefix + params.path
     // console.info(TAG, `download:`, downloadUrl);
     console.info(TAG, `params:`, params);
+
+    let p: BridgeParams = JSON.parse(params)
+
+
     return 'ArkTS收到了下载的请求';
   }
 }
@@ -45,37 +71,160 @@ struct Index {
   controller: web_webview.WebviewController = new web_webview.WebviewController();
   @State mode: MixedMode = MixedMode.All
   UIAbilityContext: common.UIAbilityContext = getContext(this) as common.UIAbilityContext
+  dialogController: CustomDialogController = new CustomDialogController({
+    builder: ProgressDialog({
+      // cancel: ()=> { this.onCancel() },
+      // confirm: ()=> { this.onAccept() },
+    }),
+    alignment: DialogAlignment.Center,
+    customStyle: true,
+  })
   // 声明需要注册的对象
-  @State bridgeObj: BridgeModel = new BridgeModel();
+  @State bridgeObj: BridgeModel = new BridgeModel(this.UIAbilityContext);
+  hasRegistered: boolean = false
+  registerJS = () => {
 
-  aboutToAppear() {
-    setTimeout(() => {
+    // 这个必须要调用刷新才起作用, 而且只能执行一次
+    if (!this.hasRegistered) {
       this.controller.registerJavaScriptProxy(this.bridgeObj, TAG, ["download"])
       this.controller.refresh()
-    }, 2000)
+      this.hasRegistered = true
+    }
+
 
   }
 
-  build() {
+  aboutToAppear(): void {
+    // this.hasRegistered = false
+    // setTimeout(() => {
+    //   this.registerJS()
+    // }, 2000)
+    // this.dialogController.open()
 
+  }
 
-    Column() {
-      Stack() {
-        // 组件创建时,加载www.example.com
+  private async openGallery() {
+    let context = getContext(this) as common.UIAbilityContext;
+    let atManager = abilityAccessCtrl.createAtManager();
+    let info = await bundleManager.getBundleInfoForSelf(0);
+    if (info && info.appInfo) {
+      let result = atManager.verifyAccessTokenSync(info.appInfo.accessTokenId, "ohos.permission.READ_MEDIA");
+      if (abilityAccessCtrl.GrantStatus.PERMISSION_GRANTED == result) {
+        console.log("has permission")
+      }
+    } else {
+      atManager.requestPermissionsFromUser(context, ["ohos.permission.READ_MEDIA"], (error, result) => {
+        if (result) {
+          console.log("result: " + JSON.stringify(result));
+          if (result.authResults[0] == abilityAccessCtrl.GrantStatus.PERMISSION_GRANTED) {
+            // 用户授予权限
+            this.openGalleryInternal();
+          } else {
+            // 用户拒绝权限
+            console.log("permission denied")
+          }
+        } else {
+          console.log("error: " + JSON.stringify(error));
+        }
+      });
+    }
+  }
+
+  private openGalleryInternal() {
+    let photoPicker = new picker.PhotoViewPicker();
+    photoPicker.select({
+      MIMEType: picker.PhotoViewMIMETypes.IMAGE_TYPE,
+      maxSelectNumber: 1
+    }, (error, result) => {
+      if (result) {
+
+        this.dialogController.open()
+
+        // this.uploadImage(result.photoUris); file://media/Photo/3/IMG_1723222627_002/IMG_20240810_005707.jpg
+        result.photoUris.forEach((url) => {
+          console.log("uploadLog: 选择完图片的路径" + url);
+
+          try {
+            const uri = url
+            // 2.2 根据uri同步打开文件
+            const file = fs.openSync(uri)
+            // 2.3 同步获取文件的详细信息
+            const stat = fs.statSync(file.fd)
+            // 2.4 创建缓冲区存储读取的文件流
+            const buffer = new ArrayBuffer(stat.size)
+            // 2.5 开始同步读取文件流到缓冲区
+            fs.readSync(file.fd, buffer)
+            // 2.6 关闭文件流
+            fs.closeSync(file)
+
+            // 3. 转成base64编码的字符串
+            // const helper = new util.Base64Helper()
+            // const str = helper.encodeToStringSync(new Uint8Array(buffer))
+            console.log('mk-logger', 'photoPlugin-str', buffer.byteLength, JSON.stringify(buffer))
+
+            let toUpFile = new File()
+            toUpFile.fileName = "test.jpg"
+            toUpFile.fileData = buffer
 
+            let fileUpload = new FileUpload({
+              baseUrl: "http://10.88.11.200:8078",
+              readTimeout: 60000,
+              connectTimeout: 60000,
+            })
+
+            const formData = new FormData();
+            // formData.append("key", 1); //可以添加基本类型的值,目前支持string、number
+            formData.append("fileName", "test.jpg"); //也可以添加File类型的对象
+            // formData.append('file', `internal://cache/${fileName}`)
+            formData.append('file', toUpFile)
+
+            fileUpload.post("/api/v1/base/upload", formData, {
+
+              header: {
+                'Content-Type': 'multipart/form-data',
+                'Authorization': "eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJsb2dpblR5cGUiOiJsb2dpbiIsImxvZ2luSWQiOnsiaWQiOjEwMDAwLCJ1c2VyTmFtZSI6ImFkbWluIiwiZGVwdElkIjoxLCJzdGF0aW9uSWQiOjAsImF2YXRhciI6Ii9qZ2ZpbGUvLzIwMjQvNS8yNy8yNzQzMjkzOTU4Mzg4NTIuanBnIiwib3JnSWQiOjF9LCJkZXZpY2UiOiJiYWNrIiwiZWZmIjoxNzIzOTQ2NTQwNzQxLCJyblN0ciI6InpkOWpKZFlBdVpnR0NEd2xBWnZIcXpkUThBaW9xaUh6In0.8fEZh6HCbkE0kmwF6Ru-1JtVSfQN39mB51pIsI6bzDI"
+              },
+            }).then((res: http.HttpResponse) => {
+              this.dialogController.close()
+              let model: FileResponseModel = res.result as FileResponseModel
 
+              // let data: FileModel = JSON.parse(model.data)
+
+              console.log(TAG, "ddddddd success", JSON.stringify(model));
+
+              // let data: ESObject = res.result as ESObject
+              // // this.netImageUrl = data.data.fileUrl ?? ""
+              // console.error("ddddddd    图片地址:  ", `http://10.88.11.201:9000/${data.data.fileUrl}`);
+            }).catch((err: BusinessError) => {
+              this.dialogController.close()
+              console.error(TAG, "ddddddd    fail");
+            })
+          }
+          catch (e) {
+            this.dialogController.close()
+            console.log(TAG, 'mk-logger', 'photoPlugin-str', JSON.stringify(e))
+          }
+
+
+          // this.uploadImg3(url)
+          // this.uploadImg2(url)
+        })
+      }
+    });
+  }
+
+  build() {
+    Column() {
+      Stack() {
         // Web({ src: $rawfile('download.html'), controller: this.controller })//测试下载proxy互相传值
+        // Web({ src: $rawfile('local.html'), controller: this.controller }) //测试webview里面选择文件
+        // Web({ src: $rawfile('camera.html'), controller: this.controller })//测试相机
+        Web({ src: $rawfile('doc.html'), controller: this.controller })//测试官方文档
 
-        // Web({ src: $rawfile('local.html'), controller: this.controller })  //测试webview里面选择文件
-        // Web({
-        //   src: 'http://10.88.11.200:10000/login',
-        //   controller: this.controller
-        // })
-        // Web({ src: 'http://apm.jgiot.com:7012/login', controller: this.controller})
-        Web({
-          src: 'http://10.88.20.88:3006/login',
-          controller: this.controller
-        })//  Web({ src: 'http://10.88.11.200:11000/login', controller: this.controller})
+          // Web({
+          //   src: 'http://10.88.20.88:3005/login',
+          //   controller: this.controller
+          // })
           .mixedMode(this.mode)
           .onlineImageAccess(true)
           .javaScriptAccess(true)
@@ -83,32 +232,23 @@ struct Index {
           .databaseAccess(true)
           .domStorageAccess(true)
           .onShowFileSelector((event) => {
-            console.log('MyFileUploader onShowFileSelector', JSON.stringify(event))
-            const documentSelectOptions = new picker.DocumentSelectOptions();
-            let uri: string | null = null;
-            const documentViewPicker = new picker.DocumentViewPicker();
-            documentViewPicker.select(documentSelectOptions).then((documentSelectResult) => {
-              uri = documentSelectResult[0];
-              console.info('documentViewPicker.select to file succeed and uri is:' + uri);
-              if (event) {
-                event.result.handleFileList([uri]);
-              }
-            }).catch((err: BusinessError) => {
-              console.error(`Invoke documentViewPicker.select failed, code is ${err.code}, message is ${err.message}`);
-            })
-            return true
+            console.log(TAG, "onShowFileSelector", JSON.stringify(event))
+
+
+            this.openGallery()
+            // setTimeout(() => {
+            //   // 这个会触发addEventListener('change')的事件,但是每次的值都要不同。
+            //   event?.result.handleFileList([Date.now() + '.jpg']);
+            // }, 1300)
+            return true;
+          })
+          .onProgressChange((e) => {
+            if (e && e.newProgress == 100) {
+              this.registerJS()
+            }
           })
-        // .onDownloadStart((event: DownStartModel) => {
-        //   console.log('onDownloadStart url:' + event.url)
-        //   console.log('onDownloadStart userAgent:' + event.userAgent)
-        //   console.log('onDownloadStart contentDisposition:' + event.contentDisposition)
-        //   console.log('onDownloadStart contentLength:' + event.contentLength)
-        //   console.log('onDownloadStart mimetype:' + event.mimetype)
-        //
-        //
-        // })
         // .onConsole((e) => {
-        //   console.log(TAG, JSON.stringify(e))
+        //   console.log(TAG, "onConsole", JSON.stringify(e))
         //   return true
         // })
 
@@ -133,36 +273,6 @@ struct Index {
     }
     .width(px2vp(1920))
     .height(px2vp(1080))
+
   }
 }
-
-
-// downloadFile(url: string) {
-//
-//   let filePath = this.UIAbilityContext.filesDir + '/' + "fileName";
-//
-//   try {
-//     request.downloadFile(this.UIAbilityContext, {
-//       url: url,
-//       filePath: filePath
-//     }).then((data) => {
-//       // 监听下载完成
-//       data.on('complete', () => {
-//         console.info('downloadFile task completed.');
-//         // 安装应用
-//         // this.installApp(filePath);
-//       });
-//       // 监听下载失败
-//       data.on('fail', (err) => {
-//         console.info('downloadFile task failed. Cause:' + err);
-//       });
-//     }).catch(() => {
-//       console.error('downloadFile to request the download. Cause: ');
-//
-//     })
-//   } catch (err) {
-//     // err.message: bad file path   Download File already exists
-//     console.error('downloadFile.code : ' + err.code + ', err.message : ' + err.message);
-//
-//   }
-// }

+ 395 - 0
entry/src/main/ets/pages/SelectAlbumPage.ets

@@ -0,0 +1,395 @@
+import common from '@ohos.app.ability.common';
+import abilityAccessCtrl from '@ohos.abilityAccessCtrl';
+import bundleManager from '@ohos.bundle.bundleManager';
+import picker from '@ohos.file.picker';
+import request from '@ohos.request';
+import http from '@ohos.net.http';
+import fs from '@ohos.file.fs';
+import { BusinessError } from '@ohos.base';
+
+import axios, { AxiosError, AxiosProgressEvent, AxiosResponse, InternalAxiosRequestConfig } from '@ohos/axios'
+import JGRequest from '../utils/Request';
+
+import { FormData, File, FileUpload } from "@ohos/commons-fileupload"
+
+const logTag = "uploadLog"
+
+
+interface FileResponseModel {
+  code?: string
+  data?: string
+  msg?: string
+}
+
+interface FileModel {
+  fileUrl?: string
+  fileName?: string
+}
+
+
+@Entry
+@Component
+struct Index {
+  @State html: string = "权限状态未知";
+  @State netImageUrl: string = ""
+
+  build() {
+    Column({ space: 10 }) {
+
+      Button("请求权限")
+        .onClick(() => {
+
+          // axios.get("http://10.88.11.200:8078/api/v1/sys/dept/orgList").then((res: AxiosResponse) => {
+          //   console.info(logTag, "测试" + JSON.stringify(res.data));
+          // })
+          //
+          // let formData = new FormData()
+          // let cacheDir = getContext(this).cacheDir
+          //
+          // 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);
+          //
+          //
+          // // formData.append('file', 'internal://cache/blue.jpg')
+          // // formData.append('file', cacheDir + '/hello.txt'); // uri支持传入沙箱路径
+          // formData.append("fdd", "dddd")
+          //
+          // // 发送请求
+          // axios.post<string, AxiosResponse<string>, FormData>('http://10.88.11.200:8078/api/v1/base/upload', formData, {
+          //   headers: {
+          //     'Content-Type': 'multipart/form-data',
+          //     'Authorization': "eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJsb2dpblR5cGUiOiJsb2dpbiIsImxvZ2luSWQiOnsiaWQiOjEwMDAwLCJ1c2VyTmFtZSI6ImFkbWluIiwiZGVwdElkIjoxLCJzdGF0aW9uSWQiOjAsImF2YXRhciI6Ii9qZ2ZpbGUvLzIwMjQvNS8yNy8yNzQzMjkzOTU4Mzg4NTIuanBnIiwib3JnSWQiOjF9LCJkZXZpY2UiOiJiYWNrIiwiZWZmIjoxNzIzOTQ2NTQwNzQxLCJyblN0ciI6InpkOWpKZFlBdVpnR0NEd2xBWnZIcXpkUThBaW9xaUh6In0.8fEZh6HCbkE0kmwF6Ru-1JtVSfQN39mB51pIsI6bzDI"
+          //   },
+          //   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(logTag, "result" + JSON.stringify(res.data));
+          // }).catch((err: AxiosError) => {
+          //   console.error(logTag, "error:" + JSON.stringify(err));
+          // })
+
+
+          // JGRequest.get("/api/v1/sys/dept/orgList")
+          // JGRequest.post("/api/v1/device/config/addBatch")
+          this.openGallery();
+          // JGRequest.post("api/v1/base/upload") // printResponse data {"code":"4106","data":null,"msg":"当前用户未登录或登录已失效"}
+        })
+      Text(this.html)
+    }
+    .width('100%')
+    .height('100%')
+    .padding(10)
+  }
+
+  private async openGallery() {
+    let context = getContext(this) as common.UIAbilityContext;
+    let atManager = abilityAccessCtrl.createAtManager();
+    let info = await bundleManager.getBundleInfoForSelf(0);
+    if (info && info.appInfo) {
+      let result = atManager.verifyAccessTokenSync(info.appInfo.accessTokenId, "ohos.permission.READ_MEDIA");
+      if (abilityAccessCtrl.GrantStatus.PERMISSION_GRANTED == result) {
+        console.log("has permission")
+      }
+    } else {
+      atManager.requestPermissionsFromUser(context, ["ohos.permission.READ_MEDIA"], (error, result) => {
+        if (result) {
+          console.log("result: " + JSON.stringify(result));
+          if (result.authResults[0] == abilityAccessCtrl.GrantStatus.PERMISSION_GRANTED) {
+            // 用户授予权限
+            this.html = "用户已经授权";
+            this.openGalleryInternal();
+          } else {
+            // 用户拒绝权限
+            this.html = "用户拒绝授权";
+            console.log("permission denied")
+          }
+        } else {
+          this.html = "请求授权异常:" + JSON.stringify(error);
+          console.log("error: " + JSON.stringify(error));
+        }
+      });
+    }
+  }
+
+  private openGalleryInternal() {
+    let photoPicker = new picker.PhotoViewPicker();
+    photoPicker.select({
+      MIMEType: picker.PhotoViewMIMETypes.IMAGE_TYPE,
+      maxSelectNumber: 1
+    }, (error, result) => {
+      if (result) {
+        // this.uploadImage(result.photoUris); file://media/Photo/3/IMG_1723222627_002/IMG_20240810_005707.jpg
+        result.photoUris.forEach((url) => {
+          console.log("uploadLog: 选择完图片的路径" + url);
+
+          try {
+            const uri = url
+            // 2.2 根据uri同步打开文件
+            const file = fs.openSync(uri)
+            // 2.3 同步获取文件的详细信息
+            const stat = fs.statSync(file.fd)
+            // 2.4 创建缓冲区存储读取的文件流
+            const buffer = new ArrayBuffer(stat.size)
+            // 2.5 开始同步读取文件流到缓冲区
+            fs.readSync(file.fd, buffer)
+            // 2.6 关闭文件流
+            fs.closeSync(file)
+
+            // 3. 转成base64编码的字符串
+            // const helper = new util.Base64Helper()
+            // const str = helper.encodeToStringSync(new Uint8Array(buffer))
+            console.log('mk-logger', 'photoPlugin-str', buffer.byteLength, JSON.stringify(buffer))
+
+            let toUpFile = new File()
+            toUpFile.fileName = "test.jpg"
+            toUpFile.fileData = buffer
+
+            let fileUpload = new FileUpload({
+              baseUrl: "http://10.88.11.200:8078",
+              readTimeout: 60000,
+              connectTimeout: 60000,
+            })
+
+            const formData = new FormData();
+            // formData.append("key", 1); //可以添加基本类型的值,目前支持string、number
+            formData.append("fileName", "test.jpg"); //也可以添加File类型的对象
+            // formData.append('file', `internal://cache/${fileName}`)
+            formData.append('file', toUpFile)
+
+            fileUpload.post("/api/v1/base/upload", formData, {
+
+              header: {
+                'Content-Type': 'multipart/form-data',
+                'Authorization': "eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJsb2dpblR5cGUiOiJsb2dpbiIsImxvZ2luSWQiOnsiaWQiOjEwMDAwLCJ1c2VyTmFtZSI6ImFkbWluIiwiZGVwdElkIjoxLCJzdGF0aW9uSWQiOjAsImF2YXRhciI6Ii9qZ2ZpbGUvLzIwMjQvNS8yNy8yNzQzMjkzOTU4Mzg4NTIuanBnIiwib3JnSWQiOjF9LCJkZXZpY2UiOiJiYWNrIiwiZWZmIjoxNzIzOTQ2NTQwNzQxLCJyblN0ciI6InpkOWpKZFlBdVpnR0NEd2xBWnZIcXpkUThBaW9xaUh6In0.8fEZh6HCbkE0kmwF6Ru-1JtVSfQN39mB51pIsI6bzDI"
+              },
+            }).then((res: http.HttpResponse) => {
+              let model: FileResponseModel = res.result as FileResponseModel
+
+              // let data: FileModel = JSON.parse(model.data)
+
+              console.log("ddddddd success", JSON.stringify(model));
+
+              // let data: ESObject = res.result as ESObject
+              // // this.netImageUrl = data.data.fileUrl ?? ""
+              // console.error("ddddddd    图片地址:  ", `http://10.88.11.201:9000/${data.data.fileUrl}`);
+            }).catch((err: BusinessError) => {
+              console.error("ddddddd    fail");
+            })
+          }
+          catch (e) {
+            console.log('mk-logger', 'photoPlugin-str', JSON.stringify(e))
+          }
+
+
+          // this.uploadImg3(url)
+          // this.uploadImg2(url)
+        })
+      }
+    });
+  }
+
+  //fileUri是文件选择器返回的路径,格式如下: "datashare:///media/image/45"
+
+  async uploadImg3(fileUri: string) {
+    //      uploadLog: file://media/Photo/2/IMG_1723222626_001/IMG_20240810_005706.jpg
+    //   uploadLog cacheDir /data/storage/el2/base/haps/entry/cache
+    // uploadLog error:{"message":"NetWork is offline","name":"AxiosError","stack":"
+
+    // / 获取应用文件路径
+    const context = getContext(this) as common.UIAbilityContext;
+    let cacheDir = context.cacheDir;
+    console.log(logTag, 'cacheDir', cacheDir);
+    //=>沙箱路径 /应用文件目录 /data/storage/el2/base/haps/entry/cache
+
+    //文件名称,下面这两种方法都可以,原则就是保持名字随机性
+    // let segments = fileUri.split('/')
+    // let fileName = segments[segments.length-1]
+    const fileName = Date.now() + '.jpg'
+    //复制这一步一定不能少 ,简而言之,就是把我们的内部文件拿到外部暴露出来,
+    let realUri = context.cacheDir + "/" + fileName //计划复制到的目标路径
+    try {
+      let file = fs.openSync(fileUri);
+      fs.copyFileSync(file.fd, realUri)
+    } catch (err) {
+      console.info(logTag, 'err:' + JSON.stringify(err));
+    }
+
+
+    // let formData = new FormData()
+    // formData.append('file', `internal://cache/${fileName}`)
+    //
+    // // 发送请求
+    // axios.post<string, AxiosResponse<string>, FormData>('http://10.88.11.200:8078/api/v1/base/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("uploadLog" + JSON.stringify(res.data));
+    // }).catch((err: AxiosError) => {
+    //   console.error("uploadLog:" + JSON.stringify(err));
+    // })
+
+
+    // try {
+    //
+    //   // 第三方库axios请求
+    //   let formData = new FormData();
+    //   formData.append('file', `internal://cache/${fileName}`, fileName);
+    //   // formData.append('fileName', fileName);
+    //   // console.info(logTag, "formData", JSON.stringify(formData));
+    //   //记得替换真实请求地址
+    //   // JGRequest.post()
+    //   JGRequest.post<string, AxiosResponse<string>, FormData>("/api/v1/base/upload", formData, {
+    //     // axios.post<string, AxiosResponse<string>, FormData>("http://10.88.11.200:8078/api/v1/base/upload", formData, {
+    //     headers: {
+    //       'Content-Type': 'multipart/form-data',
+    //       'Authorization': "eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJsb2dpblR5cGUiOiJsb2dpbiIsImxvZ2luSWQiOnsiaWQiOjEwMDAwLCJ1c2VyTmFtZSI6ImFkbWluIiwiZGVwdElkIjoxLCJzdGF0aW9uSWQiOjAsImF2YXRhciI6Ii9qZ2ZpbGUvLzIwMjQvNS8yNy8yNzQzMjkzOTU4Mzg4NTIuanBnIiwib3JnSWQiOjF9LCJkZXZpY2UiOiJiYWNrIiwiZWZmIjoxNzIzOTQ2NTQwNzQxLCJyblN0ciI6InpkOWpKZFlBdVpnR0NEd2xBWnZIcXpkUThBaW9xaUh6In0.8fEZh6HCbkE0kmwF6Ru-1JtVSfQN39mB51pIsI6bzDI"
+    //     },
+    //     context: getContext(this),
+    //     onUploadProgress: (progressEvent: AxiosProgressEvent): void => {
+    //       console.info(logTag, progressEvent && progressEvent.loaded && progressEvent.total ? Math.ceil(progressEvent.loaded / progressEvent.total * 100) + '%' : '0%');
+    //     },
+    //   }).then((res: AxiosResponse) => {
+    //     interface pathType {
+    //       filePath: string
+    //     }
+    //
+    //     interface dataType {
+    //       data: pathType
+    //     }
+    //
+    //     const data: dataType = res.data as dataType
+    //     const path = data.data.filePath
+    //     console.info(logTag, "request result", path);
+    //   }).catch((error: AxiosError) => {
+    //     console.error(logTag, "11111error:" + JSON.stringify(error));
+    //   })
+    // } catch (err) {
+    //   console.error(logTag, `axios Failed to request the upload. err: ${JSON.stringify(err)}`);
+    // }
+
+
+  }
+
+  // async uploadImg2(fileUri: string) {
+  //   // uploadLog Failed to request the upload. Code: undefined, message: Cannot read property on of undefined
+  //   // / 获取应用文件路径
+  //   const context = getContext(this) as common.UIAbilityContext;
+  //   let cacheDir = context.cacheDir;
+  //   console.log(logTag, 'cacheDir', cacheDir);
+  //   //=>沙箱路径 /应用文件目录 /data/storage/el2/base/haps/entry/cache
+  //
+  //   //文件名称,下面这两种方法都可以,原则就是保持名字随机性
+  //   // let segments = fileUri.split('/')
+  //   // let fileName = segments[segments.length-1]
+  //   const fileName = Date.now() + '.jpg'
+  //   //复制这一步一定不能少 ,简而言之,就是把我们的内部文件拿到外部暴露出来,
+  //   let realUri = context.cacheDir + "/" + fileName //计划复制到的目标路径
+  //   try {
+  //     let file = fs.openSync(fileUri);
+  //     fs.copyFileSync(file.fd, realUri)
+  //   } catch (err) {
+  //     console.info(logTag, 'err:' + JSON.stringify(err));
+  //   }
+  //
+  //
+  //   // // 鸿蒙自带请求
+  //   let uploadTask: request.UploadTask;
+  //   let uploadConfig: request.UploadConfig = {
+  //     url: "http://10.88.11.200:8078/api/v1/base/upload", //需要手动替换为真实服务器地址
+  //     header: { 'Content-Type': 'multipart/form-data' },
+  //     method: "POST",
+  //     files: [{ filename: fileName, name: "file", uri: `internal://cache/${fileName}`, type: "jpg" }],
+  //     //注意这里,files里面的url一定是'internal://cache/'和文件名的拼接,不要拼其他路径!!!
+  //     data: [],
+  //   };
+  //   //一定要定义类型,这里的类型定义真的很让人头大
+  //   interface path {
+  //     filePath: string
+  //   }
+  //
+  //   interface bodyType {
+  //     code: string
+  //     success: string
+  //     data: path
+  //   }
+  //
+  //   interface resType {
+  //     body: bodyType
+  //   }
+  //
+  //   try {
+  //     request.uploadFile(context, uploadConfig).then((data: request.UploadTask) => {
+  //       uploadTask.on('headerReceive', (header: object) => {
+  //         const picRes: resType = header as resType
+  //         console.log(logTag, '上传头picRes', picRes.body)
+  //       })
+  //       uploadTask.on("complete", () => {
+  //         // promptAction.showToast({ message: '上传成功!', duration: 2000 })
+  //         // 上传成功调接口
+  //       })
+  //     }).catch((err: BusinessError) => {
+  //       console.error(logTag, `Failed to request the upload. Code: ${err.code}, message: ${err.message}`);
+  //     });
+  //   } catch (err) {
+  //     console.error(logTag, ` err: ${JSON.stringify(err)}`);
+  //   }
+  //
+  // }
+
+  // private uploadImage(paths: string[]) {
+  //   let allFiles = Array<request.File>()
+  //
+  //   for (let i = 0; i < paths.length; i++) {
+  //     let path = paths[i]
+  //     console.log(logTag, "path: " + path)
+  //     allFiles[i] = {
+  //       name: "image" + i + ".jpg",
+  //       filename: "image" + i + ".jpg",
+  //       uri: path,
+  //       type: "image"
+  //     }
+  //   }
+  //
+  //
+  //   try {
+  //
+  //     request.uploadFile(getContext(this), {
+  //       url: "http://10.88.20.188:8079/api/v1/base/upload",
+  //       method: http.RequestMethod.POST,
+  //       files: allFiles,
+  //       header: {
+  //         'Content-Type': 'multipart/form-data',
+  //       },
+  //       data: [
+  //         {
+  //           name: "file",
+  //           value: "file"
+  //         }
+  //       ]
+  //     }, (error, response) => {
+  //       console.log(logTag, "response", JSON.stringify(error), JSON.stringify(response))
+  //       if (response) {
+  //         response.on('progress', (uploadedSize: number, totalSize: number) => {
+  //           console.log(logTag, "progress, uploadedSize: " + uploadedSize + ", totalSize: " + totalSize)
+  //         })
+  //       } else {
+  //         console.log(logTag, "upload failure: " + error)
+  //       }
+  //     });
+  //
+  //   } catch (err) {
+  //     console.error(logTag, `xx Invoke uploadFile failed, code is ${err.code}, message is ${err.message}`);
+  //
+  //   }
+  //
+  //
+  // }
+}

+ 193 - 0
entry/src/main/ets/pages/TooSimplePage.ets

@@ -0,0 +1,193 @@
+import picker from '@ohos.file.picker';
+import common from '@ohos.app.ability.common';
+import fs from '@ohos.file.fs';
+import request from '@ohos.request';
+import { BusinessError } from '@ohos.base';
+
+import abilityAccessCtrl from '@ohos.abilityAccessCtrl';
+import bundleManager from '@ohos.bundle.bundleManager';
+
+import axios, { AxiosError, AxiosProgressEvent, AxiosResponse, FormData, InternalAxiosRequestConfig } from '@ohos/axios'
+import JGRequest from '../utils/Request';
+
+// 获取应用文件路径
+let context = getContext(this) as common.UIAbilityContext;
+let cacheDir = context.cacheDir;
+const logTag = "uploadLog"
+
+// 上传任务配置项
+
+
+// interface UploadConfig {
+//   url?: string,
+//   header?: ESObject,
+//   method?: string,
+//   files?: ESObject,
+//   data?: []
+// }
+
+// let uploadConfig: Upl = {
+//   url: 'http://192.168.3.48:8740/file/upload',
+//   header: { key1: 'Content-Type', key2: 'multipart/form-data' } as ESObject,
+//   method: 'POST',
+//   files: [
+//     { filename: 'test.jpg', name: 'test', uri: 'internal://cache/test.jpg', type: 'jpg' }
+//   ],
+//   data: [
+//     { name: 'fileId', value: 'FP000008' }
+//   ]
+// }
+
+@Entry
+@Component
+struct Index {
+  @State message: string = ''
+  @State imgSrc: string = ''
+
+  private async openGallery() {
+    let context = getContext(this) as common.UIAbilityContext;
+    let atManager = abilityAccessCtrl.createAtManager();
+    let info = await bundleManager.getBundleInfoForSelf(0);
+    if (info && info.appInfo) {
+      let result = atManager.verifyAccessTokenSync(info.appInfo.accessTokenId, "ohos.permission.READ_MEDIA");
+      if (abilityAccessCtrl.GrantStatus.PERMISSION_GRANTED == result) {
+        console.log("has permission")
+      }
+    } else {
+      atManager.requestPermissionsFromUser(context, ["ohos.permission.READ_MEDIA"], (error, result) => {
+        if (result) {
+          console.log("result: " + JSON.stringify(result));
+          if (result.authResults[0] == abilityAccessCtrl.GrantStatus.PERMISSION_GRANTED) {
+            // 用户授予权限
+            this.selectImage();
+          } else {
+            // 用户拒绝权限
+            console.log("permission denied")
+          }
+        } else {
+        }
+      });
+    }
+  }
+
+  async selectImage() {
+    try {
+      let PhotoSelectOptions = new picker.PhotoSelectOptions();
+      PhotoSelectOptions.MIMEType = picker.PhotoViewMIMETypes.IMAGE_TYPE;
+      PhotoSelectOptions.maxSelectNumber = 1;
+      let photoPicker = new picker.PhotoViewPicker();
+      photoPicker.select(PhotoSelectOptions).then((PhotoSelectResult) => {
+        console.info('xx PhotoViewPicker.select successfully, PhotoSelectResult uri: ' + JSON.stringify(PhotoSelectResult));
+        // 从图库选择图片后,返回图片uri
+        let uri = PhotoSelectResult.photoUris[0];
+        console.info('xx uri:' + uri)
+        this.imgSrc = uri
+        // 读取上面返回uri
+        let file = fs.openSync(uri, fs.OpenMode.CREATE);
+        // 复制文件到缓存目录下
+        fs.copyFileSync(file.fd, cacheDir + '/test.jpg')
+        // 上传文件到服务器上
+        this.uploadImage()
+      }).catch((err: BusinessError) => {
+        console.error('xx PhotoViewPicker.select failed with err: ' + err);
+      });
+    } catch (err) {
+      console.error('xx PhotoViewPicker failed with err: ' + err);
+    }
+  }
+
+  uploadImage() {
+
+    // let formData = new FormData();
+    // formData.append('file', `internal://cache/test.jpg`);
+    // formData.append('fileName', "test");
+    //
+    //
+    // JGRequest.post<string, AxiosResponse<string>, FormData>("api/v1/base/upload", formData, {
+    //   headers: {
+    //     'Content-Type': 'multipart/form-data',
+    //     'Authorization': "eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJsb2dpblR5cGUiOiJsb2dpbiIsImxvZ2luSWQiOnsiaWQiOjEwMDAwLCJ1c2VyTmFtZSI6ImFkbWluIiwiZGVwdElkIjoxLCJzdGF0aW9uSWQiOjAsImF2YXRhciI6Ii9qZ2ZpbGUvLzIwMjQvNS8yNy8yNzQzMjkzOTU4Mzg4NTIuanBnIiwib3JnSWQiOjF9LCJkZXZpY2UiOiJiYWNrIiwiZWZmIjoxNzIzOTQ2NTQwNzQxLCJyblN0ciI6InpkOWpKZFlBdVpnR0NEd2xBWnZIcXpkUThBaW9xaUh6In0.8fEZh6HCbkE0kmwF6Ru-1JtVSfQN39mB51pIsI6bzDI"
+    //   },
+    //   context: getContext(this),
+    //   onUploadProgress: (progressEvent: AxiosProgressEvent): void => {
+    //     console.info(logTag, progressEvent && progressEvent.loaded && progressEvent.total ? Math.ceil(progressEvent.loaded / progressEvent.total * 100) + '%' : '0%');
+    //   },
+    // }).then((res: AxiosResponse) => {
+    //   interface pathType {
+    //     filePath: string
+    //   }
+    //
+    //   interface dataType {
+    //     data: pathType
+    //   }
+    //
+    //   const data: dataType = res.data as dataType
+    //   const path = data.data.filePath
+    //   console.info(logTag, "request result", path);
+    // }).catch((error: AxiosError) => {
+    //   console.error(logTag, "11111error:" + JSON.stringify(error));
+    // })
+    //
+    // return
+
+
+    // 将本地应用文件上传至网络服务器
+    try {
+      request.uploadFile(context, {
+        url: 'http://10.88.11.200:8078/api/v1/base/upload',
+        header: {
+          'Content-Type': 'multipart/form-data',
+          'Authorization': "eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJsb2dpblR5cGUiOiJsb2dpbiIsImxvZ2luSWQiOnsiaWQiOjEwMDAwLCJ1c2VyTmFtZSI6ImFkbWluIiwiZGVwdElkIjoxLCJzdGF0aW9uSWQiOjAsImF2YXRhciI6Ii9qZ2ZpbGUvLzIwMjQvNS8yNy8yNzQzMjkzOTU4Mzg4NTIuanBnIiwib3JnSWQiOjF9LCJkZXZpY2UiOiJiYWNrIiwiZWZmIjoxNzIzOTQ2NTQwNzQxLCJyblN0ciI6InpkOWpKZFlBdVpnR0NEd2xBWnZIcXpkUThBaW9xaUh6In0.8fEZh6HCbkE0kmwF6Ru-1JtVSfQN39mB51pIsI6bzDI"
+        },
+        method: 'POST',
+        files: [
+          { filename: 'test.jpg', name: 'test', uri: 'internal://cache/test.jpg', type: 'jpg' }
+        ],
+        data: [
+          { name: 'fileId', value: 'FP000008' }
+        ]
+      })
+        .then((uploadTask) => {
+          uploadTask.on('complete', (taskStates) => {
+            for (let i = 0; i < taskStates.length; i++) {
+              console.info(logTag, `xx upload complete taskState: ${JSON.stringify(taskStates[i])}`);
+              this.message = JSON.stringify(taskStates[i])
+            }
+          });
+          uploadTask.on('progress', (uploadedSize: number, totalSize: number) => {
+            console.info(logTag, `progress: ${totalSize} --- ${uploadedSize}`);
+          })
+          uploadTask.on('fail', (taskStates) => {
+            for (let i = 0; i < taskStates.length; i++) {
+              console.info(logTag, `fail: ${JSON.stringify(taskStates[i])}`);
+              this.message = JSON.stringify(taskStates[i])
+            }
+          });
+
+        })
+        .catch((err: BusinessError) => {
+          console.error(logTag, `failed, code is ${err.code}, message is ${err.message}`);
+          this.message = err.message
+        })
+    } catch (err) {
+      console.error(logTag, ` ERROR, code is ${err.code}, message is ${err.message}`);
+      this.message = err.message
+    }
+  }
+
+  build() {
+    Column({ space: 30 }) {
+      Button('打开图库')
+        .width('80%').height('40')
+        .onClick(() => {
+          this.openGallery()
+        })
+      Image(this.imgSrc)
+        .width('50%').height('50%')
+      Text(this.message)
+        .fontSize(20).width('100%')
+    }
+    .width('100%').height('100%')
+    .padding(10)
+  }
+}

+ 61 - 0
entry/src/main/ets/pages/WebTestPage.ets

@@ -0,0 +1,61 @@
+// xxx.ets
+import web_webview from '@ohos.web.webview';
+import abilityAccessCtrl, { PermissionRequestResult, Permissions } from '@ohos.abilityAccessCtrl';
+
+@Entry
+@Component
+struct WebComponent {
+  controller: web_webview.WebviewController = new web_webview.WebviewController()
+
+  aboutToAppear() {
+    // 配置Web开启调试模式
+    web_webview.WebviewController.setWebDebuggingAccess(true);
+    let atManager = abilityAccessCtrl.createAtManager();
+    atManager.requestPermissionsFromUser(getContext(this), ['ohos.permission.CAMERA', 'ohos.permission.MICROPHONE'])
+      .then(data => {
+        let result: Array<number> = data.authResults;
+        let hasPermissions1 = true;
+        result.forEach(item => {
+          if (item === -1) {
+            hasPermissions1 = false;
+          }
+        })
+        if (hasPermissions1) {
+          console.info("hasPermissions1")
+        } else {
+          console.info(" not hasPermissions1")
+        }
+      }).catch(() => {
+      return;
+    });
+  }
+
+  build() {
+    Column() {
+      Web({ src: $rawfile('camera.html'), controller: this.controller })
+        .onPermissionRequest((event) => {
+          if (event) {
+            AlertDialog.show({
+              title: 'title',
+              message: 'text',
+              primaryButton: {
+                value: 'deny',
+                action: () => {
+                  event.request.deny()
+                }
+              },
+              secondaryButton: {
+                value: 'onConfirm',
+                action: () => {
+                  event.request.grant(event.request.getAccessibleResource())
+                }
+              },
+              cancel: () => {
+                event.request.deny()
+              }
+            })
+          }
+        })
+    }
+  }
+}

+ 44 - 0
entry/src/main/ets/utils/Logger.ts

@@ -0,0 +1,44 @@
+/*
+ * Copyright (c) 2022 Huawei Device Co., Ltd.
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+import hilog from '@ohos.hilog';
+
+class Logger {
+  private domain: number;
+  private prefix: string;
+  private format: string = "%{public}s, %{public}s";
+
+  constructor(prefix: string) {
+    this.prefix = prefix;
+    this.domain = 0xFF00;
+  }
+
+  debug(...args: any[]) {
+    hilog.debug(this.domain, this.prefix, this.format, args);
+  }
+
+  info(...args: any[]) {
+    hilog.info(this.domain, this.prefix, this.format, args);
+  }
+
+  warn(...args: any[]) {
+    hilog.warn(this.domain, this.prefix, this.format, args);
+  }
+
+  error(...args: any[]) {
+    hilog.error(this.domain, this.prefix, this.format, args);
+  }
+}
+
+export default new Logger('[Camera]');

+ 94 - 0
entry/src/main/ets/utils/Request.ets

@@ -0,0 +1,94 @@
+import axios, {
+  AxiosError,
+  AxiosResponse,
+  AxiosRequestHeaders,
+  AxiosRequestConfig,
+  CreateAxiosDefaults,
+  InternalAxiosRequestConfig
+} from '@ohos/axios';
+
+//import PreferencesUtil from '../PreferencesUtil';
+import { printError, printRequest, printResponse, handleRes } from './Helps';
+import RequestParamsModel from './requestParams';
+
+// const baseUrl = "http://10.88.20.188:8079/"
+const baseUrl = "http://10.88.11.200:8078/"
+const DEBUG = true //
+
+// 创建实例
+const JGRequest = axios.create(
+  {
+    baseURL: baseUrl,
+    headers: {
+      'Content-Type': 'application/json;charset=UTF-8',
+    },
+    timeout: 60 * 1000,
+  }
+)
+
+// 添加请求拦截器
+JGRequest.interceptors.request.use((config: InternalAxiosRequestConfig) => {
+
+  // 以后登录之后可以在这里传
+  // config.headers.Authorization = ""
+  config.headers.Authorization = ""
+  printRequest(config)
+
+  return config;
+}, (error: AxiosError) => {
+  // 对请求错误做些什么
+  printError(error)
+  return Promise.reject(error);
+});
+// 添加响应拦截器
+JGRequest.interceptors.response.use((response: AxiosResponse) => {
+  // 对响应数据做点什么
+  printResponse(response)
+
+  let res = handleRes(response)
+  let success = res[0] as boolean
+  let msg = res[1] as string
+  // console.debug("handleRes的返回结果 ", success, msg)
+
+  if (success) {
+    return response.data.data;
+  }
+  else {
+    return Promise.reject<string>(msg)
+  }
+
+}, (error: AxiosError) => {
+  // 对响应错误做点什么
+  printError(error)
+
+  return Promise.reject(error);
+});
+
+// // 添加响应拦截器
+// JGRequest.interceptors.response.use((response: AxiosResponse)=> {
+//   // 对响应数据做点什么
+//   printResponse(response)
+//
+//   let [success, msg] = handleRes(response)
+//   // console.debug("handleRes的返回结果 ", success, msg)
+//
+//   if (success) {
+//     return response.data.data;
+//   }
+//   else {
+//     return Promise.reject(msg)
+//   }
+//
+// }, (error:AxiosError)=> {
+//   // 对响应错误做点什么
+//   printError(error)
+//
+//   return Promise.reject(error);
+// });
+
+
+export default JGRequest;
+
+
+
+

+ 108 - 0
entry/src/main/ets/utils/helps.ets

@@ -0,0 +1,108 @@
+import { InternalAxiosRequestConfig, AxiosResponse, AxiosError } from "@ohos/axios"
+import promptAction from '@ohos.promptAction'
+
+// 是否在控制台打印某项log
+const pConfig = true
+const pHeaders = true
+const pUrl = true
+const pParams = true
+const pBody = true
+const pResponse = true
+const pData = true
+const pError = true
+
+// @CustomDialog
+// struct CustomDialogExample {
+//   controller: CustomDialogController
+//   build() {
+//     Column() {
+//       Text('我是内容')
+//         .fontSize(20)
+//         .margin({ top: 10, bottom: 10 })
+//     }
+//   }
+// }
+
+const printRequest = (config: InternalAxiosRequestConfig) => {
+  if (pConfig) {
+    console.debug("printRequest config", JSON.stringify(config))
+  }
+
+  if (pHeaders) {
+    console.debug("printRequest headers", JSON.stringify(config.headers))
+  }
+
+  if (pUrl) {
+    console.debug("printRequest url", `Method:${config.method} ${config.baseURL}${config.url}`)
+  }
+
+  if (pBody) {
+    console.debug("printRequest 请求参数data", JSON.stringify(config.data))
+  }
+
+  if (pParams) {
+    console.debug("printRequest 请求参数params", JSON.stringify(config.params))
+  }
+
+}
+
+const printResponse = (response: AxiosResponse) => {
+  if (pResponse) {
+    console.debug('handleRes response: ', JSON.stringify(response))
+  }
+  if (pData) {
+    console.debug("printResponse data", JSON.stringify(response.data))
+  }
+}
+
+const printError = (error: AxiosError) => {
+  if (pError) {
+    console.debug("printError error", error.message)
+  }
+  promptAction.showToast({
+    message: error.message ?? "请求出错",
+    duration: 1500,
+    bottom: 100
+  })
+}
+
+
+// 处理返回数据
+const handleRes = (response: AxiosResponse): [boolean, string] => {
+  let isSuccess = true
+  let msg = ""
+
+  if (response.status === 200) { //判断返回状态是否为200
+    if (String(response.data?.code) === "200") { //判断数据的code是否为200,有可能是500的服务器错误
+      isSuccess = true
+      msg = `请求数据成功`
+    }
+    else {
+      isSuccess = false
+      // msg = `${response.data?.code}: ${response.data?.msg ?? "服务器错误"}`
+      msg = `${response.data?.msg ?? "服务器错误"}`
+    }
+  }
+  else {
+    isSuccess = false
+    msg = `状态码非200 status: ${response.status}}`
+  }
+
+  if (!isSuccess) {
+    promptAction.showToast({
+      message: msg,
+      duration: 1500,
+      bottom: 100
+    })
+
+    // const dialogController: CustomDialogController = new CustomDialogController({
+    //   builder: CustomDialogExample({}),
+    // })
+    // dialogController.open()
+  }
+
+  return [isSuccess, msg]
+}
+
+
+export { printRequest, printResponse, printError, handleRes }

+ 3 - 0
entry/src/main/ets/utils/requestParams.ets

@@ -0,0 +1,3 @@
+export default class RequestParamsModel {
+  static token: string = ''
+}

+ 19 - 1
entry/src/main/module.json5

@@ -44,7 +44,7 @@
           "abilities": [
             "EntryAbility"
           ],
-          "when": "inuse"
+          "when": "always"
         }
       },
       {
@@ -52,6 +52,24 @@
       },
       {
         "name": "ohos.permission.GET_NETWORK_INFO"
+      },
+      {
+        "name": "ohos.permission.START_INVISIBLE_ABILITY",
+      },
+      {
+        "name": "ohos.permission.CAMERA"//允许应用使用相机拍摄照片和录制视频
+      },
+      {
+        "name": "ohos.permission.MICROPHONE"//允许应用使用麦克风
+      },
+      {
+        "name": "ohos.permission.MEDIA_LOCATION"//允许应用访问用户媒体文件中的地理位置信息
+      },
+      {
+        "name": "ohos.permission.WRITE_MEDIA"//允许应用读写用户外部存储中的媒体文件信息
+      },
+      {
+        "name": "ohos.permission.READ_MEDIA"//允许应用读取用户外部存储中的媒体文件信息
       }
 
       //      {

+ 6 - 2
entry/src/main/resources/base/profile/main_pages.json

@@ -1,5 +1,9 @@
 {
   "src": [
-    "pages/Index"
+    "pages/Index",
+    "pages/WebTestPage",
+    "pages/SelectAlbumPage",
+    "pages/TooSimplePage",
+    "pages/Base64Page"
   ]
-}
+}

+ 37 - 0
entry/src/main/resources/rawfile/camera.html

@@ -0,0 +1,37 @@
+<!-- index.html -->
+<!DOCTYPE html>
+<html>
+<head>
+    <meta charset="UTF-8">
+</head>
+<body>
+<video id="video" width="500px" height="500px" style="border: 1px solid red" autoplay="autoplay"></video>
+<canvas id="canvas" width="500px" height="500px"></canvas>
+<p id="content">fffff</p>
+<br>
+<input type="button" title="HTML5摄像头" value="开启摄像头" onclick="getMedia()"/>
+<script>
+  function getMedia()
+  {
+    let constraints = {
+      video: {width: 500, height: 500},
+      audio: true
+    };
+    // 获取video摄像头区域
+    let video = document.getElementById("video");
+    // 返回的Promise对象
+    let promise = navigator.mediaDevices.getUserMedia(constraints);
+    // then()异步,调用MediaStream对象作为参数
+    promise.then(function (MediaStream) {
+       document.getElementById("content").innerHtml = JSON.stringfy(MediaStream)
+      video.srcObject = MediaStream;
+      video.play();
+    });
+  }
+
+
+
+
+</script>
+</body>
+</html>

+ 63 - 0
entry/src/main/resources/rawfile/doc.html

@@ -0,0 +1,63 @@
+<!DOCTYPE html>
+<html lang="en">
+<head>
+    <meta charset="UTF-8">
+    <meta name="viewport" content="width=device-width, initial-scale=1.0">
+    <title>File Input Example</title>
+</head>
+<body>
+<input type="file" id="fileInput" onchange="displayFileName()">
+<div id="fileNameDisplay"></div>
+<button onclick="invokeJS()">调用原生的方法</button>
+<button onclick="selectFile()">Select File</button>
+<div id="fileDisplay"></div>
+
+<script>
+        function displayFileName() {
+            const fileInput = document.getElementById('fileInput');
+            const fileNameDisplay = document.getElementById('fileNameDisplay');
+            if (fileInput.files.length > 0) {
+                fileNameDisplay.textContent = fileInput.files[0].name;
+            } else {
+                fileNameDisplay.textContent = '';
+            }
+        }
+
+        function invokeJS() {
+           openHarmonyBridge.download(JSON.stringify({
+              token: "ddddd",
+              path: "这是路径"
+            }));
+        }
+
+        function selectFile() {
+            const fileInput = document.getElementById('fileInput');
+            fileInput.click();
+        }
+
+        document.getElementById('fileInput').addEventListener('change', function() {
+            const fileDisplay = document.getElementById('fileDisplay');
+            const fileInput = document.getElementById('fileInput');
+            if (fileInput.files.length > 0) {
+                const file = fileInput.files[0];
+                const reader = new FileReader();
+                reader.onload = function(e) {
+                    fileDisplay.textContent = e.target.result;
+                };
+                reader.readAsText(file);
+            } else {
+                fileDisplay.textContent = '';
+            }
+            console.log("dddd")
+        });
+
+
+
+
+
+
+
+
+</script>
+</body>
+</html>

+ 8 - 4
entry/src/main/resources/rawfile/download.html

@@ -1,16 +1,20 @@
 <!DOCTYPE html>
 <html>
 <body>
-<button type="button" onclick="callArkTS()">Click Me!</button>
+<button type="button" onclick="callArkTS()" style="width: 500px;height: 500px">执行Register的方法</button>
 <p id="demo"></p>
 <script>
     function callArkTS() {
-        let str = testObjName.test("哈哈哈哈哈哈");
-        document.getElementById("demo").innerHTML = str;
-        console.info({message: 'ArkTS Hello World!'});
+
+      window.openHarmonyBridge.download("哈哈哈哈哈哈");
+
+
+
     }
 
 
+
+
 </script>
 </body>
 </html>

+ 35 - 13
entry/src/main/resources/rawfile/local.html

@@ -3,23 +3,45 @@
 <head>
     <meta charset="UTF-8">
     <meta name="viewport" content="width=device-width, initial-scale=1.0">
-    <title>File Selector</title>
-    <script>
-        function handleFileSelect(evt) {
-            const files = evt.target.files; // FileList object
-            for (let i = 0, f; f = files[i]; i++) {
-                document.getElementById('output').innerHTML += `<p>${f.name}</p>`;
+    <title>File Input Example</title>
+</head>
+<body>
+<input type="file" id="fileInput" onchange="displayFileName()">
+<div id="fileNameDisplay"></div>
+<button onclick="selectFile()">Select File</button>
+<div id="fileDisplay"></div>
+
+<script>
+        function displayFileName() {
+            const fileInput = document.getElementById('fileInput');
+            const fileNameDisplay = document.getElementById('fileNameDisplay');
+            if (fileInput.files.length > 0) {
+                fileNameDisplay.textContent = fileInput.files[0].name;
+            } else {
+                fileNameDisplay.textContent = '';
             }
         }
 
-        document.addEventListener('DOMContentLoaded', (event) => {
-            document.getElementById('files').addEventListener('change', handleFileSelect, false);
+        function selectFile() {
+            const fileInput = document.getElementById('fileInput');
+            fileInput.click();
+        }
+
+        document.getElementById('fileInput').addEventListener('change', function() {
+            const fileDisplay = document.getElementById('fileDisplay');
+            const fileInput = document.getElementById('fileInput');
+            if (fileInput.files.length > 0) {
+                const file = fileInput.files[0];
+                const reader = new FileReader();
+                reader.onload = function(e) {
+                    fileDisplay.textContent = e.target.result;
+                };
+                reader.readAsText(file);
+            } else {
+                fileDisplay.textContent = '';
+            }
         });
 
-    </script>
-</head>
-<body>
-<input type="file" id="files" name="files[]" multiple/>
-<output id="output"></output>
+</script>
 </body>
 </html>

+ 23 - 1
oh-package-lock.json5

@@ -2,7 +2,10 @@
   "lockfileVersion": 2,
   "ATTENTION": "THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY.",
   "specifiers": {
-    "@ohos/hypium@1.0.13": "@ohos/hypium@1.0.13"
+    "@ohos/hypium@1.0.13": "@ohos/hypium@1.0.13",
+    "@ohos/axios@2.2.0-rc.4": "@ohos/axios@2.2.0-rc.4",
+    "mime-db@1.52.0": "mime-db@1.52.0",
+    "@ohos/commons-fileupload@^1.0.0": "@ohos/commons-fileupload@1.0.0"
   },
   "packages": {
     "@ohos/hypium@1.0.13": {
@@ -10,6 +13,25 @@
       "integrity": "sha512-d0+XvDeAYk5Vgl6JQ8Q1G+NPmTyJI8qgZ1PwPfcUbx/dfyKVAAv9lz1XtVNhYypyWEKqAzu8zMAC9GuHo2Y53Q==",
       "registryType": "ohpm",
       "shasum": "88d8dda420097efb98d770bf59616faef4682f06"
+    },
+    "@ohos/axios@2.2.0-rc.4": {
+      "resolved": "https://ohpm.openharmony.cn/ohpm/@ohos/axios/-/axios-2.2.0-rc.4.har",
+      "integrity": "sha512-lLAMr4pzAREk59bDoa3/3FrrOW17mLjGKb0fb+tB5EAtI8Pw8XWcvIqIi5zFRNlbABbyiyiUwiExB8BpzEeqtg==",
+      "registryType": "ohpm"
+    },
+    "@ohos/commons-fileupload@1.0.0": {
+      "resolved": "https://ohpm.openharmony.cn/ohpm/@ohos/commons-fileupload/-/commons-fileupload-1.0.0.har",
+      "integrity": "sha512-HxXyg9C+YZcy/6z5I0hZxc5YCOoC5x3m2dlU74TVGmi1hVkfkO7kzJl+jOuUtm83QOaNmJ5S1ZfHSZDpuZVo3g==",
+      "dependencies": {
+        "mime-db": "1.52.0"
+      },
+      "registryType": "ohpm"
+    },
+    "mime-db@1.52.0": {
+      "resolved": "https://ohpm.openharmony.cn/ohpm/mime-db/-/mime-db-1.52.0.tgz",
+      "integrity": "sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==",
+      "registryType": "ohpm",
+      "shasum": "bbabcdc02859f4987301c856e3387ce5ec43bf70"
     }
   }
 }

+ 4 - 1
oh-package.json5

@@ -7,8 +7,11 @@
   "author": "",
   "license": "",
   "dependencies": {
+    "@ohos/axios": "2.2.0-rc.4",
+    "@ohos/commons-fileupload": "^1.0.0"
   },
   "devDependencies": {
     "@ohos/hypium": "1.0.13"
-  }
+  },
+  "dynamicDependencies": {}
 }