http://tmp00002.zhaodashen.cn/hello.txt

http://tmp00002.zhaodashen.cn/hello2.docx

http://tmp00002.zhaodashen.cn/hello3.pdf

http://tmp00002.zhaodashen.cn/hello4.zip

https://developer.huawei.com/consumer/cn/doc/harmonyos-references-V13/js-apis-request-V13#requestdownloadfile9

https://developer.huawei.com/consumer/cn/doc/harmonyos-references-V13/js-apis-zlib-V13

基础使用

    import { BusinessError, request } from '@kit.BasicServicesKit'
    import { fileIo as fs } from '@kit.CoreFileKit'
    import { zlib } from '@kit.BasicServicesKit';
    
    @Entry
    @Component
    struct Index {
      private filePath:string = getContext().filesDir + '/'
    
    
      @State currentSize:number = 0
      @State totalSize:number = 0
    
    
      unlinkFile(fileName:string) {
        if ( fs.accessSync(this.filePath+fileName) ) {
          fs.unlinkSync(this.filePath+fileName)
        }
      }
    
      downloadFile(url:string) {
    
        const fileName:string = url.split('/').pop() as string
    
        // fs模块检查文件是否存在 存在就删除
        this.unlinkFile(fileName)
        // 下载
        request.downloadFile(getContext(), {
          url,
          filePath:  this.filePath + fileName // 字符串变数组 [...,'node-v22.16.0.pkg'] 通过pop弹出最后数据  pop是一个函数 返回弹出的数据
        }).then(uploadTask => {
          uploadTask.on("progress", (receivedSize: number, totalSize: number) => {
            // receivedSize 当前下载字节
            // totalSize 总字节
            console.log('数据:', receivedSize, totalSize)
            this.currentSize = receivedSize
            this.totalSize = totalSize
          })
          uploadTask.on("complete", () => {
            console.log('下载完成')
          })
        })
      }
    
      build() {
        Column() {
          Button('下载文件txt').onClick(() => {
            this.downloadFile('http://tmp00002.zhaodashen.cn/hello.txt')
          })
          Progress({
            value: this.currentSize,
            total: this.totalSize,
            style:ProgressStyle.Ring
          })
          Button('下载文件node安装包').onClick(() => {
            this.downloadFile('https://npmmirror.com/mirrors/node/v22.16.0/node-v22.16.0.pkg')
          })
    
          Button('下载文件zip').onClick(() => {
            this.downloadFile('http://tmp00002.zhaodashen.cn/hello4.zip')
          })
    
    
          Button('zip解压').onClick(() => {
            let inFile =  this.filePath + 'hello4.zip';
            let outFileDir = getContext().cacheDir
            let options: zlib.Options = {
              level: zlib.CompressLevel.COMPRESS_LEVEL_DEFAULT_COMPRESSION
            };
    
            try {
              zlib.decompressFile(inFile, outFileDir, options, (errData: BusinessError) => {
                if (errData !== null) {
                  console.error(`errData is errCode:${errData.code}  message:${errData.message}`);
                }
              })
            } catch (errData) {
              let code = (errData as BusinessError).code;
              let message = (errData as BusinessError).message;
              console.error(`errData is errCode:${code}  message:${message}`);
            }
            // .....
          })
        }
      }
    }

    把冗余代码封装起来

    import { photoAccessHelper } from '@kit.MediaLibraryKit';
    import { BusinessError, request } from '@kit.BasicServicesKit';
    import  { fileIo, picker } from '@kit.CoreFileKit';
    import { cameraPicker } from '@kit.CameraKit';
    import { camera } from '@kit.CameraKit';
    
    
    export interface UploadFileType {
      database: string;
      url: string;
      preview: string;
    }
    
    export interface PostUploadFileResType {
      state: number;
      msg: string;
      data: UploadFileType;
    }
    
    
    
    class FileUploadDownloadUtil {
      // 1 拿到媒体资源本地路径
      chooseImage():Promise<string[]> {
        return new Promise((resolve, reject) => {
          const photoSelectOptions = new photoAccessHelper.PhotoSelectOptions();
          photoSelectOptions.MIMEType = photoAccessHelper.PhotoViewMIMETypes.IMAGE_TYPE; // 过滤选择媒体文件类型为IMAGE
          photoSelectOptions.maxSelectNumber = 1; // 选择媒体文件的最大数目
          let uris: Array<string> = [];
          const photoViewPicker = new photoAccessHelper.PhotoViewPicker();
          photoViewPicker.select(photoSelectOptions).then((photoSelectResult: photoAccessHelper.PhotoSelectResult) => {
            uris = photoSelectResult.photoUris; // 数组 里面是一个个file 也就是本地媒体库图片地址  咱们可以直接预览
            // this.localFilePath = photoSelectResult.photoUris[0]
            resolve(uris)
            console.info('photoViewPicker.select to file succeed and uris are:' + uris);  // file://media/Photo/947/IMG_1742896185_814/IMG_814.jpg
          }).catch((err: BusinessError) => {
            reject([])
            console.error(`Invoke photoViewPicker.select failed, code is ${err.code}, message is ${err.message}`);
          })
        })
      }
    
      chooseFile():Promise<string[]> {
        return new Promise((resolve, reject) => {
          const documentSelectOptions = new picker.DocumentSelectOptions();
          // 选择文档的最大数目(可选)。
          documentSelectOptions.maxSelectNumber = 5;
          // 指定选择的文件或者目录路径(可选)。
          // documentSelectOptions.defaultFilePathUri = "file://docs/storage/Users/currentUser/test";
          // 选择文件的后缀类型['后缀类型描述|后缀类型'](可选,不传该参数,默认不过滤,即显示所有文件),若选择项存在多个后缀名,则每一个后缀名之间用英文逗号进行分隔(可选),后缀类型名不能超过100。此外2in1设备支持通过通配符方式['所有文件(*.*)|.*'],表示为显示所有文件,手机暂不支持该配置。
          documentSelectOptions.fileSuffixFilters = ['图片(.png, .jpg)|.png,.jpg', '文档|.txt', '视频|.mp4', '.pdf'];
          //选择是否对指定文件或目录授权,true为授权,当为true时,defaultFilePathUri为必选参数,拉起文管授权界面;false为非授权(默认为false),拉起常规文管界面(可选),仅支持2in1设备。
          documentSelectOptions.authMode = false;
          // 创建文件选择器实例
          const documentViewPicker = new picker.DocumentViewPicker(getContext(this));
          documentViewPicker.select(documentSelectOptions).then((documentSelectResult: Array<string>) => {
            //文件选择成功后,返回被选中文档的uri结果集。
            console.info('documentViewPicker.select to file succeed and uris are:' + documentSelectResult);
            resolve(documentSelectResult)
          }).catch((err: BusinessError) => {
            reject([])
            console.error(`Invoke documentViewPicker.select failed, code is ${err.code}, message is ${err.message}`);
          })
        })
      }
    
      chooseCamera():Promise<string> {
        return new Promise(async (resolve, reject) => {
    
          try {
            const pickerProfile: cameraPicker.PickerProfile = {
              cameraPosition: camera.CameraPosition.CAMERA_POSITION_BACK
            };
            const  pickerResult: cameraPicker.PickerResult = await cameraPicker.pick(getContext(), [cameraPicker.PickerMediaType.PHOTO, cameraPicker.PickerMediaType.VIDEO], pickerProfile);
            console.log("the pick pickerResult is:" + JSON.stringify(pickerResult)); // 返回一个对象, 里面的【resultUri】本地的媒体地址 file:...
            console.log("the pick pickerResult is:" + pickerResult.resultUri); // file://media/Photo/2418/IMG_1748244688_2173/IMG_20250526_152948.jpg
            resolve(pickerResult.resultUri)
          } catch (error) {
            reject('')
            let err = error as BusinessError;
            console.error(`the pick call failed. error code: ${err.code}`);
          }
    
        })
      }
    
      // 2 拷贝到沙箱
      fileMoveSx(filePath:string):[string, string] {
        const fileType = filePath.split('.').pop() as string
        const fileName = Date.now() + '_' + Math.floor(  Math.random() * (9999-1000+1)+1000  ) + '.' + fileType
        const copyFilePath = getContext(this).cacheDir + '/' + fileName
        // - 2.1 通过 openSync 读取 媒体库文件
        const file = fileIo.openSync(filePath, fileIo.OpenMode.READ_ONLY)
        // - 2.2 通过 fileIo.copyFileSync(file.fd, copyFilePath)
        // fileIo.copyFileSync(原文件唯一标识, 沙箱目录及文件名)
        fileIo.copyFileSync(file.fd, copyFilePath)
        // 细节:copyFilePath沙箱中文件生成规则必须唯一
        // fileType
        // fileName   时间戳 + 随机数1000~9999 + . 后缀
        // copyFilePath
        console.log('最终沙箱目录:', copyFilePath)
        // return ['文件类型', '文件名称']
        return [fileType, fileName]
      }
    
      // 3 上传文件
      upload(filePath:string):Promise<string>{ // 空字符串代表上传失败
    
        // # 3.1 就是1 媒体本地路径
        const temp = this.fileMoveSx(filePath)
        const fileType = temp[0]
        const fileName = temp[1]
    
        // # 3.2 接着请求接口
        return new Promise((resolve, reject) => {
          // 三、上传图片到服务器
          request.uploadFile(getContext(this), {
            method: 'POST',
            url: 'http://123.56.141.187:8001/upload/create',
            header: {},
            files: [
              {name: 'file', uri:'internal://cache/'+fileName,  type: fileType,filename:fileName }
            ],
            data: []
          })
            .then((uploadTask) => {
              uploadTask.on('progress', (uploadedSize: number, totalSize: number) => {
                console.info("upload totalSize:" + totalSize + "  uploadedSize:" + uploadedSize);
              })
              uploadTask.on('headerReceive', (headers:ESObject) => {
                const serverData: PostUploadFileResType = JSON.parse(headers?.body)
                // console.log('服务器数据:', serverData.state)
                // console.log('服务器数据:', serverData.msg)
                // console.log('服务器数据:', serverData.data?.database)  // 图片名
                // console.log('服务器数据:', serverData.data?.preview)   // 完整网址+图片
                resolve(serverData.data?.database)
              })
              uploadTask.on('complete', () => {
                console.log('上传完成')
              })
              uploadTask.on('fail', () => {
                reject('')
                console.log('上传失败')
              })
            })
          // 三、上传图片到服务器 end
        })
      }
    
      // 3 下载文件
      download(url:string, filePath:string):Promise<boolean>{ // 沙箱地址
        if ( fileIo.accessSync(filePath) ) {
          fileIo.unlinkSync(filePath)
        }
    
        return new Promise((resolve, reject) => {
          // 下载
          request.downloadFile(getContext(), {
            url,
            filePath
          }).then(uploadTask => {
            uploadTask.on("complete", () => {
              console.log('下载完成')
              resolve(true)
            })
            uploadTask.on("fail", () => {
              console.log('下载失败')
              reject(false)
            })
          })
        })
      }
    }
    
    export const fileUploadDownloadUtil = new FileUploadDownloadUtil()
    

    使用

    import { fileUploadDownloadUtil } from '../utils/FileUploadDownloadUtil'
    
    @Entry
    @Component
    struct Index {
      build() {
        Button('上传图片').onClick(async () => {
          const filePath:string[] = await fileUploadDownloadUtil.chooseImage()
          if (filePath.length) {
            const serverData = await fileUploadDownloadUtil.upload(filePath[0])
            console.log('- 最终结果:' + serverData)
            console.log('- 最终结果:' + serverData)
            console.log('- 最终结果:' + serverData)
            console.log('- 最终结果:' + serverData)
            console.log('- 最终结果:' + serverData)
          }
        })
      }
    }

    鸿蒙开发者班级

    Logo

    讨论HarmonyOS开发技术,专注于API与组件、DevEco Studio、测试、元服务和应用上架分发等。

    更多推荐