Python集成C#实现界面操作下载文件功能的全过程

目录
  • 〇、写在前面
  • 一、这个功能是怎么样的
  • 二、WinForm 端功能实现
    • 1. 界面设计
  • 2. 方法定义
  • 三、Python 端功能实现
  • 四、运行效果
  • 五、存在问题
  • 总结

〇、写在前面

你想的没错,Python 和 C# 其实都可以单独实现我们要实现的功能,这里笔者只是抱着实验及学习的态度去解决问题。

我是一个 C# 程序员,目前在学习 Python,对于 Python 得天独厚的胶水语言特性自然是必须要领略一番,于是就有了本文。

学会了 Python 调用 C# 的话,就能做很多想到和想不到的东西,这很有趣,不是吗?

一、这个功能是怎么样的

我很熟悉用 C# & WinForm 的方式开发界面,现在刚好学习了 Python 的网络编程的基础库 socket,于是我就想到写一个程序,思路如下:

  • 程序运行时会打开一个 WinForm 窗体,窗体上有:

    • 输入文件下载地址的地址栏
    • 选择文件保存位置的文件开窗按钮
    • 当前下载状态的状态区域
    • 下载按钮
  • 输入下载地址,选择一个文件保存位置
  • 点击下载按钮下载文件,状态区域显示文件下载状态,最好能显示下载进度
  • 界面放到 WinForm,下载功能放到 Python

二、WinForm 端功能实现

WinForm 分为几部分功能

  • 界面设计
  • 提供下载地址的公共属性
  • 提供文件存储地址公共属性
  • 提供用于委托下载事件的委托定义
  • 提供记录状态信息的公共方法
  • 提供更新进度信息的公共方法

1. 界面设计

首先我们使用 VS 创建一个类库项目

至于为什么没有使用 .NET 5 或者 .net core,是因为:Python 调用 C# 动态链接库

创建项目后新建窗体

本例中设计界面设计如下:

2. 方法定义

/// <summary>
/// 当前地址
/// </summary>
public string ThisUrl
{
    get
    {
        return textUrl.Text;
    }
}

/// <summary>
/// 当前保存路径
/// </summary>
public string ThisSavePath
{
    get
    {
        return textSavePath.Text;
    }
}
/// <summary>
/// 下载事件委托
/// </summary>
public event EventHandler DownloadEvent;

/// <summary>
/// 下载按钮事件
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void buttonDownload_Click(object sender, EventArgs e)
{
    if (string.IsNullOrEmpty(this.textUrl.Text))
    {
        MessageBox.Show("请先输入要下载的文件地址!");
        this.textUrl.Focus();
        return;
    }
    if (string.IsNullOrEmpty(this.textSavePath.Text))
    {
        MessageBox.Show("请先选择文件要保存的地址!");
        this.textSavePath.Focus();
        return;
    }

    // 调用委托事件
    if(this.DownloadEvent != null)
    {
        this.DownloadEvent.Invoke(this, e);
    }
}

打开选择保存文件路径时候由于会报错

在可以调用OLE之前,必须将当前线程设置为单线程单元(STA)模式,请确保您的Main函数带有STAThreadAttribute标记

很无奈,因为我们的调用方并不是 C# 的 Main 函数,而我目前并不知道 Python 调用 C# 如何实现的,所以只能另外想方法,就是把选择保存文件路径的开窗单独启一个线程开发,在子线程上再标记 STA

/// 选择按钮事件
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void buttonSelect_Click(object sender, EventArgs e)
{
    if (string.IsNullOrEmpty(this.textUrl.Text))
    {
        MessageBox.Show("请先输入要下载的文件地址!");
        this.textUrl.Focus();
        return;
    }

    var index = this.textUrl.Text.LastIndexOf("/");
    var fileName = this.textUrl.Text.Substring(index + 1);

    Thread importThread = new Thread(() => {
        var text = OpenDialog(fileName);
        MessageEvent(text);
    });
    importThread.SetApartmentState(ApartmentState.STA); //重点
    importThread.Start();
}

/// <summary>
/// 打开对话框
/// </summary>
private string OpenDialog(string fileName)
{
    var saveFileDialog = new SaveFileDialog();
    saveFileDialog.Filter = "所有文件 (*.*)|*.*";
    saveFileDialog.FilterIndex = 0;

    if (!string.IsNullOrEmpty(fileName))
    {
        saveFileDialog.FileName = Path.Combine(saveFileDialog.FileName, fileName);
    }

    DialogResult dialogResult = saveFileDialog.ShowDialog();
    if (dialogResult == DialogResult.OK)
    {
        return saveFileDialog.FileName;
    }
    return String.Empty;
}

三、Python 端功能实现

Python 中分几部分功能

  • 程序调用 .NET 类库打开窗体
  • 程序中存在下载指定 URL 文件存储到指定路径的函数定义
  • 程序结束的函数定义
  • 把当前程序封装成可运行程序(如:Windows 中为封装成 exe)
import socket
import time
import re

mainapp = None

# 调用动态链接库的更新状态信息
def LogInfo(text):
    # print(text)
    mainapp.LogInfo(text)

# 调用动态链接库的更新下载进度
def downloadInfo(c, all):
    mainapp.SetProcess(c, all)
    if c == all:
        # LogInfo("下载进度 {:.2f}".format(c / all * 100))
        LogInfo("下载完成。")
    # else:
        # LogInfo("下载进度 {:.2f}%".format(c / all * 100))

# 监听下载委托事件
def Download(source, args):
    thisurl = source.ThisUrl.lower()
    thispath = source.ThisSavePath
    LogInfo("下载地址是: {}".format(thisurl))
    LogInfo("保存路径为: {}".format(thispath))

    reobj = re.compile(r"""(?xi)\A
    [a-z][a-z0-9+\-.]*://                                # Scheme
    ([a-z0-9\-._~%!$&'()*+,;=]+@)?                       # User
    ([a-z0-9\-._~%]+                                     # Named or IPv4 host
    |\[[a-z0-9\-._~%!$&'()*+,;=:]+\])                    # IPv6+ host
    """)
    match = reobj.search(thisurl)
    if match:
        HOST = match.group(2)
        PORT = 443 if thisurl.startswith('https') else 80
        mysock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
        mysock.connect((HOST, PORT))

        urlend = 'GET {} HTTP/1.0\r\n\r\n'.format(thisurl).encode()
        # LogInfo("传递参数: {}".format(urlend))
        LogInfo("开始下载……")
        mysock.sendall(urlend)
        count = 0

        picture = b""
        hearlength = 0
        filelength = 0
        hearc = b""
        while True:
            data = mysock.recv(5120)
            if (len(data) < 1): break
            time.sleep(0.1)
            count = count + len(data)
            picture = picture + data

            # print(len(data), count)
            if hearlength == 0:
                hearlength = picture.find(b"\r\n\r\n")
                if hearlength > 0:
                    hearc = picture[:hearlength].decode()
                    # print(hearc)
                    sear = re.search('Content-Length: ([0-9]+)', hearc)
                    if sear:
                        filelength = int(sear.groups()[0])
                        downloadInfo(count - 4 - hearlength, filelength)
            else:
                downloadInfo(count - 4 - hearlength, filelength)
        mysock.close()

        # Skip past the header and save the picture data
        picture = picture[hearlength+4:]
        fhand = open(thispath, "wb")
        fhand.write(picture)
        fhand.close()

        # Code: http://www.py4e.com/code3/urljpeg.py
        # Or select Download from this trinket's left-hand menu
    else:
        LogInfo('下载失败,地址格式存在问题!')

# 使用 pythonnet 的方式引入动态链接库

import clr

# 此处保证动态链接库文件放在当前文件夹中,如果不在应该使用这种方式
# clr.AddReference('D:\\Path\\DotNetWithPython')
# clr.AddReference('D:\\Path\\DotNetWithPython.dll')
clr.AddReference('DotNetWithPython')
from DotNetWithPython import *
mainapp = MainForm()
mainapp.DownloadEvent += Download
mainapp.ShowDialog()

四、运行效果

五、存在问题

功能实现了,但是存在一个无法解决的问题,就是当文件开始下载后 WinForm 的界面会卡住,疑似是没有用现线程打开主窗体的原因,但是不能解释为什么下载开始的时候没有卡顿,有哪位大白指导一下呢?不胜感激!

总结

到此这篇关于Python集成C#实现界面操作下载文件功能的文章就介绍到这了,更多相关Python界面操作下载文件内容请搜索我们以前的文章或继续浏览下面的相关文章希望大家以后多多支持我们!

(0)

相关推荐

  • python实现上传下载文件功能

    最近刚学python,遇到上传下载文件功能需求,记录下! django web项目,前端上传控件用的是uploadify. 文件上传 - 后台view 的 Python代码如下: @csrf_exempt @require_http_methods(["POST"]) def uploadFiles(request): try: user = request.session.get('user') allFimeNames = "" #获取所有上传文件 files

  • python实现下载文件的三种方法

    Python开发中时长遇到要下载文件的情况,最常用的方法就是通过Http利用urllib或者urllib2模块. 当然你也可以利用ftplib从ftp站点下载文件.此外Python还提供了另外一种方法requests. 下面来看看三种方法是如何来下载zip文件的: 方法一: import urllib import urllib2 import requests print "downloading with urllib" url = 'http://www.jb51.net//te

  • Python实现批量下载文件

    Python实现批量下载文件 #!/usr/bin/env python # -*- coding:utf-8 -*- from gevent import monkey monkey.patch_all() from gevent.pool import Pool import requests import sys import os def download(url): chrome = 'Mozilla/5.0 (X11; Linux i86_64) AppleWebKit/537.36

  • 详解使用Python下载文件的几种方法

    在使用Python进行数据抓取的时候,有时候需要保持文件或图片等,在Python中可以有多种方式实现.今天就一起来学习下. urllib.request 主要使用的是urlretrieve方法,该方法处理待淘汰的方法,不建议使用. import urllib.request url = 'https://www.baidu.com/img/superlogo_c4d7df0a003d3db9b65e9ef0fe6da1ec.png' urllib.request.urlretrieve(url,

  • python 下载文件的几种方法汇总

    前言 使用脚本进行下载的需求很常见,可以是常规文件.web页面.Amazon S3和其他资源.Python 提供了很多模块从 web 下载文件.下面介绍 一.使用 requests requests 模块是模仿网页请求的形式从一个URL下载文件 示例代码: import requests url = 'xxxxxxxx' # 目标下载链接 r = requests.get(url) # 发送请求 # 保存 with open ('r.txt', 'rb') as f: f.write(r.con

  • python下载文件时显示下载进度的方法

    本文实例讲述了python下载文件时显示下载进度的方法.分享给大家供大家参考.具体分析如下: 将这段代码放入你的脚本中,类似:urllib.urlretrieve(getFile, saveFile, reporthook=report) 第三个参数如下面的函数定义report,urlretrieve下载文件时会实时回调report函数,显示下载进度 def report(count, blockSize, totalSize): percent = int(count*blockSize*10

  • Python集成C#实现界面操作下载文件功能的全过程

    目录 〇.写在前面 一.这个功能是怎么样的 二.WinForm 端功能实现 1. 界面设计 2. 方法定义 三.Python 端功能实现 四.运行效果 五.存在问题 总结 〇.写在前面 你想的没错,Python 和 C# 其实都可以单独实现我们要实现的功能,这里笔者只是抱着实验及学习的态度去解决问题. 我是一个 C# 程序员,目前在学习 Python,对于 Python 得天独厚的胶水语言特性自然是必须要领略一番,于是就有了本文. 学会了 Python 调用 C# 的话,就能做很多想到和想不到的

  • python制作可视化GUI界面自动分类管理文件

    目录 不同的文件后缀归类为不同的类别 output 效果图 经常杂乱无章的文件夹会让我们找不到所想要的文件,因此我特意制作了一个​​可视化GUI界面​​,通过输入路径一键点击实现文件分门别类的归档. 不同的文件后缀归类为不同的类别 我们先罗列一下大致有几类文件,根据文件的后缀来设定,大致如下 SUBDIR = { "DOCUMENTS": [".pdf", ".docx", ".txt", ".html"]

  • python爬虫智能翻页批量下载文件的实例详解

    python爬虫遇到爬取文件内容时,需要一页页的翻页爬取,这样很是麻烦,其实可以获取每个列表信息下的文件名和文件链接,让文件名和文件链接处理为列表,保存后下载,实现智能翻页批量下载文件,本文以以京客隆为例,批量下载文件,如财务资料,他的每一份报告都是一份pdf格式的文档.以此页面为目标,下载他每个分类的文件python爬虫实战之智能翻页批量下载文件. 1.引入库 import requests import pandas as pd from lxml import etree import r

  • python实现的爬取电影下载链接功能示例

    本文实例讲述了python实现的爬取电影下载链接功能.分享给大家供大家参考,具体如下: #!/usr/bin/python #coding=UTF-8 import sys import urllib2 import os import chardet from bs4 import BeautifulSoup reload(sys) sys.setdefaultencoding("utf-8") #从电影html页面中获取视频下载地址 def get_movie_download_u

  • Python实现的根据文件名查找数据文件功能示例

    本文实例讲述了Python实现的根据文件名查找数据文件功能.分享给大家供大家参考,具体如下: #-*- coding: UTF-8 -*- import os import shutil AllFiles=[] NameFiles=[] def findFie(filePath): pathDir = os.listdir(filePath) for allDir in pathDir: # print(allDir) AllFiles.append(allDir) #pass #filepat

  • PHP使用CURL实现下载文件功能示例

    本文实例讲述了PHP使用CURL实现下载文件功能.分享给大家供大家参考,具体如下: 如果使用CURL下载从微信手机端上传的图片?参考下面代码 /** * CURL下载文件 成功返回文件名,失败返回false * @param $url * @param string $savePath * @return bool|string * @author Zou Yiliang */ public function downFile($url, $savePath = './uploads') { /

  • php+js实现的无刷新下载文件功能示例

    本文实例讲述了php+js实现的无刷新下载文件功能.分享给大家供大家参考,具体如下: 服务器端页面 步骤就是,设置头文件参数,然后读入并输出文件.下面代码的file_get_contents可以使用fread,fclose代替. download.php <?php $filename = $_GET['filename']; $path = __DIR__."/file/".$filename; Header( "Content-type: application/o

  • JavaScript 用fetch 实现异步下载文件功能

    废话不多说了,直接给大家贴代码了,具体代码如下所示: <!DOCTYPE html> <html> <head> <meta charset="utf-8"> <title>sample</title> </head> <body> <button id='btn'>下载</button> <span id='status'></span> &

  • Android实现下载文件功能的方法

    本文所述为Android实现下载文件功能的完整示例代码,对于学习和研究android编程相信会有一定的帮助,尤其是对Android初学者有一定的借鉴价值. 完整功能代码如下: package com.test; import java.io.File; import java.io.FileOutputStream; import java.io.InputStream; import java.net.URL; import java.net.URLConnection; import and

  • shell脚本实现ftp上传下载文件功能

    前段时间工作中需要将经过我司平台某些信息核验数据提取后上传到客户的FTP服务器上,以便于他们进行相关的信息比对核验.由于包含这些信息的主机只有4台,采取的策略是将生成的4个文件汇集到一个主机上,然后在这台主机上将文件上传的目标ftp服务器. 1,建立主机A到其他三台主机之间的信任关系,以便于远程拷贝文件 #生成主机A的本地认证秘钥,可以选择生成rsa或者dsa类型的秘钥,这里选取rsa [root@A ~]#ssh-keygen -t rsa -P '' -f ~/.ssh/id_rsa >/d

随机推荐