|
|
@@ -0,0 +1,181 @@
|
|
|
+import axios, { AxiosProgressEvent } from '@ohos/axios';
|
|
|
+import { fileIo, fileUri } from '@kit.CoreFileKit';
|
|
|
+import { camera, cameraPicker as picker } from '@kit.CameraKit';
|
|
|
+import { util } from '@kit.ArkTS';
|
|
|
+import { photoAccessHelper } from '@kit.MediaLibraryKit';
|
|
|
+import { image } from '@kit.ImageKit';
|
|
|
+import { BusinessError } from '@kit.BasicServicesKit';
|
|
|
+import { YTLog } from '../../../../Index';
|
|
|
+
|
|
|
+/**
|
|
|
+ * @method cashPhotos 传入需要下载得url数组并下载文件,通过回调函数返回对应cashPaths数组
|
|
|
+ * @method takePicture 拍照获取图片
|
|
|
+ * @method selectImage 从相册选择图片
|
|
|
+ * @method saveByShowAssetsCreationDialog 通过ShowAssetsCreationDialog保存文件(弹窗)
|
|
|
+ * @method getPhotoFileBuffer 将缓存的图片转化为流
|
|
|
+ * @method saveImgToAssets 直接保存图片至相册 需要权限
|
|
|
+ */
|
|
|
+export class YTPhotoHelper {
|
|
|
+ private cashPaths: string[] = []
|
|
|
+ private currentIndex: number = 0
|
|
|
+ private readonly context: Context
|
|
|
+
|
|
|
+ constructor(context: Context) {
|
|
|
+ this.context = context
|
|
|
+ }
|
|
|
+
|
|
|
+ //传入需要下载得url数组并下载文件,通过回调函数返回对应cashPaths数组
|
|
|
+ async cashPhotos(urls: string[], finishDownLoad: (cashPaths: string[]) => void, cashPhotoType: string = '.jpg') {
|
|
|
+ let filePath = this.context.cacheDir + '/' + util.generateRandomUUID() + cashPhotoType
|
|
|
+ // Download the file. If the file already exists, delete the existing one first.
|
|
|
+ try {
|
|
|
+ fileIo.accessSync(filePath);
|
|
|
+ fileIo.unlinkSync(filePath);
|
|
|
+ } catch (err) {
|
|
|
+ YTLog.error(err)
|
|
|
+ }
|
|
|
+
|
|
|
+ await axios({
|
|
|
+ url: urls[this.currentIndex],
|
|
|
+ method: 'get',
|
|
|
+ context: getContext(this),
|
|
|
+ filePath: filePath,
|
|
|
+ onDownloadProgress: (progressEvent: AxiosProgressEvent): void => {
|
|
|
+ YTLog.info("progress: " + progressEvent && progressEvent.loaded && progressEvent.total ?
|
|
|
+ Math.ceil(progressEvent.loaded / progressEvent.total * 100) : 0)
|
|
|
+ }
|
|
|
+ })
|
|
|
+ this.currentIndex++
|
|
|
+ this.cashPaths.unshift(filePath)
|
|
|
+ if (this.currentIndex < urls.length) {
|
|
|
+ this.cashPhotos(urls, finishDownLoad, cashPhotoType)
|
|
|
+ } else {
|
|
|
+ finishDownLoad(this.cashPaths)
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ //拍照获取图片
|
|
|
+ async takePicture() {
|
|
|
+ let pathDir = this.context.filesDir;
|
|
|
+ let fileName = `${new Date().getTime()}`
|
|
|
+ let filePath = pathDir + `/${fileName}.png`
|
|
|
+ fileIo.createRandomAccessFileSync(filePath, fileIo.OpenMode.CREATE);
|
|
|
+
|
|
|
+ let uri = fileUri.getUriFromPath(filePath);
|
|
|
+ let pickerProfile: picker.PickerProfile = {
|
|
|
+ cameraPosition: camera.CameraPosition.CAMERA_POSITION_BACK,
|
|
|
+ saveUri: uri
|
|
|
+ };
|
|
|
+ let result: picker.PickerResult =
|
|
|
+ await picker.pick(this.context, [picker.PickerMediaType.PHOTO], //(如果需要录像可以添加) picker.PickerMediaType.VIDEO
|
|
|
+ pickerProfile);
|
|
|
+ if (!result.resultUri) {
|
|
|
+ return Promise.reject('用户未拍照')
|
|
|
+ }
|
|
|
+ return filePath
|
|
|
+ }
|
|
|
+
|
|
|
+ //从相册选择图片
|
|
|
+ selectImage(success: (fullPath: string) => void) {
|
|
|
+ const option = new photoAccessHelper.PhotoSelectOptions()
|
|
|
+ option.MIMEType = photoAccessHelper.PhotoViewMIMETypes.IMAGE_TYPE
|
|
|
+ option.maxSelectNumber = 1
|
|
|
+ const picker = new photoAccessHelper.PhotoViewPicker()
|
|
|
+ picker.select(option)
|
|
|
+ .then(res => {
|
|
|
+ const photoName = util.generateRandomUUID()
|
|
|
+ const photoType = '.' + res.photoUris[0].split('.').pop()
|
|
|
+ const fullPath = this.context.cacheDir + '/' + photoName + photoType
|
|
|
+ const photo = fileIo.openSync(res.photoUris[0])
|
|
|
+ try {
|
|
|
+ fileIo.copyFile(photo.fd, fullPath)
|
|
|
+ .then(() => {
|
|
|
+ YTLog.info(fullPath)
|
|
|
+ success(fullPath)
|
|
|
+ })
|
|
|
+ } catch (err) {
|
|
|
+ YTLog.error(err)
|
|
|
+ }
|
|
|
+ })
|
|
|
+ }
|
|
|
+
|
|
|
+
|
|
|
+ //传入需要保存得cashPaths数组,并通过ShowAssetsCreationDialog保存文件
|
|
|
+ async saveByShowAssetsCreationDialog(cashPaths: string[], success?: () => void) {
|
|
|
+ const phAccessHelper = photoAccessHelper.getPhotoAccessHelper(this.context);
|
|
|
+ const uris = cashPaths.map(item => fileUri.getUriFromPath(item))
|
|
|
+ try {
|
|
|
+ // 指定待保存照片的创建选项,包括文件后缀和照片类型,标题和照片子类型可选。
|
|
|
+ const photoCreationConfigs = uris.map(() => {
|
|
|
+ const photoCreationConfig: photoAccessHelper.PhotoCreationConfig = {
|
|
|
+ fileNameExtension: 'jpg',
|
|
|
+ photoType: photoAccessHelper.PhotoType.IMAGE,
|
|
|
+ }
|
|
|
+ return photoCreationConfig
|
|
|
+ })
|
|
|
+ // 基于弹窗授权的方式获取媒体库的目标uri。
|
|
|
+ let desFileUris: Array<string> =
|
|
|
+ await phAccessHelper.showAssetsCreationDialog(uris, photoCreationConfigs);
|
|
|
+
|
|
|
+ let index = 0
|
|
|
+ while (index < uris.length) {
|
|
|
+ //通过该uri打开图片
|
|
|
+ let file = await fileIo.open(desFileUris[index], fileIo.OpenMode.READ_WRITE | fileIo.OpenMode.CREATE)
|
|
|
+ //获取流
|
|
|
+ const buffer = await this.getPhotoFileBuffer(cashPaths[index])
|
|
|
+ //通过流写入相册
|
|
|
+ await fileIo.write(file.fd, buffer)
|
|
|
+ //关流
|
|
|
+ await fileIo.close(file)
|
|
|
+ index++
|
|
|
+ }
|
|
|
+ success?.()
|
|
|
+ } catch (err) {
|
|
|
+ YTLog.error(err)
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ //传入图片地址,转化为流
|
|
|
+ async getPhotoFileBuffer(filePath: string): Promise<ArrayBuffer> {
|
|
|
+ try {
|
|
|
+ const imageSource = image.createImageSource(filePath)
|
|
|
+ let imagePackerApi = image.createImagePacker();
|
|
|
+ let buffer = await imagePackerApi.packing(imageSource, {
|
|
|
+ quality: 100,
|
|
|
+ format: 'image/jpeg'
|
|
|
+ })
|
|
|
+ return buffer
|
|
|
+ } catch (err) {
|
|
|
+ let error: BusinessError = err as BusinessError;
|
|
|
+ console.error(`read file failed, errCode:${error.code}, errMessage:${error.message}`);
|
|
|
+ return Promise.reject(err)
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+
|
|
|
+ //须先申请权限ohos.permission.WRITE_IMAGEVIDEO 保存图片至相册
|
|
|
+ async saveImgToAssets(cashPaths: string[]) {
|
|
|
+ try {
|
|
|
+ let index = 0;
|
|
|
+ while (index < cashPaths.length) {
|
|
|
+ //获取当前上下文
|
|
|
+ //通过accessHelper模块获取accessHelper对象
|
|
|
+ let accessHelper = photoAccessHelper.getPhotoAccessHelper(getContext())
|
|
|
+ //指定待创建的文件类型、后缀和创建选项,创建图片或视频资源 返回创建的图片和视频的uri
|
|
|
+ let uri = await accessHelper.createAsset(photoAccessHelper.PhotoType.IMAGE, 'jpg')
|
|
|
+ //通过该uri打开图片
|
|
|
+ let file = await fileIo.open(uri, fileIo.OpenMode.READ_WRITE | fileIo.OpenMode.CREATE)
|
|
|
+ //获取流
|
|
|
+ const buffer = await this.getPhotoFileBuffer(cashPaths[index])
|
|
|
+ //通过流写入相册
|
|
|
+ await fileIo.write(file.fd, buffer)
|
|
|
+ //关流
|
|
|
+ await fileIo.close(file)
|
|
|
+ index++
|
|
|
+ }
|
|
|
+
|
|
|
+ } catch (e) {
|
|
|
+ YTLog.error(e)
|
|
|
+ }
|
|
|
+ }
|
|
|
+}
|