【问题标题】:upload files through http post in Pyside/PyQt在 Pyside/PyQt 中通过 http post 上传文件
【发布时间】:2014-01-16 09:37:39
【问题描述】:

我正在尝试将文件和其他 POST 变量发送到我客户服务器上的 xfilesharing 脚本(在 perl 中)。

Google 上没有好的资源,我发现的代码示例不起作用。(实际上它们是用 c++ 编写的,我无法让它们工作)

服务器正在使用 Apache 作为网络服务器

我之前问了一个问题,我得到了一个很好的答案,所以我在这里使用uploader,代码不能通过http post上传文件

所以任何人都可以首先告诉我我需要做什么才能通过 HTTP 发布上传文件,然后如果你能给我一个示例,那就太好了(在 localhost 上上传的简单代码就足够了,我只是想要看看如何做到这一点以及上传是如何工作的)

【问题讨论】:

  • 您是否有理由不在 Python 标准库中使用类似 urllib2 的东西?只是好奇使用 qt 库发送 POST 请求有什么好处。
  • 是的,实际上它是一个将文件上传到 xfilesharing 脚本的 GUI 软件,对于 GUI,我需要 Qt,而且我不知道如何将 urllib2 与 Qt 集成 :( ,仍然有很多问题发布文件,你有更好的主意吗?
  • 嗯,我不明白为什么您不能只使用 Qt 小部件获取要发送的信息,并使用 urllib2 来实际执行 POST 请求。例如,您可以使用 QFileDialog 获取要上传的文件路径,然后关注其他有关使用 urllib2 的 stackoverflow 帖子(例如 stackoverflow.com/questions/4496691/… )。仅仅因为您将 Qt 用于您的 GUI,并不意味着您不能从代码中调用其他 -GUI 库。
  • 这是个好主意,我不知道(对不起,我是新人)。如果只是 urllib2 为我做一件事:我使用 QtNetwork 的主要原因是我需要并行上传,我可以使用(不知何故)urllib2 在 PyQt 中进行并行上传吗?(要求只是为了确定)如果可以的话我会切换到 urllib2
  • 啊,是的,urllib2 不是线程安全的,所以并行上传已经结束。幸运的是,一个快速的谷歌搜索返回项目 urllib3(不包括 Python 的标准,但您可以通过从命令行运行 pip install urllib3easy_install urllib3 非常简单地安装它)。 urllib3 表示它是线程安全的,并为上传文件提供了更好的支持。看看:github.com/shazow/urllib3

标签: python qt http pyqt pyside


【解决方案1】:

这个问题看起来非常困难。这个话题确实没有完整的例子。

PyQt

在 PyQt4 中,我设法运行了QHttpMultiPart documentation 中提供的示例。适配的 Python 版本(需要 Qt 4.8):

from PyQt4 import QtGui, QtCore, QtNetwork
import sys
import time

def finished(reply):
  print "Finished: ", reply.readAll()
  app.quit()

def construct_multipart(data, files):
  multiPart = QtNetwork.QHttpMultiPart(QtNetwork.QHttpMultiPart.FormDataType)
  for key, value in data.items():
    textPart = QtNetwork.QHttpPart()
    textPart.setHeader(QtNetwork.QNetworkRequest.ContentDispositionHeader,
      "form-data; name=\"%s\"" % key)
    textPart.setBody(value)
    multiPart.append(textPart)

  for key, file in files.items():
    imagePart = QtNetwork.QHttpPart()
    #imagePart.setHeader(QNetworkRequest::ContentTypeHeader, ...);
    fileName = QtCore.QFileInfo(file.fileName()).fileName()
    imagePart.setHeader(QtNetwork.QNetworkRequest.ContentDispositionHeader,
      "form-data; name=\"%s\"; filename=\"%s\"" % (key, fileName))
    imagePart.setBodyDevice(file);
    multiPart.append(imagePart)
  return multiPart

app = QtGui.QApplication(sys.argv)
file1 = QtCore.QFile('/tmp/1.txt')
file1.open(QtCore.QFile.ReadOnly)
url = QtCore.QUrl('http://localhost:3000/qwertytest1');
data = { 'text1': 'test1', 'text2': 'test2' }
files = {'file1': file1 }
multipart = construct_multipart(data, files)
request_qt = QtNetwork.QNetworkRequest(url)
request_qt.setHeader(QtNetwork.QNetworkRequest.ContentTypeHeader,
  'multipart/form-data; boundary=%s' % multipart.boundary())
manager = QtNetwork.QNetworkAccessManager()
manager.finished.connect(finished)
request = manager.post(request_qt, multipart)

sys.exit(app.exec_())

PySide

PySide 实现缺少QHttpMultiPart。唯一的方法是手动构建发布数据内容。幸运的是,Python 有自己的库来创建多部分 HTTP 请求。这是我写的:

import sys
from PySide import QtCore, QtGui, QtNetwork
import requests

def finished(reply):
  print "Finished: ", reply.readAll()
  app.quit()

app = QtGui.QApplication(sys.argv)
url = 'http://localhost:3000/qwertytest1'
data = { 'text1': 'test1', 'text2': 'test2' }
files = {'file1': open('/tmp/1.txt') }
request = requests.Request('POST', url, data=data, files=files).prepare()
request_qt = QtNetwork.QNetworkRequest(url)
for header, value in request.headers.items():
  request_qt.setRawHeader(header, value)
manager = QtNetwork.QNetworkAccessManager()
manager.finished.connect(finished)
request = manager.post(request_qt, request.body)

sys.exit(app.exec_())

请注意,此方法会加载内存中的所有文件内容。如果您正在处理大文件,这是不可接受的。 python-requests 模块本身支持动态发送大文件,但是没有办法在 Qt 中使用这个功能。如果是这种情况,您可以在没有 Qt 的情况下使用 python-requests。

【讨论】:

  • 您好,谢谢您的回答,我正在安装PyQt,由于文件很大,我似乎需要将代码更改为PyQt,我还有一个问题,我知道如何为内容设置标题长度,但我不知道如何设置提交表单的标题,我之前也搜索过这部分但没有运气。即像这样的简单表单:。这个表格的标题是什么?一个提示就足够了。谢谢
  • 没有“提交表单的标题”之类的东西。发出 POST 请求意味着提交表单。您可以使用浏览器的开发工具来获取浏览器发送的实际标题和表单数据。
  • 抱歉再次询问,但我无缘无故收到此错误:“QHttpPart.setBodyDevice(QIODevice): argument 1 has unexpected type 'QByteArray'”。我根本没有使用 QByteArray 那么这是什么意思?
  • @Mohammadhzp。你怎么得到这个错误?我尝试了上面的 PyQt 示例,它似乎对我有用,没有错误。
  • 我试图在我自己的软件中使用它,我粘贴了代码here。(你的例子)给出了错误,我不明白为什么 Pavel 代码不能这样工作
猜你喜欢
  • 1970-01-01
  • 2010-11-01
  • 1970-01-01
  • 1970-01-01
  • 2011-10-18
  • 1970-01-01
  • 1970-01-01
  • 2011-07-15
  • 1970-01-01
相关资源
最近更新 更多