WebApi+Python PyQ5实现大文件下载,Ui增加进度条和下载速率+已验证uos和Windows环境

这篇具有很好参考价值的文章主要介绍了WebApi+Python PyQ5实现大文件下载,Ui增加进度条和下载速率+已验证uos和Windows环境。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

Web Api接品代码:

using Microsoft.AspNetCore.Mvc;
using System.Collections.Concurrent;
using System.Net;

namespace LargeFileHandling.Controllers
{
    [ApiController]
    [Route("[controller]")]

    public class TestProgramFileManagerController : Controller
    {
        private readonly string _testProgramPath;

        // 用于存储文件块的信息
        private static ConcurrentDictionary<string, int> fileChunkTracker = new ConcurrentDictionary<string, int>();

        public TestProgramFileManagerController(FileStorageSettings fileStorageSettings)
        {
            _testProgramPath = fileStorageSettings.TestProgramPath;

            //确保上传文件夹存在
            if (!Directory.Exists(_testProgramPath))
            {
                Directory.CreateDirectory(_testProgramPath);//如果不存在则创建
            }
        }

        //上传测试日志
        [HttpPost("uploadTestProgram")]
        /*
         testProgramFile:测试程式文件
         ProgramDriectory:程式存放目录
         */
        public async Task<IActionResult> UploadTestProgram(IFormFile testProgramFile, string programDriectory)
        {
            try
            {
                //判断产品文件夹是否存在
                if (!Directory.Exists($@"{_testProgramPath}\{programDriectory}"))
                {
                    Directory.CreateDirectory($@"{_testProgramPath}\{programDriectory}");//如果不存在则创建
                }

                if (testProgramFile == null || testProgramFile.Length == 0)
                {
                    return BadRequest(new { code = 400, message = "Upload failed. No file provided.", data = new { } });
                }

                var filename = Path.GetFileName(testProgramFile.FileName);
                var filePath = Path.Combine($@"{_testProgramPath}\{programDriectory}", filename);

                await using (var stream = System.IO.File.Create(filePath))
                {
                    await testProgramFile.CopyToAsync(stream);
                }

                return Ok(new { code = 200, message = "test log file uploaded successfully.", data = new { filePath } });
            }
            catch (Exception ex)
            {
                // 增加更详细的错误日志
                Console.WriteLine($"Error: {ex.GetType().FullName}: {ex.Message}");
                Console.WriteLine($"Stack Trace: {ex.StackTrace}");

                // 记录到日志文件或其他监控工具(根据您的日志配置)
                // Logger.LogError(ex, "Error listing files");

                return StatusCode(500, new { code = 500, message = "UploadTestProgram Error.", details = ex.Message });
            }
        }

        // Check if file exists and return JSON response
        /*
         * 查找测试程式文件是否存在
         testProgramFile:测试程式文件
         programDriectory:程式目录
         */
        [HttpGet("exists")]
        public IActionResult CheckProgramFileExists(string testProgramFile, string programDriectory)
        {
            var filePath = Path.Combine($@"{_testProgramPath}\{programDriectory}", testProgramFile);
            if (System.IO.File.Exists(filePath))
            {
                return Ok(new { code = 200, message = "File exists.", data = new { filePath } });
            }
            else
            {
                return NotFound(new { code = 404, message = "File not found.", data = new { } });
            }
        }

        // Actual file download operation
        /*
         下载测试程式
        testProgramFile:程式文件
        programDriectory:程式目录
         */
        [HttpGet("download")]
        public IActionResult DownloadTestProgramFile(string testProgramFile, string programDriectory)
        {
            try
            {
                //var filePath = Path.Combine(_uploadFolderPath, fileName);
                // 解码路径
                string decodedPath = WebUtility.UrlDecode($@"{_testProgramPath}\{programDriectory}\{testProgramFile}");

                if (!System.IO.File.Exists(decodedPath))
                {
                    return NotFound(new { code = 404, message = "File not found.", data = new { } });
                }

                var stream = new FileStream(decodedPath, FileMode.Open, FileAccess.Read);
                return new FileStreamResult(stream, "application/octet-stream")
                {
                    FileDownloadName = testProgramFile
                };
            }
            catch (Exception ex)
            {
                // 增加更详细的错误日志
                Console.WriteLine($"Error: {ex.GetType().FullName}: {ex.Message}");
                Console.WriteLine($"Stack Trace: {ex.StackTrace}");

                // 记录到日志文件或其他监控工具(根据您的日志配置)
                // Logger.LogError(ex, "Error listing files");

                return StatusCode(500, new { code = 500, message = "Internal Server Error.", details = ex.Message });
            }

        }

        /// <summary>
        /// 上传测试程序块
        /// </summary>
        /// <param name="testProgramFile">测试程式文件</param>
        /// <param name="programDriectory">文件上传目录</param>
        /// <param name="fileName">文件名</param>
        /// <param name="chunkIndex">文件对应块指针</param>
        /// <param name="totalChunks">合总块</param>
        /// <returns></returns>
        [HttpPost("uploadtestProgramChunk")]
        public async Task<IActionResult> UploadtestProgramChunk(IFormFile testProgramFile, string programDriectory, string fileName, int chunkIndex, int totalChunks)
        {
            if (testProgramFile == null || testProgramFile.Length == 0)
            {
                return BadRequest(new { code = 400, message = "Upload failed. No chunk provided." });
            }

            string tempFilePath = Path.Combine($@"{_testProgramPath}\{programDriectory}", $"{fileName}.part{chunkIndex}");
            await using (var fileStream = System.IO.File.Create(tempFilePath))
            {
                await testProgramFile.CopyToAsync(fileStream);
            }

            fileChunkTracker.AddOrUpdate(fileName, 1, (key, oldValue) => oldValue + 1);
            if (fileChunkTracker[fileName] == totalChunks)
            {
                bool mergeSuccess = await MergeFileChunks(fileName, totalChunks, programDriectory);
                if (!mergeSuccess)
                {
                    return StatusCode(500, new { code = 500, message = "Error merging file chunks." });
                }

                fileChunkTracker.TryRemove(fileName, out _);
                return Ok(new { code = 200, message = "File uploaded and merged successfully." });
            }

            return Ok(new { code = 200, message = "Chunk uploaded successfully." });
        }

        /// <summary>
        /// 合并文件块
        /// </summary>
        /// <param name="fileName">文件名</param>
        /// <param name="totalChunks">总块数</param>
        /// <param name="programDriectory">程式目录</param>
        /// <returns></returns>
        private async Task<bool> MergeFileChunks(string fileName, int totalChunks, string programDriectory)
        {
            string finalFilePath = Path.Combine($@"{_testProgramPath}\{programDriectory}", fileName);
            try
            {
                // Check if all chunk files exist before starting to merge
                for (int i = 0; i < totalChunks; i++)
                {
                    string tempFilePath = Path.Combine($@"{_testProgramPath}\{programDriectory}", $"{fileName}.part{i}");
                    if (!System.IO.File.Exists(tempFilePath))
                    {
                        Console.WriteLine($"Missing chunk: {tempFilePath}");
                        return false; // If any chunk is missing, abort the merge
                    }
                }

                await using (var finalStream = new FileStream(finalFilePath, FileMode.Create))
                {
                    for (int i = 0; i < totalChunks; i++)
                    {
                        string tempFilePath = Path.Combine($@"{_testProgramPath}\{programDriectory}", $"{fileName}.part{i}");
                        await using (var sourceStream = new FileStream(tempFilePath, FileMode.Open))
                        {
                            await sourceStream.CopyToAsync(finalStream);
                        }
                        System.IO.File.Delete(tempFilePath); // Delete the chunk file after it's been merged
                    }
                }
                return true; // All chunks have been merged successfully
            }
            catch (Exception ex)
            {
                Console.WriteLine($"An error occurred while merging chunks: {ex.Message}");
                return false;
            }
        }

        /// <summary>
        /// 合并单元
        /// </summary>
        /// <param name="fileName">文件名</param>
        /// <param name="totalChunks">总块数</param>
        /// <param name="programDriectory">程式目录</param>
        /// <returns></returns>
        [HttpPost("mergeChunks")]
        public async Task<IActionResult> MergeChunks(string fileName, int totalChunks, string programDriectory)
        {
            bool mergeSuccess = await MergeFileChunks(fileName, totalChunks, programDriectory);
            if (!mergeSuccess)
            {
                return StatusCode(500, new { code = 500, message = "Error merging file chunks." });
            }

            return Ok(new { code = 200, message = "File merged successfully." });
        }

        /// <summary>
        /// 列出下载程式清单
        /// </summary>
        /// <param name="programDriectory">程式目录</param>
        /// <returns></returns>
        [HttpGet("listdownFilePath")]
        public IActionResult ListDownloadableTestProgramFiles(string programDriectory)
        {
            try
            {
                // 解码路径
                string decodedPath = WebUtility.UrlDecode($@"{_testProgramPath}\{programDriectory}");

                if (!Directory.Exists(decodedPath))
                {
                    return new JsonResult(new { code = 404, message = "Upload folder not found." }) { StatusCode = StatusCodes.Status404NotFound };
                }

                var files = Directory.GetFiles(decodedPath, "*.*", SearchOption.AllDirectories)
                                     .Select(file => file.Replace(decodedPath, "").TrimStart(Path.DirectorySeparatorChar))
                                     .ToList();

                return new JsonResult(new { code = 200, message = "File list retrieved successfully.", data = new { files } }) { StatusCode = StatusCodes.Status200OK };
            }
            catch (Exception ex)
            {
                // 增加更详细的错误日志
                Console.WriteLine($"Error: {ex.GetType().FullName}: {ex.Message}");
                Console.WriteLine($"Stack Trace: {ex.StackTrace}");

                // 记录到日志文件或其他监控工具(根据您的日志配置)
                // Logger.LogError(ex, "Error listing files");

                return StatusCode(500, new { code = 500, message = "Internal Server Error.", details = ex.Message });
            }
        }
    }
}

 WebApi+Python PyQ5实现大文件下载,Ui增加进度条和下载速率+已验证uos和Windows环境,ui,python,xhtml

import configparser
import logging
import sys
import time  # 修改这里
#import time as time_module  # 修改这里,避免命名冲突
import requests
from PyQt5.QtWidgets import QApplication, QWidget, QVBoxLayout, QPushButton, QProgressBar, QLabel, QDesktopWidget, \
    QMessageBox
from PyQt5.QtCore import QThread, pyqtSignal, Qt, QPoint
import os
import platform
import subprocess


class DownloadThread(QThread):
    progress_updated = pyqtSignal(int)
    speed_updated = pyqtSignal(str)
    download_completed = pyqtSignal()  # 新信号,表示下载完成
    current_file = pyqtSignal(str)  # 新增信号,传递当前下载文件的名称
    # 其他信号保持不变
    error_occurred = pyqtSignal()  # 新增信号,表示发生了错误

    def __init__(self, url, params_list, save_path_prefix):
        super().__init__()
        self.url = url
        self.params_list = params_list  # 现在是参数列表,每个元素是一个文件的参数

        self.save_path_prefix = save_path_prefix.replace("\\", "/")  # 确保使用正斜杠

    #执行
    def run(self):
        for params in self.params_list:
            # 用于Windows路径和兼容UNIX-like系统的路径处理
            file_path = params['testProgramFile'].replace("\\", "/")
            self.current_file.emit(file_path)  # 发出当前下载文件的名称
            # 检查文件路径中是否包含目录
            if "/" in file_path:
                # 存在目录,创建目录结构
                full_path = os.path.join(self.save_path_prefix, file_path)
                directory = os.path.dirname(full_path)
                if not os.path.exists(directory):
                    os.makedirs(directory, exist_ok=True)
            else:
                # 文件不包含目录,直接保存到根目录下
                full_path = os.path.join(self.save_path_prefix, file_path)

            try:
                with requests.get(self.url, params=params, stream=True) as r:
                    r.raise_for_status()
                    total_length = int(r.headers.get('content-length', 0))
                    download_length = 0
                    start_time = time.time()
                    with open(full_path, 'wb') as f:
                        for chunk in r.iter_content(chunk_size=1024):
                            if chunk:
                                f.write(chunk)
                                download_length += len(chunk)
                                if total_length > 0:
                                    progress = int(100 * download_length / total_length)
                                    self.progress_updated.emit(progress)  # 发出进度更新信号

                                elapsed_time = time.time() - start_time
                                if elapsed_time > 0:
                                    speed = download_length / elapsed_time
                                    self.speed_updated.emit(f"{speed / 1024:.2f} KB/s")  # 发出速度更新信号
            except Exception as e:
                print(f"下载{file_path}失败: {e}")
                self.error_occurred.emit()

        self.download_completed.emit()

        # 检查操作系统,如果不是Windows,则执行chmod命令
        print(platform.system())
        if platform.system() != "Windows":
            try:
                # 构建命令字符串
                cmd = f"chmod 777 {self.save_path_prefix} -R"
                subprocess.run(cmd, shell=True, check=True)
            except subprocess.CalledProcessError as e:
                print(f"修改权限失败: {e}")

    # def run(self):
    #     try:
    #         for params in self.params_list:
    #             file_name = params['testProgramFile']
    #             self.current_file.emit(file_name)  # 发出当前文件名信号
    #             save_path = f"{self.save_path_prefix}{file_name}"
    #             try:
    #                 with requests.get(self.url, params=params, stream=True) as r:
    #                     r.raise_for_status()  # 确保请求成功
    #                     total_length = int(r.headers.get('content-length'))
    #                     download_length = 0
    #                     start_time = time.time()
    #                     with open(save_path, 'wb') as f:
    #                         for chunk in r.iter_content(chunk_size=1024):
    #                             if chunk:
    #                                 f.write(chunk)
    #                                 download_length += len(chunk)
    #                                 progress = int(100 * download_length / total_length)
    #                                 self.progress_updated.emit(progress)
    #
    #                                 elapsed_time = time.time() - start_time
    #                                 if elapsed_time > 0:
    #                                     speed = download_length / elapsed_time
    #                                     self.speed_updated.emit(f"{speed / 1024:.2f} KB/s")
    #             except Exception as e:
    #                 print(f"下载{file_name}失败: {e}")
    #
    #         self.download_completed.emit()  # 下载完成后发出信号
    #
    #     except Exception as e:
    #         print(f"下载过程中发生错误: {e}")
    #         self.error_occurred.emit()


class MainWindow(QWidget):
    # 定义颜色代码
    COLOR_SUCCESS = "\033[1;32;43m"
    COLOR_ERROR = "\033[1;31m"
    COLOR_RESET = "\033[0m"

    def __init__(self):
        super().__init__()
        self.initUI()
        self.start_download()  # 添加这行代码来在窗口初始化后自动开始下载
        self.config = configparser.ConfigParser()

        # 生成日志信息
        self.logger = logging.getLogger('my_logger')  # 步骤1 创建日志记录器
        self.logger.setLevel(logging.DEBUG)  # 步骤2 将指定日志级别
        self.file_handler = logging.FileHandler('log/log.txt')  # 步骤3 创建文件处理器
        self.formatter = logging.Formatter('%(asctime)s - %(levelname)s - %(message)s')  # 步骤4 创建格式化器
        self.file_handler.setFormatter(self.formatter)  # 步骤4 将格式化器添加到处理器
        self.logger.addHandler(self.file_handler)  # 步骤5 将处理器添加到日志记录器

        # 读取配置
        self.config.read('./Conf/config.conf', encoding='utf-8')  # 读取配置文件,如果配置文件不存在则创建

        # 读取Test_WebApi接口配置
        self.TestWebApi = self.config.get('TestWepApi', 'url')


    def initUI(self):
        self.setWindowTitle('File Downloader')
        self.setGeometry(100, 100, 400, 200)
        self.setWindowFlags(Qt.FramelessWindowHint)  # 设置为无边框窗口

        self.layout = QVBoxLayout()

        self.progress_bar = QProgressBar(self)
        self.speed_label = QLabel('Speed: 0 KB/s', self)
        self.current_file_label = QLabel('Current File: None', self)  # 新增标签
        #self.download_button = QPushButton('Download', self)
        #self.download_button.clicked.connect(self.start_download)

        self.layout.addWidget(self.progress_bar)
        self.layout.addWidget(self.speed_label)
        self.layout.addWidget(self.current_file_label)  # 将新标签添加到布局
        #self.layout.addWidget(self.download_button)

        self.setLayout(self.layout)
        self.centerWindow()#窗体居中显示

        self.oldPos = self.pos()

    def mousePressEvent(self, event):
        self.oldPos = event.globalPos()

    def mouseMoveEvent(self, event):
        delta = QPoint(event.globalPos() - self.oldPos)
        self.move(self.x() + delta.x(), self.y() + delta.y())
        self.oldPos = event.globalPos()

    #获取文件列表
    def get_file_list(self):
        url = f'{self.TestWebApi}/TestProgramFileManager/listdownFilePath'
        params = {'programDriectory': 'Online_UpdateProgram\\X86_UOS'}
        try:
            response = requests.get(url, params=params)
            response.raise_for_status()  # 这将抛出异常,如果请求返回了一个错误
            file_list = response.json().get('data', {}).get('files', [])
            return file_list
        except requests.RequestException as e:
            #print(f"获取文件列表失败: {e}")
            self.ShowLog(f"获取文件列表失败: {e}",False)
            return []

    #执行文件下载
    # MainWindow中start_download方法的修改
    def start_download(self):
        try:
            file_list = self.get_file_list()
            if not file_list:
                #print("文件列表为空,无法下载")
                self.ShowLog("文件列表为空,无法下载",False)
                return

            params_list = [{'testProgramFile': file_name, 'programDriectory': 'Online_UpdateProgram\\X86_UOS'} for
                           file_name in file_list]
            self.download_thread = DownloadThread(f'{self.TestWebApi}/TestProgramFileManager/download',
                                                  params_list, "")
            self.download_thread.progress_updated.connect(self.progress_bar.setValue)
            self.download_thread.speed_updated.connect(self.speed_label.setText)
            self.download_thread.current_file.connect(self.current_file_label.setText)  # 连接新信号
            self.download_thread.start()

            # 获取文件列表和初始化下载线程的代码保持不变
            self.download_thread.download_completed.connect(self.on_download_completed)
            self.download_thread.error_occurred.connect(self.on_error_occurred)
        except Exception as e:
            self.ShowLog(f"下载失败: {e}",False)
            #print(f"下载失败: {e}")

    #显示当前下载的文件
    def update_current_file_label(self, file_name):
        # 设置标签的文本
        self.current_file_label.setText(f"Current File: {file_name}")
        # 设置工具提示以显示完整的文件名
        self.current_file_label.setToolTip(file_name)

    #窗体居中显示
    def centerWindow(self):
        screen = QDesktopWidget().screenGeometry()  # 获取屏幕尺寸
        # 设置窗口宽度为屏幕宽度的1/3,高度为屏幕高度的1/12
        width = screen.width() * 2 / 3
        height = screen.height() * 1 / 15
        self.setFixedSize(width, height)  # 设置固定大小

        qr = self.frameGeometry()  # 获取主窗口的矩形框架
        cp = screen.center()  # 获取显示屏幕的中心点
        qr.moveCenter(cp)  # 将窗口框架的中心点移动到屏幕的中心位置
        self.move(qr.topLeft())  # 将窗口的左上角移动到矩形框架的左上角,实际上就是将窗口居中

        qr = self.frameGeometry()  # 获取主窗口的矩形框架
        cp = QDesktopWidget().availableGeometry().center()  # 获取显示屏幕的中心点
        qr.moveCenter(cp)  # 将窗口框架的中心点移动到屏幕的中心位置
        self.move(qr.topLeft())  # 将窗口的左上角移动到矩形框架的左上角,实际上就是将窗口居中

    def on_download_completed(self):
        QApplication.exit(0)  # 下载完成后正常退出

    def on_error_occurred(self):
        QApplication.exit(1)  # 发生错误时退出并返回1

    # 日志
    def ShowLog(self, log, is_success):
        try:
            if is_success:
                color = self.COLOR_SUCCESS
                self.logger.info(log)
            else:
                color = self.COLOR_ERROR
                self.logger.error(log)
                # QMessageBox.critical(self, '系统提醒', f"{log}", QMessageBox.Yes, QMessageBox.Yes)
            print(f"{color}{log}{self.COLOR_RESET}")
        except Exception as e:
            QMessageBox.critical(self, '系统提醒', f"{log}", QMessageBox.Yes, QMessageBox.Yes)
            print(f"{self.COLOR_ERROR}{e}{self.COLOR_RESET}")
            sys.exit(1)

if __name__ == '__main__':
    app = QApplication(sys.argv)
    ex = MainWindow()
    ex.show()
    sys.exit(app.exec_())

WebApi+Python PyQ5实现大文件下载,Ui增加进度条和下载速率+已验证uos和Windows环境,ui,python,xhtml文章来源地址https://www.toymoban.com/news/detail-847513.html

到了这里,关于WebApi+Python PyQ5实现大文件下载,Ui增加进度条和下载速率+已验证uos和Windows环境的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • python flask创建服务器实现文件的上传下载,已获千赞

    } 二、后端代码(python) import os from string import Template from flask import Flask, send_file,request,jsonify from flask_cors import CORS import time app = Flask( name ) absolute = os.path.dirname( file ) CORS(app) app.debug = True FOLDER = os.path.join(absolute, ‘save_file’) HOST = “localhost” PORT = 8080 UPLOAD = ‘upload’ app.config

    2024年04月22日
    浏览(48)
  • Python实现将pdf,docx,xls,doc,wps链接下载并将文件保存到本地

    前言 本文是该专栏的第31篇,后面会持续分享python的各种干货知识,值得关注。 在工作上,尤其是在处理爬虫项目中,会遇到这样的需求。访问某个网页或者在采集某个页面的时候,正文部分含有docx,或pdf,或xls,或doc,或wps,或ofd,或xlsx,或zip等链接。需要你使用python自

    2024年02月16日
    浏览(56)
  • element-ui文件上传下载组件+后台对应接口

    element-ui文件上传下载组件: 具备上传、下载和删除功能。 不自动上传,附件选择后只将文件加入待上传列表,点击确认上传按钮后上传到后台服务器,已上传的文件通过表格的形式展示在上方表格中。 删除和上传权限可配置。 效果如下: 代码如下: 后端:

    2024年02月12日
    浏览(43)
  • python怎么下载视频文件,怎么用python下载文件

    大家好,本文将围绕python怎么下载安装视频教学展开说明,python怎么下载视频文件是一个很多人都想弄明白的事情,想搞清楚怎么用python下载文件需要先了解以下几个事情。 原标题:运用Python爬虫下载电影、电视剧、动漫 前言: 本程序代码仅供学习,切莫用于商业活动,一

    2024年04月28日
    浏览(40)
  • Python实现将pdf,docx,xls,doc,wps,zip,xlsx,ofd链接下载并将文件保存到本地

    前言 本文是该专栏的第31篇,后面会持续分享python的各种干货知识,值得关注。 在工作上,尤其是在处理爬虫项目中,会遇到这样的需求。访问某个网页或者在采集某个页面的时候,正文部分含有docx,或pdf,或xls,或doc,或wps,或ofd,或xlsx,或zip等链接。需要你使用python自

    2024年02月17日
    浏览(65)
  • 使用element-ui的el-upload进行excel文件上传与下载

    需求:前端上传文件后,后端接受文件进行处理后直接返回处理后的文件,前端直接再将文件下载下来。 通常我们都是直接使用el-upload的action属性来直接完成文件上传的操作,如果要进行后续文件的直接下载,可以在on-success中用代码进行操作,若存在401权限问题也可以直接

    2024年02月11日
    浏览(45)
  • 【Java 实现文件下载】vue前端+java后端实现文件下载详解(附源码)

    【 写在前面 】前端时间总结了一下有关java文件上传的功能,也给不少读者带来一些帮助,因此今天继续完善文件下载这套体系,希望能给屏幕前的您带来实质性的帮助,其实文件下载最怕的就是中文乱码的现象,当然这个我单独写了一篇文章解释,这里不做详谈。 涉及知识

    2024年02月09日
    浏览(56)
  • 前端实现文件下载功能——文件流

    前端下载文件一般使用的是blob 核心的步骤是获取后端响应的文件流,用blob创建一个临时的URL,然后创建一个隐藏的a标签,实现下载需求。 那就先上代码 如果后端响应的数据是一个二进制数据,那我们就得这是响应类型是blob,否则浏览器会默认按照json解析 至于后端如何向

    2024年02月11日
    浏览(52)
  • 【Java实战】Feign调用文件下载服务接口实现文件下载功能

    最近需要实现Feign调用服务提供者的文件下载接口,进行文件下载功能,这里对功能的实现做一个简单的记录 通过调用服务提供者的文件下载接口,将文件传输的流数据通过 feign.Response 来接收,服务消费者再将数据转化 首先,在项目中引入Feign的依赖。你可以使用Maven进行管

    2024年02月12日
    浏览(80)
  • 通过 Blob 对二进制流文件下载实现文件保存下载

    原理 : 前端将二进制文件做转换 实现下载:请求后端接口-接收后端返回的二进制流(通过二进制流( Blob )下载, 把后端返回的二进制文件放在 Blob 里面)-再通过 file-saver 插件保存 需求背景 业务:下载模板文件 页面上使用: 保存文件: 发起请求通用方法(更改 axios 的 re

    2024年02月09日
    浏览(71)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包