做普通网站公司,wordpress 维护代码,网站建设投诉去哪里投诉,网站放视频代码一、案例实现 
(一) 案例效果截图   (二) 案例运用到的知识点 
核心知识点 
文件管理能力 #xff1a;该模块为基础文件操作API#xff0c;提供基础文件操作能力#xff0c;包括文件基本管理、文件目录管理、文件信息统计、文件流式读写等常用功能。#xff08;ohos.file.f…一、案例实现 
(一) 案例效果截图   (二) 案例运用到的知识点 
核心知识点 
文件管理能力 该模块为基础文件操作API提供基础文件操作能力包括文件基本管理、文件目录管理、文件信息统计、文件流式读写等常用功能。ohos.file.fs选择器  选择器Picker模块封装了PhotoViewPicker、DocumentViewPicker、AudioViewPicker等API模块提供文件选择与保存能力。ohos.file.picker相册管理模块 该模块提供相册管理模块能力包括创建相册以及访问、修改相册中的媒体数据信息等。ohos.file.photoAccessHelperPhotoViewPicker 图库选择器对象用来支撑选择图片/视频和保存图片/视频等用户场景。DocumentViewPicker 文件选择器对象用来支撑选择和保存各种格式文档。 
其他知识点 
ArkTS 语言基础V2版状态管理ComponentV2/Local自定义组件自定义构建函数Builder内置组件SaveButton/Tabs/Scroll/Column/Text/TextArea/Button常量与资源分类的访问MVVM模式 
(三) 代码结构 
├──entry/src/main/ets                      // 代码区
│  ├──common
│  │  └──utils
│  │     ├──Logger.ets                     // 日志打印类
│  │     ├──PictureSaving.ets              // 图片保存方法
│  │     ├──ReadFile.ets                   // 文件读取方法
│  │     ├──SavingAndSelectUserFile.ets    // 用户文件保存与选择方法
│  │     └──WriteFile.ets                  // 文件写入方法
│  ├──entryability
│  │  └──EntryAbility.ets                  // 程序入口类
│  ├──pages
│  │  └──HomePage.ets                      // 主界面  
│  └──view
│     ├──ApplicationFileTab.ets            // 应用文件功能展示
│     └──PublicFilesTab.ets                // 公共文件功能展示
└──entry/src/main/resources                // 资源文件目录 
(四) 公共文件与资源 
本案例涉及到的常量类和工具类代码如下 
通用日志类 
// entry/src/main/ets/common/utils/Logger.ets
import { hilog } from kit.PerformanceAnalysisKitconst LOGGER_PREFIX: string  File_Management
class Logger {private domain: numberprivate prefix: stringprivate format: string  %{public}s, %{public}sconstructor(prefix: string  , domain: number  0xFF00) {this.prefix  prefixthis.domain  domain}debug(...args: string[]): void {hilog.debug(this.domain, this.prefix, this.format, args)}info(...args: string[]): void {hilog.info(this.domain, this.prefix, this.format, args)}warn(...args: string[]): void {hilog.warn(this.domain, this.prefix, this.format, args)}error(...args: string[]): void {hilog.error(this.domain, this.prefix, this.format, args)}
}export default new Logger(LOGGER_PREFIX, 0xFF02) 
本案例涉及到的资源文件如下 
string.json 
// entry/src/main/resources/base/element/string.json
{string: [{name: module_desc,value: 模块描述},{name: EntryAbility_desc,value: description},{name: EntryAbility_label,value: 文件管理},{name: textarea_default,value: 请输入保存至文件的内容},{name: file_content,value: 文件内容},{name: button1,value: 保存至应用沙箱目录},{name: button2,value: 读取保存的文件内容},{name: title,value: 文件管理},{name: bar1,value: 应用文件},{name: bar2,value: 公共文件},{name: select_photo,value: 从图库中选择一张图片展示},{name: textarea_default2,value: 文件内容...},{name: button3,value: 保存test.txt至用户目录},{name: button4,value: 读取test.txt文件内容}]
} 
color.json 
// entry/src/main/resources/base/element/color.json
{color: [{name: start_window_background,value: #FFFFFF},{name: text_color,value: #182431},{name: picture_background,value: #0D182431}]
} 
float.json 
// entry/src/main/resources/base/element/float.json
{float: [{name: default_22,value: 22vp},{name: default_24,value: 24vp},{name: default_294,value: 294vp},{name: default_312,value: 312vp},{name: default_40,value: 40vp},{name: default_16,value: 16vp},{name: default_13,value: 13vp},{name: default_336,value: 336vp},{name: default_8,value: 8vp},{name: default_139,value: 139vp},{name: default_20,value: 20vp},{name: default_100,value: 100vp},{name: default_48,value: 48vp},{name: default_147,value: 147vp},{name: default_10,value: 10vp},{name: default_223,value: 223vp},{name: default_302,value: 302vp},{name: default_213,value: 213vp},{name: default_120,value: 120vp},{name: default_251,value: 251vp},{name: default_41,value: 41vp},{name: default_30,value: 30vp},{name: default_7,value: 7vp},{name: default_360,value: 360vp},{name: default_56,value: 56vp},{name: default_680,value: 680vp},{name: default_200,value: 200vp},{name: default_12,value: 12vp}]
} 
其他资源请到源码中获取。 
(五) 沙箱路径下的文件读写 
构建主界面 
// entry/src/main/ets/pages/HomePage.ets
import { ApplicationFileTab } from ../views/ApplicationFileTabEntry
ComponentV2
struct HomePage {build() {Column() {Column() {Text($r(app.string.title)).width($r(app.float.default_312)).height($r(app.float.default_41)).textAlign(TextAlign.Start).fontSize($r(app.float.default_30)).fontFamily(HarmonyHeiTi-Bold).fontColor($r(app.color.text_color)).lineHeight($r(app.float.default_41)).fontWeight(700).margin({top: $r(app.float.default_7),bottom: $r(app.float.default_8),left: $r(app.float.default_24),right: $r(app.float.default_24)})}.width($r(app.float.default_360)).height($r(app.float.default_56))Tabs() {TabContent() {ApplicationFileTab()}.tabBar(new SubTabBarStyle($r(app.string.bar1)).indicator({ marginTop: $r(app.float.default_8) }).labelStyle({ font: { size: $r(app.float.default_16) } }))TabContent() {Scroll() {Text(PublicFilesTab)}.height($r(app.float.default_680))}.height(100%).tabBar(new SubTabBarStyle($r(app.string.bar2)).indicator({marginTop : $r(app.float.default_8)}).labelStyle({font : {size : $r(app.float.default_16)}}))}.barWidth($r(app.float.default_200)).barHeight($r(app.float.default_56)).width(100%)}.backgroundColor($r(app.color.picture_background)).justifyContent(FlexAlign.Center).width(100%)}
} 
应用文件组件 
// entry/src/main/ets/views/ApplicationFileTab.ets
import { readFile } from ../common/utils/ReadFile
import { writeFile } from ../common/utils/WriteFileComponentV2
export struct ApplicationFileTab {// 用于记录读取的内容。Local message: string  // 用于记录文本框中的内容。Local content: string  build() {Column() {Text($r(app.string.textarea_default)).width($r(app.float.default_294)).height($r(app.float.default_22)).fontColor($r(app.color.text_color)).fontWeight(500).fontSize($r(app.float.default_16)).fontFamily(HarmonyHeiTi-Medium).lineHeight($r(app.float.default_22)).textAlign(TextAlign.Start).margin({top: $r(app.float.default_13),bottom: $r(app.float.default_13),right: $r(app.float.default_8)})TextArea({ text: this.content }).width($r(app.float.default_336)).height($r(app.float.default_139)).borderRadius($r(app.float.default_24)).backgroundColor($r(app.color.start_window_background)).enableKeyboardOnFocus(false).onChange((value: string)  {this.content  value})Text($r(app.string.file_content)).width($r(app.float.default_294)).height($r(app.float.default_22)).fontSize($r(app.float.default_16)).lineHeight($r(app.float.default_22)).fontWeight(500).margin({top: $r(app.float.default_13),bottom: $r(app.float.default_13),right: $r(app.float.default_8)})TextArea({ text: this.message }).enableKeyboardOnFocus(false).width($r(app.float.default_336)).height($r(app.float.default_139)).backgroundColor($r(app.color.start_window_background)).borderRadius($r(app.float.default_24))Column() {Button($r(app.string.button1)).width($r(app.float.default_312)).height($r(app.float.default_40))// 写入信息并清空输入内容点击“保存”后清空文本框。.onClick(()  {writeFile(this.content)this.content  })Button($r(app.string.button2)).width($r(app.float.default_312)).height($r(app.float.default_40)).margin({top: $r(app.float.default_12),bottom: $r(app.float.default_100)}).onClick(()  {this.message  readFile()})}.width(100%).margin({ top: $r(app.float.default_100) })}.width(100%).height(100%)}
} 
实现沙箱路径下文件的写入操作 
// entry/src/main/ets/common/utils/WriteFile.ets
import { fileIo } from kit.CoreFileKit
import { common } from kit.AbilityKitlet context  getContext(this) as common.UIAbilityContext
let filesDir  context.filesDir/*** writeFile.* 将内容写入文件* param content 要写入文件的内容*/
export function writeFile(content: string): void {let filePath  filesDir  /test.txt// 基于文件路径打开文件流let fileStream  fileIo.createStreamSync(filePath, w)fileStream.writeSync(content)fileStream.close()
} 
关键代码说明 
首先需要结合context得到想要操作的文件路径。然后对该文件进行写入操作这里使用的是createStreamSync创建文件流的形式。通过文件流的方式可以控制文件的读写方式覆盖写的方式可以使得每次写操作互不影响。 
实现沙箱路径下文件的读取操作 
// entry/src/main/ets/common/utils/ReadFile.ets
import { fileIo } from kit.CoreFileKit
import { common } from kit.AbilityKit
import { buffer } from kit.ArkTS// 获取应用文件路径
let context  getContext(this) as common.UIAbilityContext
let filesDir  context.filesDir
let res: string  /*** readFile.* 读取文件内容并返回字符串。* return 字符串。*/
export function readFile(): string {let filePath  filesDir  /test.txtlet stat  fileIo.statSync(filePath)let size  stat.sizelet buf  new ArrayBuffer(size)// 基于文件路径打开文件流let fileStream  fileIo.createStreamSync(filePath, r)// 读取文件流信息fileStream.readSync(buf)// 将读取的信息转换为字符串类型并返回let con  buffer.from(buf, 0)res  con.toString()fileStream.close()return res
} 
关键代码说明 
与写入类似也通过文件路径去创建文件流进行读取操作。通过statSync获取文件的详细信息进而得到文件内容的大小然后利用文件流将文件内容读取到ArrayBuffer中再将ArrayBuffer转化为string返回即可完成文件的读取操作。 
(六) 图库的读取与写入 
在主界面引入公共文件组件 
// entry/src/main/ets/pages/HomePage.ets
// ...
import { publicFilesTab } from ../views/PublicFilesTabEntry
ComponentV2
struct HomePage {build() {Column() {// ...Tabs() {// ...TabContent() {Scroll() {publicFilesTab()}// ...}// ...}// ...}// ...}
} 
构建公共文件组件实现保存图片到图库 
// entry/src/main/ets/views/PublicFilesTab.ets
import { photoAccessHelper } from kit.MediaLibraryKit
import { fileIo } from kit.CoreFileKit
import Logger from ../common/utils/Logger
import { photoPickerGetUri } from ../common/utils/PictureSavingComponentV2
export struct publicFilesTab {Local picture: string  Local flag: Boolean  falseLocal message: string  Local content: string  Local isInput: Boolean  false// 设置安全控件的按钮属性Local saveButtonOptions: SaveButtonOptions  {icon: SaveIconStyle.FULL_FILLED,text: SaveDescription.SAVE_IMAGE,buttonType: ButtonType.Capsule}build() {Column() {Column() {Image($r(app.media.img)).borderRadius($r(app.float.default_24)).width($r(app.float.default_312)).height($r(app.float.default_147))// 创建安全控件按钮SaveButton(this.saveButtonOptions).onClick(async (event, result: SaveButtonOnClickResult)  {if (result  SaveButtonOnClickResult.SUCCESS) {try {Logger.info(createAsset 成功, event:   event)let context  getContext()let phAccessHelper  photoAccessHelper.getPhotoAccessHelper(context)// 创建媒体文件let uri  await phAccessHelper.createAsset(photoAccessHelper.PhotoType.IMAGE, jpg)Logger.info(createAsset 成功, uri:   uri)// 打开创建的媒体文件读取本地文件并转换为 ArrayBuffer便于写入let file  await fileIo.open(uri, fileIo.OpenMode.READ_WRITE)let buffer  getContext(this).resourceManager.getMediaContentSync($r(app.media.img).id)// 将读取的 ArrayBuffer 写入新的媒体文件let writeLen  await fileIo.write(file.fd, buffer.buffer)Logger.info(写入成功, 长度  writeLen)await fileIo.close(file)} catch (err) {Logger.error(createAsset 失败, message  , err)}} else {Logger.error(SaveButtonOnClickResult createAsset 失败)}})}.margin({ bottom: $r(app.float.default_10) }).width($r(app.float.default_336)).height($r(app.float.default_223)).borderRadius($r(app.float.default_24)).justifyContent(FlexAlign.SpaceAround).backgroundColor($r(app.color.start_window_background))Column() {Text($r(app.string.select_photo)).width($r(app.float.default_302)).height($r(app.float.default_48)).lineHeight($r(app.float.default_22)).fontFamily(HarmonyHeiTi-Medium).fontSize($r(app.float.default_16)).fontWeight(500).textAlign(TextAlign.Start).fontColor($r(app.color.text_color))Column() {if (!this.flag) {Image($r(app.media.ic_folder_add2)).width($r(app.float.default_24)).height($r(app.float.default_24)).objectFit(ImageFit.Contain)} else {Image(this.picture).width(100%).height(100%).borderRadius($r(app.float.default_24))}}.width($r(app.float.default_312)).height($r(app.float.default_147)).borderRadius($r(app.float.default_16)).backgroundColor($r(app.color.picture_background)).onClick(async ()  {await photoPickerGetUri().then(value  {this.flag  truethis.picture  value})}).justifyContent(FlexAlign.Center).alignItems(HorizontalAlign.Center)}.margin({ bottom: $r(app.float.default_10) }).backgroundColor($r(app.color.start_window_background)).width($r(app.float.default_336)).height($r(app.float.default_213)).borderRadius($r(app.float.default_24))}.width(100%)}
} 
关键代码说明 
首先需要在图库中创建媒体资源随后将图片读取转化为ArrayBuffer最后再将该内容写入在图库中创建的媒体资源中。createAsset方法会返回在图库中新建的媒体资源的uri只不过此时还是没有内容的空文件然后需要将本地图片文件的内容读取出来并写入该空文件即可完成图片保存到图库的操作。 
从图库中选择图片进行展示 
// entry/src/main/ets/common/utils/PictureSaving.ets
import { photoAccessHelper } from kit.MediaLibraryKit
import { BusinessError } from kit.BasicServicesKit
import Logger from ./Logger// 定义 URI 数组用于接收 PhotoViewPicker 选择图片后返回的 URI。
let uris: Arraystring  []/*** photoPickerGetUri.* 根据 PhotoViewPicker 的 select 方法返回所选文件的 URI。* return Promisestring.*/
export async function photoPickerGetUri(): Promisestring {try {let PhotoSelectOptions  new photoAccessHelper.PhotoSelectOptions()PhotoSelectOptions.MIMEType  photoAccessHelper.PhotoViewMIMETypes.IMAGE_TYPEPhotoSelectOptions.maxSelectNumber  1let photoPicker  new photoAccessHelper.PhotoViewPicker()await photoPicker.select(PhotoSelectOptions).then((PhotoSelectResult: photoAccessHelper.PhotoSelectResult)  {Logger.info(PhotoViewPicker.select 成功, 返回的 PhotoSelectResult uri:   JSON.stringify(PhotoSelectResult))uris  PhotoSelectResult.photoUris}).catch((err: BusinessError)  {Logger.error(PhotoViewPicker.select 失败, 错误信息:   JSON.stringify(err))})} catch (error) {let err  error as BusinessErrorLogger.error(PhotoViewPicker 失败, 错误信息:   err.message)}return uris[0].toString()
} 
关键代码说明 
调用PhotoViewPicker的select方法来得到被选择图片的uri即可完成读取图库中图片的信息。 
(七) 用户目录的文件读写 
// entry/src/main/ets/common/utils/SavingAndSelectUserFile.ets
import { BusinessError } from kit.BasicServicesKit
import { picker, fileIo } from kit.CoreFileKit
import { buffer } from kit.ArkTS
import Logger from ./Loggerlet uri: string  
// 获取应用文件路径let message: string  /*** saveToUser.* 将内容保存到用户目录文件中* param content 要保存到用户目录文件中的内容*/
export async function saveToUser(content: string) {try {let DocumentSaveOptions  new picker.DocumentSaveOptions()DocumentSaveOptions.newFileNames  [test.txt]let documentPicker  new picker.DocumentViewPicker()documentPicker.save(DocumentSaveOptions).then((DocumentSaveResult: Arraystring)  {Logger.info(DocumentViewPicker.save 成功返回的 uri:   JSON.stringify(DocumentSaveResult))uri  DocumentSaveResult[0]let file  fileIo.openSync(uri, fileIo.OpenMode.READ_WRITE)// 根据文件路径打开文件流。fileIo.writeSync(file.fd, content)}).catch((err: BusinessError)  {Logger.error(DocumentViewPicker.save 失败错误信息:   JSON.stringify(err))})} catch (error) {let err: BusinessError  error as BusinessErrorLogger.error(DocumentViewPicker 失败错误信息:   err.message)}
}/*** readUserFile.* 读取用户目录文件中的内容。* return Promisestring.*/
export async function readUserFile(): Promisestring {try {let DocumentSelectOptions  new picker.DocumentSelectOptions()let documentPicker  new picker.DocumentViewPicker()await documentPicker.select(DocumentSelectOptions).then((DocumentSelectResult: Arraystring)  {Logger.info(DocumentViewPicker.select 成功返回的 uri:   JSON.stringify(DocumentSelectResult))uri  DocumentSelectResult[0]let file  fileIo.openSync(uri, fileIo.OpenMode.READ_WRITE)let stat  fileIo.statSync(file.fd)let size  stat.sizelet buf  new ArrayBuffer(size)fileIo.readSync(file.fd, buf)let con  buffer.from(buf, 0)message  con.toString()Logger.info(DocumentViewPicker.select 成功读取的内容:   message)return message}).catch((err: BusinessError)  {Logger.error(DocumentViewPicker.select 失败错误信息:   JSON.stringify(err))})} catch (error) {let err  error as BusinessErrorLogger.error(DocumentViewPicker.select 失败错误信息:   err.message)}return message
} 
关键代码说明 
在DocumentViewPicker提供的save方法的帮助下可以向用户目录下创建一个文件并返回它的uri。DocumentViewPicker提供的select方法可以选择想要访问的文件并返回其uri。获取到uri后即可完成对文件的读取并将信息返回的操作。 
二、文件管理知识点 
Core File Kit文件基础服务为开发者提供统一的文件访问和管理能力涵盖应用文件和用户文件帮助用户高效地查找、管理、备份各类文件满足多样化的文件操作需求。 
在文件分类上Core File Kit将文件划分为三类应用文件如安装包、资源、缓存等由应用拥有和管理用户文件如图片、视频、文档等由登录用户所有系统文件包括系统资源、设备文件等由系统统一管理开发者无需操作。按文件存储位置分为本地文件系统本地设备或外置设备和分布式文件系统支持跨设备访问。 
Core File Kit支持对应用文件进行查看、创建、读写、删除、复制、移动、获取属性等操作支持将应用文件上传至服务器或从服务器下载资源支持查询应用及文件系统的空间使用情况支持通过URI或文件描述符方式实现跨应用文件分享支持配置应用数据的备份与恢复同时提供统一的用户文件访问接口便于用户文件的选择与保存还支持在多设备间进行文件访问和传输。 
亮点方面Core File Kit采用沙箱隔离机制为每个应用提供专属的文件目录空间确保文件的隔离性与安全性。通过分享机制开发者可安全、高效地实现应用间文件共享确保数据一致性与传输安全是构建HarmonyOS文件能力的基础组件之一。 
(一) 应用文件 
应用文件的所有者为应用包括应用安装文件、应用资源文件、应用缓存文件等。 
1. 应用沙箱目录 
应用沙箱是一种以安全防护为目的的隔离机制避免数据受到恶意路径穿越访问。在这种沙箱的保护机制下应用可见的目录范围即为“应用沙箱目录”。 
对于每个应用系统会在内部存储空间映射出一个专属的“应用沙箱目录”它是“应用文件目录”与一部分系统文件应用运行必需的少量系统文件所在的目录组成的集合。应用沙箱限制了应用可见的数据范围。在“应用沙箱目录”中应用仅能看到自己的应用文件以及少量的系统文件应用运行必需的少量系统文件。因此本应用的文件也不为其他应用可见从而保护了应用文件的安全。应用可以在“应用文件目录”下保存和处理自己的应用文件系统文件及其目录对于应用是只读的而应用若需访问用户文件则需要通过特定API同时经过用户的相应授权才能进行。 
下图展示了应用沙箱下应用可访问的文件范围和方式。 2. 应用文件访问 
应用需要对应用文件目录下的应用文件进行查看、创建、读写、删除、移动、复制、获取属性等访问操作下面介绍具体方法。 
接口说明 
开发者通过基础文件操作接口ohos.file.fs实现应用文件访问能力主要功能如下表所示。 接口名  功能  接口类型  支持同步  支持异步  access  检查文件是否存在  方法  √  √  close  关闭文件  方法  √  √  copyFile  复制文件  方法  √  √  createStream  基于文件路径打开文件流  方法  √  √  listFile  列出文件夹下所有文件名  方法  √  √  mkdir  创建目录  方法  √  √  moveFile  移动文件  方法  √  √  open  打开文件  方法  √  √  read  从文件读取数据  方法  √  √  rename  重命名文件或文件夹  方法  √  √  rmdir  删除整个目录  方法  √  √  stat  获取文件详细属性信息  方法  √  √  unlink  删除单个文件  方法  √  √  write  将数据写入文件  方法  √  √  Stream.close  关闭文件流  方法  √  √  Stream.flush  刷新文件流  方法  √  √  Stream.write  将数据写入流文件  方法  √  √  Stream.read  从流文件读取数据  方法  √  √  File.fd  获取文件描述符  属性  -  -  OpenMode  设置文件打开标签  属性  -  -  Filter  设置文件过滤配置项  类型  -  -  
注意使用基础文件操作接口时耗时较长的操作例如read、write等建议使用异步接口避免应用崩溃。 
开发示例 
在对应用文件开始访问前开发者需要获取应用文件路径。 
新建并读写一个文件 
以下示例代码演示了如何新建一个文件并对其读写。 
import { fileIo as fs, ReadOptions } from kit.CoreFileKit
import { common } from kit.AbilityKit
import { buffer } from kit.ArkTS// 获取应用文件路径
let context  getContext(this) as common.UIAbilityContext
let filesDir  context.filesDirfunction createFile(): void {// 文件不存在时创建并打开文件文件存在时打开文件let file  fs.openSync(filesDir  /test.txt, fs.OpenMode.READ_WRITE | fs.OpenMode.CREATE)// 写入一段内容至文件let writeLen  fs.writeSync(file.fd, Try to write str.)console.info(The length of str is:   writeLen)// 创建一个大小为1024字节的ArrayBuffer对象用于存储从文件中读取的数据let arrayBuffer  new ArrayBuffer(1024)// 设置读取的偏移量和长度let readOptions: ReadOptions  {offset: 0,length: arrayBuffer.byteLength}// 读取文件内容到ArrayBuffer对象中并返回实际读取的字节数let readLen  fs.readSync(file.fd, arrayBuffer, readOptions)// 将ArrayBuffer对象转换为Buffer对象并转换为字符串输出let buf  buffer.from(arrayBuffer, 0, readLen)console.info(the content of file:   buf.toString())// 关闭文件fs.closeSync(file)
} 
读取文件内容并写入到另一个文件 
以下示例代码演示了如何从一个文件读写内容到另一个文件。 
import { fileIo as fs, ReadOptions, WriteOptions } from kit.CoreFileKit
import { common } from kit.AbilityKit// 获取应用文件路径
let context  getContext(this) as common.UIAbilityContext
let filesDir  context.filesDirfunction readWriteFile(): void {// 打开文件let srcFile  fs.openSync(filesDir  /test.txt, fs.OpenMode.READ_WRITE | fs.OpenMode.CREATE)let destFile  fs.openSync(filesDir  /destFile.txt, fs.OpenMode.READ_WRITE | fs.OpenMode.CREATE)// 读取源文件内容并写入至目的文件let bufSize  4096let readSize  0let buf  new ArrayBuffer(bufSize)let readOptions: ReadOptions  {offset: readSize,length: bufSize}let readLen  fs.readSync(srcFile.fd, buf, readOptions)while (readLen  0) {readSize  readLenlet writeOptions: WriteOptions  {length: readLen}fs.writeSync(destFile.fd, buf, writeOptions)readOptions.offset  readSizereadLen  fs.readSync(srcFile.fd, buf, readOptions)}// 关闭文件fs.closeSync(srcFile)fs.closeSync(destFile)
} 
使用读写接口时需注意可选项参数offset的设置。对于已存在且读写过的文件文件偏移指针默认在上次读写操作的终止位置。 
以流的形式读写文件 
以下示例代码演示了如何使用流接口读取test.txt的文件内容并写入到destFile.txt文件中。 
import { fileIo as fs, ReadOptions } from kit.CoreFileKit
import { common } from kit.AbilityKit// 获取应用文件路径
let context  getContext(this) as common.UIAbilityContext
let filesDir  context.filesDirasync function readWriteFileWithStream(): Promisevoid {// 创建并打开输入文件流let inputStream  fs.createStreamSync(filesDir  /test.txt, r)// 创建并打开输出文件流let outputStream  fs.createStreamSync(filesDir  /destFile.txt, w)let bufSize  4096let readSize  0let buf  new ArrayBuffer(bufSize)let readOptions: ReadOptions  {offset: readSize,length: bufSize}// 以流的形式读取源文件内容并写入到目标文件let readLen  await inputStream.read(buf, readOptions)readSize  readLenwhile (readLen  0) {const writeBuf  readLen  bufSize ? buf.slice(0, readLen) : bufawait outputStream.write(writeBuf)readOptions.offset  readSizereadLen  await inputStream.read(buf, readOptions)readSize  readLen}// 关闭文件流inputStream.closeSync()outputStream.closeSync()
} 
使用流接口时需注意流的及时关闭。同时流的异步接口应严格遵循异步接口使用规范避免同步、异步接口混用。流接口不支持并发读写。 
查看文件列表 
以下示例代码演示了如何查看文件列表。 
import { fileIo as fs, Filter, ListFileOptions } from kit.CoreFileKit
import { common } from kit.AbilityKit// 获取应用文件路径
let context  getContext(this) as common.UIAbilityContext
let filesDir  context.filesDir// 查看文件列表
function getListFile(): void {let listFileOption: ListFileOptions  {recursion: false,listNum: 0,filter: {suffix: [.png, .jpg, .txt],displayName: [test*],fileSizeOver: 0,lastModifiedAfter: new Date(0).getTime()}}let files  fs.listFileSync(filesDir, listFileOption)for (let i  0; i  files.length; i) {console.info(The name of file: ${files[i]})}
} 
使用文件流 
以下示例代码演示了如何使用文件可读流文件可写流。 
import { fileIo as fs } from kit.CoreFileKit
import { common } from kit.AbilityKitlet context  getContext(this) as common.UIAbilityContext
let filesDir  context.filesDirfunction copyFileWithReadable(): void {// 创建文件可读流const rs  fs.createReadStream(${filesDir}/read.txt)// 创建文件可写流const ws  fs.createWriteStream(${filesDir}/write.txt)// 暂停模式拷贝文件。在拷贝数据时将原始数据暂停然后将数据复制到另一个位置// 适用于对数据完整性和一致性要求较高的场景rs.on(readable, ()  {const data  rs.read()if (!data) {return}ws.write(data)})
}function copyFileWithData(): void {// 创建文件可读流const rs  fs.createReadStream(${filesDir}/read.txt)// 创建文件可写流const ws  fs.createWriteStream(${filesDir}/write.txt)// 流动模式拷贝文件。数据的读取和写入是同时进行的不需要暂停原始数据的访问// 适用于对数据实时性要求较高的场景rs.on(data, (emitData)  {const data  emitData?.dataif (!data) {return}ws.write(data as Uint8Array)})
} 
使用文件哈希流 
哈希流是一种数据传输和存储技术可以将任意长度的数据转换为固定长度的哈希值来验证数据的完整性和一致性。以下代码演示了如何使用文件哈希处理接口ohos.file.hash来处理文件哈希流。 
import { fileIo as fs } from kit.CoreFileKit
import { hash } from kit.CoreFileKit
import { common } from kit.AbilityKit// 获取应用文件路径
let context  getContext(this) as common.UIAbilityContext
let filesDir  context.filesDirfunction hashFileWithStream() {const filePath  ${filesDir}/test.txt// 创建文件可读流const rs  fs.createReadStream(filePath)// 创建哈希流const hs  hash.createHash(sha256)rs.on(data, (emitData)  {const data  emitData?.datahs.update(new Uint8Array(data?.split().map((x: string)  x.charCodeAt(0))).buffer)})rs.on(close, async ()  {const hashResult  hs.digest()const fileHash  await hash.hash(filePath, sha256)console.info(hashResult: ${hashResult}, fileHash: ${fileHash})})
} 
(二) 用户文件 
用户文件是指登录到该终端设备的用户所拥有的文件包括用户私有的图片、视频、音频、文档等 
1. 用户文件uri 
用户文件uri是文件的唯一标识在对用户文件进行访问与修改等操作时往往都会使用到uri不建议开发者解析uri中的片段用于业务代码开发。 
uri类型可以归纳为文档类uri和媒体文件uri两类 
文档类uri由picker拉起文件管理器选择或保存返回以及通过fileAccess模块获取。媒体文件uri由picker通过拉起图库选择图片或者视频返回通过photoAccessHelper模块获取图片或者视频文件的uri以及通过userFileManager模块获取图片、视频或者音频文件的uri。 2. 选择用户文件 
用户需要分享文件、保存图片、视频等用户文件时开发者可以通过系统预置的文件选择器FilePicker实现该能力。通过Picker访问相关文件将拉起对应的应用引导用户完成界面操作接口本身无需申请权限。picker获取的uri只具有临时权限获取持久化权限需要通过FilePicker设置永久授权方式获取。 
根据用户文件的常见类型选择器FilePicker分别提供以下选项 
PhotoViewPicker适用于图片或视频类型文件的选择与保存。DocumentViewPicker适用于文件类型文件的选择与保存。DocumentViewPicker对接的选择资源来自于FilePicker, 负责文件类型的资源管理文件类型不区分后缀比如浏览器下载的图片、文档等都属于文件类型。AudioViewPicker适用于音频类型文件的选择与保存。AudioViewPicker目前对接的选择资源来自于FilePicker。 
选择图片或视频类文件 
图库选择器对象用来支撑选择图片/视频等用户场景。在使用前需要先创建PhotoViewPicker实例。 
let photoPicker  new photoAccessHelper.PhotoViewPicker() 
用法一 
select(option?: PhotoSelectOptions) : PromisePhotoSelectResult 
通过选择模式拉起photoPicker界面用户可以选择一个或多个图片/视频。接口采用promise异步返回形式传入可选参数PhotoSelectOptions对象返回PhotoSelectResult对象。示例如下 
import { BusinessError } from kit.BasicServicesKit
async function example01() {try {let PhotoSelectOptions  new photoAccessHelper.PhotoSelectOptions()PhotoSelectOptions.MIMEType  photoAccessHelper.PhotoViewMIMETypes.IMAGE_TYPE;PhotoSelectOptions.maxSelectNumber  5let photoPicker  new photoAccessHelper.PhotoViewPicker()photoPicker.select(PhotoSelectOptions).then((PhotoSelectResult: photoAccessHelper.PhotoSelectResult)  {console.info(PhotoViewPicker.select successfully, PhotoSelectResult uri:   JSON.stringify(PhotoSelectResult))}).catch((err: BusinessError)  {console.error(PhotoViewPicker.select failed with  err: ${err.code}, ${err.message})})} catch (error) {let err: BusinessError  error as BusinessError;console.error(PhotoViewPicker failed with  err: ${err.code}, ${err.message})}
} 
用法二 
select(option: PhotoSelectOptions, callback: AsyncCallbackPhotoSelectResult
): void 
通过选择模式拉起photoPicker界面用户可以选择一个或多个图片/视频。接口采用callback异步返回形式传入参数PhotoSelectOptions对象返回PhotoSelectResult对象。示例如下 
import { BusinessError } from kit.BasicServicesKit
async function example02() {try {let PhotoSelectOptions  new photoAccessHelper.PhotoSelectOptions()PhotoSelectOptions.MIMEType  photoAccessHelper.PhotoViewMIMETypes.IMAGE_TYPEPhotoSelectOptions.maxSelectNumber  5let photoPicker  new photoAccessHelper.PhotoViewPicker();photoPicker.select(PhotoSelectOptions, (err: BusinessError, PhotoSelectResult: photoAccessHelper.PhotoSelectResult)  {if (err) {console.error(PhotoViewPicker.select failed with  err: ${err.code}, ${err.message})return}console.info(PhotoViewPicker.select successfully,PhotoSelectResult uri:  JSON.stringify(PhotoSelectResult));})} catch (error) {let err: BusinessError  error as BusinessError;console.error(PhotoViewPicker failed with  err: ${err.code}, ${err.message});}
} 
用法三 
select(callback: AsyncCallbackPhotoSelectResult) : void 
通过选择模式拉起photoPicker界面用户可以选择一个或多个图片/视频。接口采用callback异步返回形式返回PhotoSelectResult对象。示例如下 
import { BusinessError } from kit.BasicServicesKit
async function example03() {try {let photoPicker  new photoAccessHelper.PhotoViewPicker()photoPicker.select((err: BusinessError, PhotoSelectResult: photoAccessHelper.PhotoSelectResult)  {if (err) {console.error(PhotoViewPicker.select failed with  err: ${err.code}, ${err.message})return}console.info(PhotoViewPicker.select successfully,PhotoSelectResult uri:  JSON.stringify(PhotoSelectResult))})} catch (error) {let err: BusinessError  error as BusinessErrorconsole.error(PhotoViewPicker failed with err: ${err.code}, ${err.message})}
} 
选择文档类文件 
导入选择器模块和基础文件API模块。 
import  { picker } from kit.CoreFileKit
import { fileIo as fs } from kit.CoreFileKit
import { common } from kit.AbilityKit
import { BusinessError } from kit.BasicServicesKit 
创建文件类型、文件选择选项实例。 
const documentSelectOptions  new picker.DocumentSelectOptions()
// 选择文档的最大数目可选。
documentSelectOptions.maxSelectNumber  5
// 指定选择的文件或者目录路径可选。
documentSelectOptions.defaultFilePathUri  file://docs/storage/Users/currentUser/test
// 选择文件的后缀类型[后缀类型描述|后缀类型]可选 若选择项存在多个后缀名
// 则每一个后缀名之间用英文逗号进行分隔可选后缀类型名不能超过100,
// 选择所有文件所有文件(*.*)|.*。
documentSelectOptions.fileSuffixFilters  [图片(.png, .jpg)|.png,.jpg, 文档|.txt, 视频|.mp4, .pdf]
// 选择是否对指定文件或目录授权true为授权当为true时defaultFilePathUri为必选参数
// 拉起文管授权界面false为非授权默认为false拉起常规文管界面可选仅支持2in1设备。
documentSelectOptions.authMode  false 
创建文件选择器DocumentViewPicker实例。调用select()接口拉起FilePicker应用界面进行文件选择。 
let uris: Arraystring  []
// 请确保 getContext(this) 返回结果为 UIAbilityContext
let context  getContext(this) as common.Context 
// 创建文件选择器实例
const documentViewPicker  new picker.DocumentViewPicker(context);
documentViewPicker.select(documentSelectOptions).then((documentSelectResult: Arraystring)  {//文件选择成功后返回被选中文档的uri结果集。uris  documentSelectResultconsole.info(documentViewPicker.select to file succeed and uris are:  uris)}).catch((err: BusinessError)  {console.error(Invoke documentViewPicker.select failed,  code is ${err.code}, message is ${err.message})}) 
待界面从FilePicker返回后使用基础文件API的fs.openSync接口通过uri打开这个文件得到文件描述符(fd)。 
let uri: string  
//这里需要注意接口权限参数是fs.OpenMode.READ_ONLY。
let file  fs.openSync(uri, fs.OpenMode.READ_ONLY)
console.info(file fd:   file.fd) 
通过fd使用fs.readSync接口读取这个文件内的数据。 
let buffer  new ArrayBuffer(4096)
let readLen  fs.readSync(file.fd, buffer)
console.info(readSync data to file succeed and buffer size is:  readLen)
//读取完成后关闭fd。
fs.closeSync(file) 
选择音频类文件 
导入选择器模块和基础文件API模块。 
import  { picker } from kit.CoreFileKit
import { fileIo as fs } from kit.CoreFileKit
import { BusinessError } from kit.BasicServicesKit
import { common } from kit.AbilityKit 
创建音频类型文件选择选项实例。 
const audioSelectOptions  new picker.AudioSelectOptions() 
创建音频选择器AudioViewPicker实例。调用select()接口拉起FilePicker应用界面进行文件选择。 
let uris: string  
// 请确保 getContext(this) 返回结果为 UIAbilityContext
let context  getContext(this) as common.Context
const audioViewPicker  new picker.AudioViewPicker(context)
audioViewPicker.select(audioSelectOptions).then((audioSelectResult: Arraystring)  {//文件选择成功后返回被选中音频的uri结果集。uris  audioSelectResult[0]console.info(audioViewPicker.select to file succeed and uri is:  uris)}).catch((err: BusinessError)  {console.error(Invoke audioViewPicker.select failed  code is ${err.code}, message is ${err.message})}) 
待界面从FilePicker返回后可以使用基础文件API的fs.openSync接口通过uri打开这个文件得到文件描述符(fd)。 
let uri: string  
//这里需要注意接口权限参数是fs.OpenMode.READ_ONLY。
let file  fs.openSync(uri, fs.OpenMode.READ_ONLY)
console.info(file fd:   file.fd) 
通过fd可以使用基础文件API的fs.readSync接口读取这个文件内的数据。 
let buffer  new ArrayBuffer(4096)
let readLen  fs.readSync(file.fd, buffer)
console.info(readSync data to file succeed and buffer size is:  readLen)
//读取完成后关闭fd。
fs.closeSync(file) 
3. 保存用户文件 
在从网络下载文件到本地或将已有用户文件另存为新的文件路径等场景下需要使用FilePicker提供的保存用户文件的能力。 
保存图片或视频类文件 
当用户需要保存图片、视频等用户文件到图库时无需在应用中申请相册管理模块权限ohos.permission.WRITE_IMAGEVIDEO应用可以通过安全控件或授权弹窗的方式将用户指定的媒体资源保存到图库中。 
(1) 使用安全控件保存媒体库资源 
下面以使用安全控件创建一张图片资源为例。开发步骤如下 
设置安全控件按钮属性。创建安全控件按钮。调用MediaAssetChangeRequest.createImageAssetRequest和PhotoAccessHelper.applyChanges接口创建图片资源。 
import { photoAccessHelper } from kit.MediaLibraryKitEntry
ComponentV2
struct Index {saveButtonOptions: SaveButtonOptions  {icon: SaveIconStyle.FULL_FILLED,text: SaveDescription.SAVE_IMAGE,buttonType: ButtonType.Capsule} // 设置安全控件按钮属性build() {Column() {SaveButton(this.saveButtonOptions) // 创建安全控件按钮.onClick(async (event, result: SaveButtonOnClickResult)  {if (result  SaveButtonOnClickResult.SUCCESS) {try {let context  getContext()let phAccessHelper  photoAccessHelper.getPhotoAccessHelper(context)// 需要确保fileUri对应的资源存在let fileUri  file://com.example.temptest/data/storage  /el2/base/haps/entry/files/test.jpg;let assetChangeRequest: photoAccessHelper.MediaAssetChangeRequest photoAccessHelper.MediaAssetChangeRequest.createImageAssetRequest(context, fileUri)await phAccessHelper.applyChanges(assetChangeRequest)console.info(createAsset successfully, uri:   assetChangeRequest.getAsset().uri)} catch (err) {console.error(create asset failed with   error: ${err.code}, ${err.message})}} else {console.error(SaveButtonOnClickResult create asset failed)}})}.width(100%)}
} 
除了上述通过fileUri从应用沙箱指定资源内容的方式开发者还可以通过ArrayBuffer的方式添加资源内容。 
(2) 使用弹窗授权保存媒体库资源 
下面以弹窗授权的方式保存一张图片资源为例。开发步骤如下 
指定待保存到媒体库的位于应用沙箱的应用文件图片uri。指定待保存照片的创建选项包括文件后缀和照片类型标题和照片子类型可选。调用showAssetsCreationDialog基于弹窗授权的方式获取的目标媒体文件uri。将来源于应用沙箱的照片内容写入媒体库的目标uri。 
import { photoAccessHelper } from kit.MediaLibraryKit
import { fileIo } from kit.CoreFileKitlet context  getContext(this)
let phAccessHelper  photoAccessHelper.getPhotoAccessHelper(context)async function example() {try {// 指定待保存到媒体库的位于应用沙箱的图片urilet srcFileUri  file://com.example.temptest/data/storage/ el2/base/haps/entry/files/test.jpglet srcFileUris: Arraystring  [srcFileUri]// 指定待保存照片的创建选项包括文件后缀和照片类型标题和照片子类型可选let photoCreationConfigs: ArrayphotoAccessHelper.PhotoCreationConfig  [{title: test, // 可选fileNameExtension: jpg,photoType: photoAccessHelper.PhotoType.IMAGE,subtype: photoAccessHelper.PhotoSubtype.DEFAULT, // 可选}]// 基于弹窗授权的方式获取媒体库的目标urilet desFileUris: Arraystring  await phAccessHelper.showAssetsCreationDialog(srcFileUris, photoCreationConfigs)// 将来源于应用沙箱的照片内容写入媒体库的目标urilet desFile: fileIo.File  await fileIo.open(desFileUris[0], fileIo.OpenMode.WRITE_ONLY)let srcFile: fileIo.File  await fileIo.open(srcFileUri, fileIo.OpenMode.READ_ONLY)await fileIo.copyFile(srcFile.fd, desFile.fd)fileIo.closeSync(srcFile)fileIo.closeSync(desFile)console.info(create asset by dialog successfully)} catch (err) {console.error(failed to create asset by dialog successfully   errCode is: ${err.code}, ${err.message})}
} 
保存文档类文件 
模块导入。 
import { picker } from kit.CoreFileKit
import { fileIo as fs } from kit.CoreFileKit
import { BusinessError } from kit.BasicServicesKit
import { common } from kit.AbilityKit 
配置保存选项。 
// 创建文件管理器选项实例。
const documentSaveOptions  new picker.DocumentSaveOptions()
// 保存文件名可选。 默认为空。
documentSaveOptions.newFileNames  [DocumentViewPicker01.txt]
// 保存文件类型[后缀类型描述|后缀类型],选择所有文件所有文件(*.*)|.*可选
// 如果选择项存在多个后缀最大限制100个过滤后缀默认选择第一个。
// 如果不传该参数默认无过滤后缀。
documentSaveOptions.fileSuffixChoices  [文档|.txt, .pdf] 
创建文件选择器DocumentViewPicker实例。调用save()接口拉起FilePicker界面进行文件保存。 
let uris: Arraystring  []
// 请确保 getContext(this) 返回结果为 UIAbilityContext
let context  getContext(this) as common.Context
const documentViewPicker  new picker.DocumentViewPicker(context)
documentViewPicker.save(documentSaveOptions).then((documentSaveResult: Arraystring)  {uris  documentSaveResultconsole.info(documentViewPicker.save to file succeed and uris are:  uris)}).catch((err: BusinessError)  {console.error(Invoke documentViewPicker.save failed,   code is ${err.code}, message is ${err.message})}) 
待界面从FilePicker返回后使用基础文件API的fs.openSync接口通过URI打开这个文件得到文件描述符(fd)。 
const uri  
//这里需要注意接口权限参数是fs.OpenMode.READ_WRITE。
let file  fs.openSync(uri, fs.OpenMode.READ_WRITE)
console.info(file fd:   file.fd) 
通过(fd)使用基础文件API的fs.writeSync接口对这个文件进行编辑修改编辑修改完成后关闭(fd)。 
let writeLen: number  fs.writeSync(file.fd, hello, world)
console.info(write data to file succeed and size is:  writeLen)
fs.closeSync(file) 
保存音频类文件 
模块导入。 
import { picker } from kit.CoreFileKit
import { fileIo as fs } from kit.CoreFileKit
import { BusinessError } from kit.BasicServicesKit
import { common } from kit.AbilityKit 
配置保存选项。 
const audioSaveOptions  new picker.AudioSaveOptions()
// 保存文件名可选 
audioSaveOptions.newFileNames  [AudioViewPicker01.mp3] 
创建音频选择器AudioViewPicker实例。调用save()接口拉起FilePicker界面进行文件保存。 
let uri: string  
// 请确保 getContext(this) 返回结果为 UIAbilityContext
let context  getContext(this) as common.Context
const audioViewPicker  new picker.AudioViewPicker(context);
audioViewPicker.save(audioSaveOptions).then((audioSelectResult: Arraystring)  {uri  audioSelectResult[0]console.info(audioViewPicker.save to file succeed and uri is:  uri)}).catch((err: BusinessError)  {console.error(Invoke audioViewPicker.save failed, code is   ${err.code}, message is ${err.message})}) 
待界面从FilePicker返回后可以使用基础文件API的fs.openSync接口通过URI打开这个文件得到文件描述符(fd)。 
//这里需要注意接口权限参数是fileIo.OpenMode.READ_WRITE。
let file  fs.openSync(uri, fs.OpenMode.READ_WRITE)
console.info(file fd:   file.fd) 
通过(fd)使用基础文件API的fs.writeSync接口对这个文件进行编辑修改编辑修改完成后关闭(fd)。 
let writeLen  fs.writeSync(file.fd, hello, world)
console.info(write data to file succeed and size is:  writeLen)
fs.closeSync(file) 
DOWNLOAD模式保存文件 
该模式具备自动在 Download/包名/ 路径创建目录、跳过文件选择界面直接保存文件、并返回具备持久化权限的URI供用户创建文件的能力。 
模块导入。 
import { fileUri, picker } from kit.CoreFileKit
import { fileIo as fs } from kit.CoreFileKit
import { BusinessError } from kit.BasicServicesKit
import { common } from kit.AbilityKit 
配置下载模式。 
const documentSaveOptions  new picker.DocumentSaveOptions()
// 配置保存的模式为DOWNLOAD若配置了DOWNLOAD模式
// 此时配置的其他documentSaveOptions参数将不会生效。
documentSaveOptions.pickerMode  picker.DocumentPickerMode.DOWNLOAD 
保存到下载目录。 
let uri: string  
// 请确保 getContext(this) 返回结果为 UIAbilityContext
let context  getContext(this) as common.Context
const documentViewPicker  new picker.DocumentViewPiker(context)
const documentSaveOptions  new picker.DocumentSaveOptions()
documentSaveOptions.pickerMode  picker.DocumentPickerMode.DOWNLOAD;
documentViewPicker.save(documentSaveOptions ).then((documentSaveResult: Arraystring)  {uri  documentSaveResult[0];console.info(documentViewPicker.save succeed and uri is:  uri)const testFilePath  new fileUri.FileUri(uri  /test.txt).pathconst file  fs.openSync(testFilePath, fs.OpenMode.CREATE | fs.OpenMode.READ_WRITE)fs.writeSync(file.fd, Hello HarmonyOS)fs.closeSync(file.fd);}).catch((err: BusinessError)  {console.error(Invoke documentViewPicker.save failed,   code is ${err.code}, message is ${err.message})}) 
 文章转载自: http://www.morning.plchy.cn.gov.cn.plchy.cn http://www.morning.zpqk.cn.gov.cn.zpqk.cn http://www.morning.wfdlz.cn.gov.cn.wfdlz.cn http://www.morning.hhfqk.cn.gov.cn.hhfqk.cn http://www.morning.kfbth.cn.gov.cn.kfbth.cn http://www.morning.stmkm.cn.gov.cn.stmkm.cn http://www.morning.gwhjy.cn.gov.cn.gwhjy.cn http://www.morning.nppml.cn.gov.cn.nppml.cn http://www.morning.htsrm.cn.gov.cn.htsrm.cn http://www.morning.yqwrj.cn.gov.cn.yqwrj.cn http://www.morning.mhcft.cn.gov.cn.mhcft.cn http://www.morning.ccjhr.cn.gov.cn.ccjhr.cn http://www.morning.ptysj.cn.gov.cn.ptysj.cn http://www.morning.jrlgz.cn.gov.cn.jrlgz.cn http://www.morning.rwzmz.cn.gov.cn.rwzmz.cn http://www.morning.tmbtm.cn.gov.cn.tmbtm.cn http://www.morning.tgyqq.cn.gov.cn.tgyqq.cn http://www.morning.bqyb.cn.gov.cn.bqyb.cn http://www.morning.tfgkq.cn.gov.cn.tfgkq.cn http://www.morning.wkmrl.cn.gov.cn.wkmrl.cn http://www.morning.drfcj.cn.gov.cn.drfcj.cn http://www.morning.bwnd.cn.gov.cn.bwnd.cn http://www.morning.ksqyj.cn.gov.cn.ksqyj.cn http://www.morning.dkqbc.cn.gov.cn.dkqbc.cn http://www.morning.gxklx.cn.gov.cn.gxklx.cn http://www.morning.qhln.cn.gov.cn.qhln.cn http://www.morning.lssfd.cn.gov.cn.lssfd.cn http://www.morning.klyyd.cn.gov.cn.klyyd.cn http://www.morning.bwrbm.cn.gov.cn.bwrbm.cn http://www.morning.ptwqf.cn.gov.cn.ptwqf.cn http://www.morning.nkwgy.cn.gov.cn.nkwgy.cn http://www.morning.kqcqr.cn.gov.cn.kqcqr.cn http://www.morning.nhbhc.cn.gov.cn.nhbhc.cn http://www.morning.nfyc.cn.gov.cn.nfyc.cn http://www.morning.oumong.com.gov.cn.oumong.com http://www.morning.wrfk.cn.gov.cn.wrfk.cn http://www.morning.ppqjh.cn.gov.cn.ppqjh.cn http://www.morning.mbpzw.cn.gov.cn.mbpzw.cn http://www.morning.mhpmw.cn.gov.cn.mhpmw.cn http://www.morning.xwbwm.cn.gov.cn.xwbwm.cn http://www.morning.hjlsll.com.gov.cn.hjlsll.com http://www.morning.mdjzydr.com.gov.cn.mdjzydr.com http://www.morning.wmlby.cn.gov.cn.wmlby.cn http://www.morning.qbxdt.cn.gov.cn.qbxdt.cn http://www.morning.hjwxm.cn.gov.cn.hjwxm.cn http://www.morning.hpkgm.cn.gov.cn.hpkgm.cn http://www.morning.gthc.cn.gov.cn.gthc.cn http://www.morning.rhzzf.cn.gov.cn.rhzzf.cn http://www.morning.tbnn.cn.gov.cn.tbnn.cn http://www.morning.plqkz.cn.gov.cn.plqkz.cn http://www.morning.fplwz.cn.gov.cn.fplwz.cn http://www.morning.lmdkn.cn.gov.cn.lmdkn.cn http://www.morning.kpxnz.cn.gov.cn.kpxnz.cn http://www.morning.tfpbm.cn.gov.cn.tfpbm.cn http://www.morning.hryhq.cn.gov.cn.hryhq.cn http://www.morning.wcjk.cn.gov.cn.wcjk.cn http://www.morning.tgpgx.cn.gov.cn.tgpgx.cn http://www.morning.rrms.cn.gov.cn.rrms.cn http://www.morning.qydgk.cn.gov.cn.qydgk.cn http://www.morning.qpqb.cn.gov.cn.qpqb.cn http://www.morning.rfrxt.cn.gov.cn.rfrxt.cn http://www.morning.xbtlt.cn.gov.cn.xbtlt.cn http://www.morning.lstmg.cn.gov.cn.lstmg.cn http://www.morning.bfmq.cn.gov.cn.bfmq.cn http://www.morning.qdxtj.cn.gov.cn.qdxtj.cn http://www.morning.rycd.cn.gov.cn.rycd.cn http://www.morning.ydhck.cn.gov.cn.ydhck.cn http://www.morning.fmry.cn.gov.cn.fmry.cn http://www.morning.tqrxm.cn.gov.cn.tqrxm.cn http://www.morning.bnrnb.cn.gov.cn.bnrnb.cn http://www.morning.ndcf.cn.gov.cn.ndcf.cn http://www.morning.gbfuy28.cn.gov.cn.gbfuy28.cn http://www.morning.zzfjh.cn.gov.cn.zzfjh.cn http://www.morning.bpptt.cn.gov.cn.bpptt.cn http://www.morning.rqmr.cn.gov.cn.rqmr.cn http://www.morning.ykwbx.cn.gov.cn.ykwbx.cn http://www.morning.ymwnc.cn.gov.cn.ymwnc.cn http://www.morning.mrfr.cn.gov.cn.mrfr.cn http://www.morning.bhgnj.cn.gov.cn.bhgnj.cn http://www.morning.taojava.cn.gov.cn.taojava.cn