vue3 + electron 做图片缓存

// 获取文件名字
export const getFileName = (fileUrl=''):string => {
  let u:any = '';
  if(fileUrl){
    if(url.parse(fileUrl)){
      u = url.parse(fileUrl);
      if(u.pathname){
        u = u.pathname.split('/').pop();
        return u;
      }
    }
  }
  return  '';
};


// 打开本地文件
export const handleOpen = (path) => {
  const p = path;
  return  judgeFileExist(path).then((res)=>{
    if(res){
      shell.openPath(p).catch(err=>{
        shell.showItemInFolder(p);
      });
      return  true;
    }else{
      return false;
    }
  });
};

/**
 * 判断文件是否存在
 * @param fileUrl 文件路径
 * @returns 文件是否存在
 */
export function judgeFileExist(file: string): Promise<boolean> {
  return new Promise((resolve, reject) => {
    fs.access(file, fs.constants.F_OK, (err: any) => {
      if (err) { // 文件存在时err = false;文件不存在时err = true
        resolve(false);
      } else {
        resolve(true);
      }
    });
  });
}
// 获取文件的本地路径
export const getFilePath = (url='',downloadPathCache = false) => {
  let name = '';
  if(downloadPathCache){
    name =  path.resolve(process.cwd() + '/download/Cache/' + url);
  }else{
    const match = url.match(/\/([\w|\.]+$)/);
    name =  path.resolve(process.cwd() + '/download/' + (match ? match[1] : ""));
  }
  return name;

};

export const setPathToLS = (path=''): void => {
  if(!path) return;
  const pathGroup: Array<string> = getItem(TEMP_PATH_NAME_GROUP,false) || [];
  if(pathGroup.indexOf(path) === -1) {
    pathGroup.push(path);
  }
  setItem(TEMP_PATH_NAME_GROUP, pathGroup,false);
};

export const DeletePathToLS = (path=''): void => {
  if(!path) return;
  let pathGroup: Array<string> = getItem(TEMP_PATH_NAME_GROUP,false) || [];
  pathGroup = pathGroup.filter((item) => item !== path);
  setItem(TEMP_PATH_NAME_GROUP, pathGroup,false);
};
export const checkPathInLS = (path='') => {
  if(!path){
    return  false;
  }
  const pathGroup: Array<string> = getItem(TEMP_PATH_NAME_GROUP,false) || [];
  if(pathGroup.length && pathGroup.indexOf(path) > -1) return true;
  retu

以上是对文件操作时需要使用的方法 主要是获取文件的路径 文件名 从下载地址中解析出文件名 再将文件名存到本地存储中 取出时 需要判断文件时候存在 才决定下不下载

import { getFileName, getFilePath, setPathToLS } from './fsMethod';

const path = require('path');
const os = require('os');
const progressStream = require('progress-stream');
const fs = require('fs');
const { dialog } = require('electron');
import fetch from 'node-fetch';
const cwd = process.cwd();

const downloadStatus = [
  {
    status: 0,
    text: '未下载'
  },
  {
    status: 1,
    text: '下载完成'
  },
  {
    status: 2,
    text: '下载失败,请重试'
  },{
    status: 3,
    text: '文件已存在,请勿重复下载'
  },{
    status: 4,
    text: '正在下载'
  }
];

// 下载文件
export const downloadFilesByUrl = ({file_url,id},win)=> {
  try {
    const downloadDicPath = path.resolve(os.homedir(), cwd+ '/Download/');
    if (!fs.existsSync(downloadDicPath)) {
      fs.mkdirSync(downloadDicPath);
    }

    const file_name = getFileName(file_url);
    const file_path = path.resolve(downloadDicPath, file_name);
    const file_path_temp = `${file_path}.tmp`;
    if (!fs.existsSync(file_path)) {
      // Create write stream
      const fileStream = fs.createWriteStream(file_path_temp).on('error', function (e) {
        console.error('error==>', e);
      }).on('ready', function () {
        console.log("start download :", file_url);
      }).on('finish', function () {
        try {
          // Rename the file after the download is complete
          fs.renameSync(file_path_temp, file_path);
          console.log('file download complete :', file_path);
        } catch (err) {
          //
        }
      });
      // request file
      fetch(file_url, {
        method: 'GET',
        headers: { 'Content-Type': 'application/octet-stream' },
      }).then(res => {
        // Get the file size data in the request header
        let fsize = res.headers.get("content-length");
        // Create progress
        let str = progressStream({
          length: fsize,
          time: 100 /* ms */
        });
        // Download progress
        str.on('progress', function (progressData) {
          // output without wrapping
          win.webContents.send('progressData', [{progressData:Math.round(progressData.percentage),id:id,status:downloadStatus[4]}]);
        });
        res.body.pipe(str).pipe(fileStream);
      }).catch(e => {
        // Custom exception handling
        win.webContents.send('progressData', [{progressData:0,id:id,status:downloadStatus[2]}]);
        console.log(e);
      });
    } else {
      // existed
      win.webContents.send('progressData', [{progressData:0,id:id,status:downloadStatus[3]}]);
      console.log(path.resolve(downloadDicPath, file_name), 'already exists, do not download');
    }
  } catch (err) {
    win.webContents.send('progressData', [{progressData:0,id:id,status:downloadStatus[2]}]);
    console.log('Failed to download file, please try again later.', err);
  }
};
export const mkdirsSync = (dirname)=> {
  if (fs.existsSync(dirname)) {
    return true;
  } else {
    if (mkdirsSync(path.dirname(dirname))) {
      fs.mkdirSync(dirname);
      return true;
    }
  }
};

// 保存文件
export const saveFilesByPath = (params) => {
  fs.readFile(params.path,(err,data)=>{
    if(err){
      console.log(err);
      return false;
    }
    dialog.showSaveDialog({
      title: "保存文件",
      defaultPath: params.name,
      properties: ['saveFile'],
      filters: [
        { name: 'All Files', extensions: ['*'] }
      ]
    }).then(async (result) => {
      let  fd = fs.openSync(result.filePath, 'w');
      fs.writeFileSync(fd,data);
      fs.closeSync(fd);
    }).catch(err => {
      console.log(err);
    });
  });
};

// 自动下载文件
export const downloadFilesByUrlCache = (file_url)=> {
  try {
    const downloadDicPath = path.resolve(os.homedir(), cwd+ '/Download/Cache/');
    const downloadPath = path.resolve(os.homedir(), cwd+ '/Download/');
    if (!fs.existsSync(downloadPath)) {
      fs.mkdirSync(downloadPath);
    }
    if (!fs.existsSync(downloadDicPath)) {
      fs.mkdirSync(downloadDicPath);
    }
    const file_name = getFileName(file_url);
    const file_path = path.resolve(downloadDicPath, file_name);
    const file_path_temp = `${file_path}.tmp`;
    if (!fs.existsSync(file_path)) {
      // Create write stream
      const fileStream = fs.createWriteStream(file_path_temp).on('error', function (e) {//
      }).on('ready', function () {
        //
      }).on('finish', function () {
        try {
          // Rename the file after the download is complete
          fs.renameSync(file_path_temp, file_path);
          setPathToLS(getFilePath(file_url,true));
          console.log('file download complete :', file_path);
        } catch (err) {
          console.log('err',err);
        }
      });
      // request file
      fetch(file_url, {
        method: 'GET',
        headers: { 'Content-Type': 'application/octet-stream' },
      }).then(res => {
        // Get the file size data in the request header
        let fsize = res.headers.get("content-length");
        // Create progress
        let str = progressStream({
          length: fsize,
          time: 100 /* ms */
        });
        res.body.pipe(str).pipe(fileStream);
      }).catch(e => {
        console.log(e);
      });
    } else {
      // existed
      // console.log(path.resolve(downloadDicPath, file_name), 'already exists, do not download');
    }
  } catch (err) {
    console.log('Failed to download file, please try again later.', err);
  }
};

以上是下载逻辑  

https://juejin.cn/post/7135640435011092510

这是参考链接

主要使用到了electron的

protocol模块和
session模块
  // 这个需要在app.ready触发之后使用
  protocol.registerFileProtocol('item', (request, callback) => {
    const url = request.url.substr(7);
    console.log('posturl',url,path.normalize(url),decodeURI(path.normalize(url)));
    callback(decodeURI(path.normalize(url)));
  });

  // 这里filter参数是为了筛选过滤哪些url的请求,
  session.defaultSession.webRequest.onCompleted({urls:[]}, (details) => {
    // 这里可以通过details.resourceType判断请求的是否为图片类型,这里也获取了other,是因为视频也会存在在other中
    if ((details.resourceType === 'image' || details.resourceType === 'other')) {
      // 获取请求地址
      if(!checkPathInLS(details.url)){
        downloadFilesByUrlCache(details.url);
      }
    }
  });

上面一个是增加本地文件下载协议 一个是拦截该次回话的所有请求 

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值