You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

NativeScript 8.3(TypeScript)应用文件下载性能与健壮性优化咨询

NativeScript文件下载功能:性能与健壮性优化建议

针对你的NativeScript 8.3(TypeScript)应用的文件下载功能,结合给定环境(文件大小<200KB、WiFi环境、Express/Node服务端),从性能和健壮性角度给出以下优化建议:


服务端优化(Express路由)

当前代码

const download = (req, res) => {
  const fileName = req.params.name;
  res.download(dirRoot + fileName, fileName, (err) => {
    if (err) {
      res.status(500).send({message: "Echec téléchargement de fichier. " + err,});
      console.log("!!!!!! download, échec envoi du fichier " + dirRoot + fileName);
    }
    else 
      console.log(getCurrentDate() + " Envoi réussi du fichier " + dirRoot + fileName);
  });
};

健壮性优化

  • 路径安全校验:直接拼接文件名存在路径遍历风险(如传入../malicious.csv),用path.resolve限制访问范围:
    const safePath = path.resolve(dirRoot, fileName);
    if (!safePath.startsWith(dirRoot)) {
      return res.status(403).send({message: "Accès refusé"});
    }
    
  • 文件存在性预检查:提前校验文件是否存在,返回明确的404错误而非通用500:
    fs.access(safePath, fs.constants.F_OK, (err) => {
      if (err) {
        return res.status(404).send({message: "Fichier non trouvé"});
      }
      res.download(safePath, fileName, ...);
    });
    
  • 错误信息脱敏:避免向客户端暴露服务器内部细节,仅返回通用提示,详细错误仅记录日志:
    if (err) {
      res.status(500).send({message: "Échec du téléchargement, veuillez réessayer"});
      console.error("Erreur envoi fichier", safePath, err);
    }
    

性能优化

  • 启用静态文件缓存:添加缓存头让客户端缓存文件,减少重复请求:
    res.setHeader('Cache-Control', 'public, max-age=86400'); // 缓存1天
    res.download(safePath, fileName, ...);
    
  • 保持流式传输:res.download已默认使用流式传输,无需额外修改,这能避免将整个文件加载到内存,适合并发场景。

客户端优化(NativeScript TypeScript)

当前代码

export async function GetStock():Promise<string>  {
  let result = "";
  if (global.selfIP != "") {
    let serverUrl = "http://" + global.serverIP + ":8080/files/stock.csv";
    await Http.request({url : serverUrl, method : "GET",}).then(
      (response: HttpResponse) => {
        try {
          if ((response.statusCode >= 200) && (response.statusCode <=304)) {
            const resultat   = response.content.toString();
            const chemin     : string = path.join(downloadsPath, 'stock.csv')
            const filefevcsv : File = File.fromPath(chemin);
            filefevcsv.writeTextSync(resultat, WriteOnError, encoding.UTF_8);
          }
          else
            throw Error("Code réponse du serveur : " + response.statusCode);
        }
        catch(err) {
          result = serverUrl + "\nException traitement requete: " + err.message;
        }
      },
      (e) => {
        result = serverUrl + "\nException requete: " + e.message;
      }
    ),
    (error) => {
      result += serverUrl + "\nErreur requête : " + error;
    }
  }
  else 
    result += "Connexion wifi non établie";
  return result;
}

健壮性优化

  • 统一异步代码风格:移除await与then/catch的混合使用,改用try/catch包裹await,逻辑更清晰:
    export async function GetStock(): Promise<string> {
      if (!global.selfIP) {
        return "Connexion wifi non établie";
      }
      const serverUrl = `http://${global.serverIP}:8080/files/stock.csv`;
      try {
        const response = await Http.request({ url: serverUrl, method: "GET" });
        if (!(response.statusCode >= 200 && response.statusCode <= 304)) {
          throw new Error(`Code réponse du serveur : ${response.statusCode}`);
        }
        const resultat = response.content.toString();
        const chemin = path.join(downloadsPath, 'stock.csv');
        const filefevcsv = File.fromPath(chemin);
        filefevcsv.writeTextSync(resultat, WriteOnError, encoding.UTF_8);
      } catch (err: any) {
        return `${serverUrl}\nException: ${err.message}`;
      }
      return "";
    }
    
  • 添加请求超时:设置超时时间避免请求无限等待:
    const response = await Http.request({ 
      url: serverUrl, 
      method: "GET",
      timeout: 10000 // 10秒超时
    });
    
  • 细化文件写入错误:区分网络错误与文件写入错误,提升问题定位效率:
    try {
      const response = await Http.request({ url: serverUrl, method: "GET" });
      // ... 状态码校验
      const resultat = response.content.toString();
      const chemin = path.join(downloadsPath, 'stock.csv');
      const filefevcsv = File.fromPath(chemin);
      try {
        filefevcsv.writeTextSync(resultat, WriteOnError, encoding.UTF_8);
      } catch (writeErr) {
        throw new Error(`Échec écriture fichier : ${writeErr.message}`);
      }
    } catch (err: any) {
      return `${serverUrl}\nErreur: ${err.message}`;
    }
    
  • 校验服务器IP格式:避免构建无效URL:
    const ipRegex = /^(?:(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.){3}(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)$/;
    if (!ipRegex.test(global.serverIP)) {
      return "Adresse serveur invalide";
    }
    

性能优化

  • 异步写入替代同步写入:writeTextSync会阻塞主线程,改用异步的writeText避免UI卡顿:
    await filefevcsv.writeText(resultat, WriteOnError, encoding.UTF_8);
    
  • 利用304缓存响应:配合服务端的缓存头,当服务器返回304时,直接使用本地缓存文件,无需重复下载写入:
    if (response.statusCode === 304) {
      // 直接使用本地已存在的文件,无需处理
      return "";
    }
    // 否则执行下载写入逻辑
    
  • 流式写入优化内存占用:避免将整个文件转为字符串加载到内存,直接将响应内容写入文件(如果NativeScript Http支持):
    await response.content.toFile(path.join(downloadsPath, 'stock.csv'));
    

内容的提问来源于stack exchange,提问作者BenoitB

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.12 10:50:37