文档中心 > 开发指南

快速上手文件下载

更新时间:2024/08/21 访问次数:1516

一、配置

参考文章:链接

参考文章《外部域名添加》的开通云服务添加章节。

二、空小游戏项目发起http请求

1. 创建项目

后台创建项目

参考文章:链接

参考文章的第一章。

将域名g.alicdn.com配置到后台上,下文会用到;

IDE创建项目

选择对应的项目,然后选择设置项目保存路径,点击【确定】。

2. 开发

安装云服务的SDK

npm install @tbmp/mp-cloud-sdk


引入库

在game.js的第一行引入

import cloud from '@tbmp/mp-cloud-sdk';

定义测试函数

注意:代码中所涉及到的测试资源仅供测试参考,不能用于生产环境。

代码中设计的http请求详情可以阅读《快速上手Http请求》文章;

const fs = my.getFileSystemManager();

const createDir = (targetPath) => {
  const mkdirResult = fs.mkdirSync({ dirPath: targetPath, recursive: true });
  console.log('创建目录:', targetPath, '结果', mkdirResult);
}

const getFileMD5 = (filePath) => {
  const fileInfo = fs.getFileInfoSync({ filePath, digestAlgorithm: 'md5' });
  return fileInfo?.digest;
}

const readUTF8File = (filePath) => {
  fs.readFile({
    filePath,
    encoding: 'utf-8', // 如果不传 encoding,则以 ArrayBuffer 格式读取文件的二进制内容
    success: (textData) => {
      console.log('文本的内容', textData);
    }
  });
}

const requestConfig = () => {
  return new Promise((res, rej) => {

    cloud.init({
      //test、online
      env: 'test'
    });
    const result = cloud.application.httpRequest({
      //不需要完整域名,只需要接口访问路径即可
      path: '/hdtest/igo_assets_test/0.6.0/json/assets.json',
      'method': 'GET',
      'headers': {},

      'exts': {
        "timeout": 1000,
        //空应用调用需要填写该字段,包括协议头以及端口号(可省略),支持http、https
        "domain": "https://g.alicdn.com"
      }
    }).then((httpRequestRes) => {
      console.log('requestConfig', httpRequestRes);
      res(JSON.parse(httpRequestRes));
    }).catch((httpRequestError) => {
      rej(httpRequestError);
    });



  });

}

// 在线生成文件md5码
const readTextPromise = () => {
  return new Promise((res, rej) => {
    const fileName = 'utf8_arraybuffer_base64';
    const filePath = `${my.env.USER_DATA_PATH}/data/${fileName}`;

    requestConfig().then((requestConfigRes) => {
      console.log('requestConfig res=', requestConfigRes);
      const configData = requestConfigRes;
      const localFileMD5 = getFileMD5(filePath);
      const remoteFileMD5 = configData.find(item => item.name === fileName)?.md5;

      console.log('测试', localFileMD5, remoteFileMD5)

      //  如果md5不一致,则进行文件下载
      if (localFileMD5 === remoteFileMD5) {
        console.log('本地文件md5一致,无需下载');
        readUTF8File(filePath);
        res(true);
      } else {
        console.log('本地文件md5不一致,需要下载');
        my.downloadFile({
          url: 'https://g.alicdn.com/hdtest/igo_assets_test/0.4.0/bin/' + fileName,
          success(data) {
            const textPath = data?.apFilePath;

            createDir(`${my.env.USER_DATA_PATH}/data/`);

            fs.copyFile({
              srcPath: textPath,
              destPath: filePath,
              success: (copyFileRes) => {
                console.log("拷贝文件成功", copyFileRes);
                readUTF8File(filePath);
                res(true);
              },
              fail: (copyFileError) => {
                console.log("拷贝文件失败", copyFileError);
                rej(false);
              }
            });

          },
          fail(res) {
            console.error('text报错', res.errorMessage || res.error);
            rej(false);
          },
        })
      }
    }).catch((loadAssetError) => {
      console.error('下载asset.json失败', loadAssetError);
      rej(false);
    })

  });
};

const targetPath = `${my.env.USER_DATA_PATH}/unzipDir02`;
const unzipPromise = () => {
  return new Promise((res, rej) => {
    my.downloadFile({
      url: 'https://g.alicdn.com/hdtest/igo_assets_test/0.5.0/zip/woman.jpg.zip',
      success(data) {
        try {
          const path = data?.apFilePath;

          const rmdir = fs.rmdirSync({ dirPath: targetPath, recursive: true });
          console.log('rmdir', rmdir);
          createDir(targetPath);
          fs.unzip({
            zipFilePath: path,
            targetPath: targetPath,
            success: function (unzipResult) {
              console.log('解压成功', unzipResult);

              try {
                // 存储空间有限,需要手动维护空间,若不处理及时处理会导致存储空间超过200mb限制,文件操作会失败
                fs.unlink({
                  filePath: path,
                  success: unlinkResult => console.log('删除zip包成功', unlinkResult),
                  fail: unlinkError => console.error('删除zip包失败', unlinkError)
                });
              } catch (error) { }

              const fileList = fs.readdirSync({ dirPath: targetPath });
              console.log('fileList', fileList);
              const unzipFileInfo = fs.getFileInfoSync({ filePath: targetPath + '/' + fileList?.files?.[0] });
              console.log('unzipFileInfo', unzipFileInfo);

              res(true);
            },
            fail: function (err) {
              console.log('解压失败', err);
              rej(false)
            }
          });
        } catch (error) {
          console.log('解压前准备工作失败', error);
          rej(false)
        }
      },
      fail(res) {
        console.error('下载报错', res.errorMessage || res.error);
        rej(false);
      },
    })
  });
}

const testErrorCode10028 = () => {
  const testErrorPath = `${my.env.USER_DATA_PATH}/testError`
  return new Promise((res, rej) => {
    my.downloadFile({
      url: 'https://g.alicdn.com/hdtest/igo_assets_test/0.5.0/zip/woman.jpg.zip',
      success(data) {
        try {
          const path = data?.apFilePath;

          const rmdir = fs.rmdirSync({ dirPath: testErrorPath, recursive: true });
          console.log('rmdir', rmdir);


          let count = 0;

          const intervalId = setInterval(() => {


            const subPath = `${testErrorPath}/${count}`;
            createDir(subPath);
            fs.unzip({
              zipFilePath: path,
              targetPath: subPath,
              success: function (unzipResult) {
                console.log('解压成功', unzipResult); // 限制200mb大小,大概下载到70+的时候会触发100028的错误

                const fileList = fs.readdirSync({ dirPath: subPath });
                console.log('fileList', fileList);
                const unzipFileInfo = fs.getFileInfoSync({ filePath: subPath + '/' + fileList?.files?.[0] });
                console.log('unzipFileInfo', unzipFileInfo);

                // res(true);
              },
              fail: function (err) {
                console.log('解压失败', err);
                if(err?.error === '10028'){
                  console.warn('监控到10028错误,说明磁盘已满,清理可清理目录后可继续操作')
                  const rmdir = fs.rmdirSync({ dirPath: testErrorPath, recursive: true });
                  console.log('rmdir', rmdir);
                }else{
                  rej(false)
                }
              }
            });

            count++;
            if (count >= 200) {
              clearInterval(intervalId); // 停止定时器
              console.log('Completed 200 executions.');
            }
          }, 200); // 1000 毫秒(1秒)

        } catch (error) {
          console.log('解压前准备工作失败', error);
          rej(false)
        }
      },
      fail(res) {
        console.error('下载报错', res.errorMessage || res.error);
        rej(false);
      },
    })
  });
}


const downloadTest = async () => {
  console.log('本地缓存目录的虚拟路径', my.env.USER_DATA_PATH, { env: my.env });

  try {
    await readTextPromise(); // 读取文本文件示例
    await unzipPromise(); // 解压文件示例
    await testErrorCode10028(); // 内存满的监控和处理


  } catch (error) {
    console.error(error);
  }
}

调用

在game.js的代码尾部调用测试函数

downloadTest();

说明

  • 目前手机淘宝规定有2大类型文件缓存类型。临时文件缓存和用户文件缓存。临时文件缓存会定期清理,用户文件缓存则不会清理,需要开发者去维护存储空间,避免存储空间不足导致无法进行文件操作。
  • 目前临时文件缓存和用户文件缓存共享200mb的存储空间,开发者可以根据一下建议合理利用;
  • 缓存路径均已虚拟路径透出给开发者,开发者在使用接口传参的时候也是使用虚拟路径。临时文件缓存虚拟路径为:https://tmp/。用户文件缓存的虚拟路径为:https://usr/ ,可以用my.env.USER_DATA_PATH来获取。
  • 在IDE下,临时文件缓存虚拟路径为https://resource/,而非https://tmp/。

建议

建议1:在下载文件之前,对比已有文件的MD5码,避免重复下载。

  • 可以在服务器中维护一份需要下载的资源列表极其对应的MD5码。
  • 获取本地MD5码的参考getFileMD5函数。注意digestAlgorithm的值区分打小写;

建议2:将游戏的资源放在一个统一目录下,可以方便清理。

  • 删除文件夹使用的是rmdir接口,清理文件使用的是unlinke接口。
  • 创建文件夹和删除文件夹注意带上recursive: true参数;

建议3:监听到10028错误,则需要及时清空过期文件,否则无法进行后续操作。

  • 存储空间有限,需要手动维护空间,若不处理及时处理会导致存储空间超过200mb限制,文件操作会失败。
  • downloadFile、copyFile、writeFile和unzip会检查存储空间是否已满,如果分配的内存已满,会抛出10028的错误码;
  • 根据建议2,可以删除过期数据所在的文件夹,然后再对文件进行重试操作;

建议4:下载zip解压后,将zip包删除以节省空间。

  • 使用unlink接口进行文件删除;

FAQ

关于此文档暂时还没有FAQ
返回
顶部