HarmonyOS 鸿蒙Next 特殊字符名称的图片保存到相册失败

发布于 1周前 作者 yibo5220 来自 鸿蒙OS

HarmonyOS 鸿蒙Next 特殊字符名称的图片保存到相册失败

图片名称

【1415266】测试123qwe~!@#$%^&()+}{,.’][=-}{+)(^%$#@!``,.;’][=-.jpeg

相关代码

async saveImageToAlbum() {
    try {
      // 获取需要保存到媒体库的位于应用沙箱的图片/视频uri
      let phAccessHelper = photoAccessHelper.getPhotoAccessHelper(YContext.get());
      let imageUri = fileUri.getUriFromPath(this.imageUri);
      let srcFileUris: Array<string> = [
        imageUri
      ];
      let fileName = fs.openSync(imageUri).name
      let array = fileName.split('.')
      let photoCreationConfigs: Array<photoAccessHelper.PhotoCreationConfig> = [
        {
          title: `${array[0]}_${new Date().getTime()}`,
          fileNameExtension: array[array.length - 1],
          photoType: photoAccessHelper.PhotoType.IMAGE,
          subtype: photoAccessHelper.PhotoSubtype.DEFAULT,
        }
      ];
      let desFileUris: Array<string> = await phAccessHelper.showAssetsCreationDialog(srcFileUris, photoCreationConfigs);
      if (desFileUris.length === 0) {
        YToast.show($r('app.string.save_failed'));
        return;
      }
      let originFile = fs.openSync(imageUri, fs.OpenMode.READ_ONLY);
      let file = fs.openSync(desFileUris[0], fs.OpenMode.READ_WRITE);

      fs.copyFileSync(originFile.fd, file.fd);
      fs.closeSync(originFile);
      fs.closeSync(file);
      phAccessHelper.release();
      YToast.show($r('app.string.chat_save_image_success'));
    } catch (err) {
      YToast.show($r('app.string.save_failed'));
      YLog.e(TAG, `[error][saveImageToAlbum] + ${this.imageUri}`, err);
    }
}

原因

PhotoCreationConfig中title的array[0]包含特殊字符串,导致desFileUris得到的是错误路径,导致保存失败,看文档也没有说title有什么特殊的处理,就说是文件名字符串。

请问一下这种具有特殊字符的数据有什么提供的解决方案吗?替换还是什么


更多关于HarmonyOS 鸿蒙Next 特殊字符名称的图片保存到相册失败的实战系列教程也可以访问 https://www.itying.com/category-93-b0.html

4 回复

官方文档,对于包含特殊字符,title是不允许的, 参考:@ohos.file.photoAccessHelper (相册管理模块) https://developer.huawei.com/consumer/cn/doc/harmonyos-references-V13/js-apis-photoaccesshelper-V13#photocreationconfig12

title参数规格为: 不应包含扩展名。 文件名字符串长度为1~255。 不允许出现非法字符,包括: . \ / : * " ’ ` < > | { } [ ]

从获取到图片路径上进行修改图片的title或者对title进行设置,不带有特殊字符的,或者使用默认的随机名称

import { BusinessError, request } from '@kit.BasicServicesKit';
import { photoAccessHelper } from '@kit.MediaLibraryKit';
import { fileIo, fileUri, picker } from '@kit.CoreFileKit';
import promptAction from '[@ohos](/user/ohos).promptAction';
import { buffer } from '@kit.ArkTS';
import fs, { ReadOptions, WriteOptions } from '[@ohos](/user/ohos).file.fs';

let context = getContext(this);
let phAccessHelper = photoAccessHelper.getPhotoAccessHelper(context);

@Entry
@Component
struct PPage {
  @State src: string = 'https://syfrontweb.oss-cn-hangzhou.aliyuncs.com/wechat/small-mina/icon-account.png'
  @State base64: string = 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABcAAAAWCAYAAAArdgcFAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8YQUAAAAJcEhZcwAADsMAAA7DAcdvqGQAAALXSURBVEhLrZVLSJRRFMdvZgUFvR+StVCsqKhpofmYZpTUXPSgCCKfqaTRqoheuGlh5TJauLFFEKZFgSBiGUFF0AOSgkxHSAqSdoL4CIr03//Md25+fXOxRR344ZV7zu/eOd/5ZgxiMaCwEMjP/+8YNDQ4NxIoKgJaWoDWVqC83J0TwKB4DxDlP7NRUgIMDuJ3TE4C9SfcuT4MIlzMRjHF/QNq1RgaBnr7gapad41iEOYij8jfILsd4ie9wK1u4PFrYGAIqK336h0Y5ETxB9lKAdv1wSeemgIuXQP21QBdz4CPX4Bxtmd8AqjhAbbOh0FmBHGyFFlHihPFp64CqbnApjBwoBQY/gpMT3v78gyO8QDrUgx2cCGElBxORR/7aUPEJ68AS7OBtZRvpDy0CzhaCYyMaBJjggeU1QHbuacYbOXCkknx+4C47jKwIAtYRvk6n1w+emVV4gGH2bYt3N8scvmYghS9fKNZDBEfp3hOpieXm0tb/HKZiupqYHRUixijY9zbC2wIU57OZCHEyfDHjQ7AUByX7+TNczw5i7DNJ5cXprFRizSamoE0ka/PQ5w0Jk9+011G7DOwmhNjb27bInLpaTafj8gLCoCeHi3SqDjDi+RRnsICS+XZmQmQ6OMcp/AAkS/Rtli5jG2U4s5OTdZo7wLWMI8YrOTHtawg5ecSD0jlAdJzuXmGynN566C4jWJxLPcw8RsFKTuv2Rrv+M2ZzgNsW2RkOwLiVoqldvEMBou4CLKQVPDbUuInp2ZsHHj0guPKhy43v33f27PR/sCrCWDik+Bnvl2zz6UXKebrHftE+SvgehvQ/VSNGnf5MON1zA9gkMzFbOw/DTx/yzZQOsAJ8scdipMpnss8BwZJHDWLjJ2LIxfU5ov2h6yhxJWvGGQc9F6Wv3GIYyrfghLN91hMsSvPh0HTTeeGkyS2YB7HzLXnwOD7D75l/MlybP4Tq4rwC42denLaEHw7AAAAAElFTkSuQmCC'
  @State isDownload:boolean = false
  @State total:number = 0
  @State value:number = 0

  build() {
    Column() {
      Image(this.base64).height(100).width(100)

      Button('保存').onClick(() =>{
        this.saveImage(this.base64)
      })

      if (this.isDownload){
        Progress({ value: this.value, total: this.total, type: ProgressType.Linear }).margin({top:20})
      }
    }
    .align(Alignment.BottomEnd).width('100%').height('100%').backgroundColor(Color.White)
  }
  saveBase64Image(base64Str:string) {
    //文件保存路径
    let uri = '';
    try {
      let PhotoSaveOptions = new picker.PhotoSaveOptions();
      //保存图片默认名称
      PhotoSaveOptions.newFileNames = ['123qwe~!@#$%^&()+}{,.\'][=-}{+)(&^%$#@!``,.;\'][=-.png'];
      let photoPicker = new picker.PhotoViewPicker();
      //调起系统的图片保存功能
      photoPicker.save(PhotoSaveOptions).then((PhotoSaveResult) => {
        uri = PhotoSaveResult[0];
        //获取图片的base64字符串
        let imageStr = base64Str.split(',')[1];
        //打开文件
        let file = fs.openSync(uri, fs.OpenMode.READ_WRITE);
        //base64字符串转成buffer
        const decodeBuffer = buffer.from(imageStr, 'base64').buffer;
        //写入文件
        fs.writeSync(file.fd, decodeBuffer);
        //关闭文件
        fs.closeSync(file);
      }).catch((err: Error) => {
        console.error(err + '');
      }) } catch (e) {
      console.error(e);
    }
  }

  //保存图片
  async saveImage(imageURL: string) {
    try {
      let content = imageURL.split(',')[1]
      let dirPath: string = context.cacheDir;
      let fileName = 'test.jpg'
      fileIo.access(`${dirPath}/${fileName}`).then(async (result: boolean) => {
        if (result) {
          this.total = 0
          this.value = 0
          await fileIo.unlink(`${dirPath}/${fileName}`)
        }
      })
      this.writeBufferToFile(dirPath,fileName,buffer.from(content, 'base64').buffer)
      let uri = fileUri.getUriFromPath(`${dirPath}/${fileName}`);
      let srcFileUris: Array<string> = [
        uri// 实际场景请使用真实的uri
      ];
      let photoCreationConfigs: Array<photoAccessHelper.PhotoCreationConfig> = [
        {
          title: '=======``', // 可选 设置或者使用默认的随机名称
          fileNameExtension: 'png',
          photoType: photoAccessHelper.PhotoType.IMAGE,
          subtype: photoAccessHelper.PhotoSubtype.DEFAULT, // 可选
        }
      ];
      let desFileUris: Array<string> = await phAccessHelper.showAssetsCreationDialog(srcFileUris, photoCreationConfigs);
      if (desFileUris.length > 0) {
        for (let index = 0; index < desFileUris.length; index++) {
          this.copyFileContentTo(srcFileUris[0], desFileUris[index])
        }
      }

    } catch (err) {
      console.error('showAssetsCreationDialog failed, errCode is ' + err.code + ', errMsg is ' + err.message);
    }
  }
  writeBufferToFile(dirPath: string, fileName: string, buf: ArrayBuffer) {
    if (!fs.accessSync(dirPath)) {
      // 如果文件夹不存在,则先创建文件夹
      fs.mkdirSync(dirPath)
    }

    let file = fs.openSync(`${dirPath}/${fileName}`, fs.OpenMode.READ_WRITE | fs.OpenMode.CREATE)
    fs.writeSync(file.fd, buf)
    fs.closeSync(file)
  }
  copyFileContentTo(srcFilePath: string, destFilePath: string) {
    let srcFile = fs.openSync(srcFilePath, fs.OpenMode.READ_WRITE | fs.OpenMode.CREATE)
    let destFile = fs.openSync(destFilePath, fs.OpenMode.READ_WRITE | fs.OpenMode.CREATE)

    // 读取源文件内容并写入至目的文件
    let bufSize = 4096;
    let readSize = 0;
    let buf = new ArrayBuffer(bufSize);
    let readOptions: ReadOptions = {
      offset: readSize,
      length: bufSize
    };
    let readLen = fs.readSync(srcFile.fd, buf, readOptions);
    while (readLen > 0) {
      readSize += readLen;
      let writeOptions: WriteOptions = {
        length: readLen
      };
      fs.writeSync(destFile.fd, buf, writeOptions);
      readOptions.offset = readSize;
      readLen = fs.readSync(srcFile.fd, buf, readOptions);
    }
    // 关闭文件
    fs.closeSync(srcFile);
    fs.closeSync(destFile);
  }
}

更多关于HarmonyOS 鸿蒙Next 特殊字符名称的图片保存到相册失败的实战系列教程也可以访问 https://www.itying.com/category-93-b0.html


替换,我们也遇到了,直接正则干掉特殊字符了

fileName = fileName.replaceAll(/[:\|?*]/g, ‘_’);

针对“HarmonyOS 鸿蒙Next 特殊字符名称的图片保存到相册失败”的问题,可能的原因及解决方案如下:

原因一:文件名编码问题 鸿蒙系统在处理包含特殊字符的文件名时可能存在编码不兼容的情况,导致文件无法正确保存至相册。

解决方案: 尝试将图片文件名中的特殊字符替换为普通字符或数字,确保文件名不包含任何特殊或非标准字符,然后再次尝试保存。

原因二:系统权限限制 鸿蒙系统对应用访问相册的权限有严格限制,如果应用未获得相应权限,则无法将图片保存到相册。

解决方案: 请检查应用是否已获得“存储”或“相册”访问权限。在鸿蒙系统的设置中,找到应用管理,为该应用开启相应的权限。

原因三:系统Bug 鸿蒙系统本身可能存在Bug,导致在某些情况下无法保存图片至相册。

解决方案: 尝试更新鸿蒙系统至最新版本,看是否能解决问题。同时,也可以关注华为官方发布的更新日志和修复信息。

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

回到顶部