Results 1 to 18 of 18

Thread: Http Posting using QNetworkAccessManager

  1. #1
    Join Date
    Jan 2014
    Location
    Iran
    Posts
    15
    Thanks
    9
    Qt products
    Platforms
    Unix/X11 Windows

    Default Http Posting using QNetworkAccessManager

    Hello
    I'm facing another problem
    it's about uploading file through HTTP posting
    this is my code

    Qt Code:
    1. from PyQt4 import QtCore, QtGui, QtNetwork
    2. import sys
    3. class Window(QtGui.QWidget):
    4. def __init__(self, parent=None):
    5. super(Window, self).__init__(parent)
    6.  
    7. self.netaccess = QtNetwork.QNetworkAccessManager(self)
    8. self._uploaders = {}
    9. row = 1 #this number will change per upload in real program,this is just demo
    10. self.address = 'http://localhost/01/upload/demo.php'
    11. stream = QtCore.QFile('/home/patriot/icon.png')
    12. if stream.open(QtCore.QIODevice.ReadOnly):
    13. data = stream
    14.  
    15. uploader = self._uploaders[row] = Uploader(row, self.netaccess)
    16.  
    17. uploader.upload(data, self.address)
    18.  
    19. class Uploader(QtCore.QObject):
    20.  
    21. def __init__(self, key, parent):
    22. QtCore.QObject.__init__(self, parent)
    23. self._key = key
    24. self._reply = None
    25.  
    26.  
    27. def upload(self, data, url):
    28. if self._reply is None:
    29.  
    30. self._stream = data
    31.  
    32. self._multiPart = QtNetwork.QHttpMultiPart(QtNetwork.QHttpMultiPart.FormDataType)
    33.  
    34. fileName = QtCore.QFileInfo(self._stream.fileName()).fileName()
    35. key = 'file'
    36.  
    37. imagePart = QtNetwork.QHttpPart()
    38. imagePart.setHeader(QtNetwork.QNetworkRequest.ContentDispositionHeader,
    39. "form-data; name=\"%s\"; filename=\"%s\"" % (key, fileName))
    40. imagePart.setHeader(QtNetwork.QNetworkRequest.ContentTypeHeader,
    41. 'image/png')
    42. imagePart.setBodyDevice(self._stream)
    43.  
    44. self._multiPart.append(imagePart)
    45.  
    46. request = QtNetwork.QNetworkRequest(QtCore.QUrl(url))
    47. request.setHeader(QtNetwork.QNetworkRequest.ContentTypeHeader,
    48. 'multipart/form-data; boundary=%s' % self._multiPart.boundary())
    49. request.setRawHeader('User-Agent','Mozilla/5.0 (X11; Linux i686) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/31.0.1650.63 Safari/537.36')
    50.  
    51. self._reply = self.parent().post(request, self._multiPart)
    52. self._reply.uploadProgress.connect(self.handleUploadProgress)
    53. self._reply.error.connect(self.handleError)
    54. self._reply.finished.connect(self.handleFinished)
    55.  
    56.  
    57.  
    58. def handleUploadProgress(self, sent, total):
    59. if sent >= total:
    60. # prevent duplicated uploads
    61. self._reply.close()
    62.  
    63. def handleFinished(self):
    64. print('Content: ',self._reply.readAll())#no output here :(
    65. self._stream.close()
    66. self._multiPart.deleteLater()
    67. self._reply.deleteLater()
    68. self._reply = None
    69. app.quit()
    70.  
    71. def handleError(self):
    72. print('Error String :',self._reply.errorString())
    73. print('Error number: ',self._reply.error())
    74.  
    75.  
    76. app = QtGui.QApplication(sys.argv)
    77. demo = Window()
    78. sys.exit(app.exec_())
    To copy to clipboard, switch view to plain text mode 

    I use an answer in stackoverflow.com,the code needs to upload to a php script but I don't know why it's not working
    anyone have any idea ?anything
    thanks

    edit: this is html form
    Qt Code:
    1. <form action="demo.php" method="post"
    2. enctype="multipart/form-data">
    3. <label for="file">Filename:</label>
    4. <input type="file" name="file" id="file"><br>
    5. <input type="submit" name="submit" value="Submit">
    6. </form>
    To copy to clipboard, switch view to plain text mode 
    Last edited by Mohammadhzp; 21st January 2014 at 01:19.

  2. #2
    Join Date
    Mar 2009
    Location
    Brisbane, Australia
    Posts
    7,729
    Thanks
    13
    Thanked 1,610 Times in 1,537 Posts
    Qt products
    Qt4 Qt5
    Platforms
    Unix/X11 Windows
    Wiki edits
    17

    Default Re: Http Posting using QNetworkAccessManager

    • Install Wireshark (UNIX or Windows).
    • Open the HTML form in your browser,
    • Submit the form using the same data as your Python program (Make it a small file).
    • Inspect what exactly is sent.
    • Run your program.
    • Inspect what exactly is sent.

    The differences will be informative.

  3. The following user says thank you to ChrisW67 for this useful post:

    Mohammadhzp (21st January 2014)

  4. #3
    Join Date
    Jan 2014
    Location
    Iran
    Posts
    15
    Thanks
    9
    Qt products
    Platforms
    Unix/X11 Windows

    Default Re: Http Posting using QNetworkAccessManager

    I'll look into this exactly
    but my problem is I can't see anything from python(even a simple echo in php)
    I think I can't even get into apache(for no reason)
    I can upload with requests(a python library) with this headers,but in Qt I can't,nothing,something is not right I can't figure out what is that.hope members could help

  5. #4
    Join Date
    Mar 2009
    Location
    Brisbane, Australia
    Posts
    7,729
    Thanks
    13
    Thanked 1,610 Times in 1,537 Posts
    Qt products
    Qt4 Qt5
    Platforms
    Unix/X11 Windows
    Wiki edits
    17

    Default Re: Http Posting using QNetworkAccessManager

    If your Qt code cannot even fetch a page from Apache (a GET) then you have more fundamental issues. You should work these out first.

    Read the docs for QNetworkReply::uploadProgress() again and ask yourself what happens if the total size cannot be determined.

    BTW: I do not see any reason from the close() call at all.
    "We can't solve problems by using the same kind of thinking we used when we created them." -- Einstein
    If you are posting code then please use [code] [/code] tags around it - makes addressing the problem easier.

  6. The following user says thank you to ChrisW67 for this useful post:

    Mohammadhzp (21st January 2014)

  7. #5
    Join Date
    Jan 2014
    Location
    Iran
    Posts
    15
    Thanks
    9
    Qt products
    Platforms
    Unix/X11 Windows

    Default Re: Http Posting using QNetworkAccessManager

    I edited my first code,I was thinking because my code is long it's looks ugly,thanks for mention that

    Quote Originally Posted by ChrisW67 View Post
    If your Qt code cannot even fetch a page from Apache (a GET) then you have more fundamental issues. You should work these out first.

    Read the docs for QNetworkReply::uploadProgress() again and ask yourself what happens if the total size cannot be determined.

    BTW: I do not see any reason from the close() call at all.
    you see,I need to upload through HTTP,at first when I was writing my first Qt program and did not know about HTTP stuff,I read data as a QByteArray and pass it to Uploader,after processing was done I could fetch the page and I could see contents,so uploadProgress is Ok,when I added QHttpMultiPart first of all I change data from QByteArray to QFile then pass it to Uploader and append data to multipart,at the end I posted QHttpMultiPart and request
    All I'm saying is Since I added QHttpMultiPart I can't fetch any pages,do you still think it's because QNetworkReply::uploadProgress() ?
    If I don't use close() or deleteLater() program will crash(seagment crash) or if you mean in UploadProgress it's because PyQt sometimes will post file twice(after uploading it start uploading again) I don't know it's my code or PyQt bug,but that solved my problem
    Last edited by Mohammadhzp; 21st January 2014 at 01:32.

  8. #6
    Join Date
    Mar 2009
    Location
    Brisbane, Australia
    Posts
    7,729
    Thanks
    13
    Thanked 1,610 Times in 1,537 Posts
    Qt products
    Qt4 Qt5
    Platforms
    Unix/X11 Windows
    Wiki edits
    17

    Default Re: Http Posting using QNetworkAccessManager

    Yes, I suspect it is. I suspect you are closing the reply at the first sign of progress. Print the value of total in handleUploadProgress.

  9. #7
    Join Date
    Jan 2014
    Location
    Iran
    Posts
    15
    Thanks
    9
    Qt products
    Platforms
    Unix/X11 Windows

    Default Re: Http Posting using QNetworkAccessManager

    I print both total and sent and at the end the value were the same(sent = total)
    Is this mean that closing reply is ok ? if yes do you have any idea ?


    Oh Chris,you are great,I did remove self._reply.close() in my real program and I could see a variable which I echo in PHP,you were right
    but still,can't send any file
    Last edited by Mohammadhzp; 21st January 2014 at 09:58.

  10. #8
    Join Date
    Jan 2006
    Location
    Graz, Austria
    Posts
    8,416
    Thanks
    37
    Thanked 1,544 Times in 1,494 Posts
    Qt products
    Qt3 Qt4 Qt5
    Platforms
    Unix/X11 Windows

    Default Re: Http Posting using QNetworkAccessManager

    You don't have to close a QNetworkReply. It will emit its finished() signal when it is done. If you don't need to do anything else when it is done, just connect the signal to the reply's deleteLater() slot.
    If you have other clean up to do, connect to a slot elsewhere.

    Cheers,
    _

  11. #9
    Join Date
    Jan 2014
    Location
    Iran
    Posts
    15
    Thanks
    9
    Qt products
    Platforms
    Unix/X11 Windows

    Default Re: Http Posting using QNetworkAccessManager

    Thanks for reply
    Yeah I got that but my main problem right now is not that,It's uploading file or data to a PHP script

  12. #10
    Join Date
    Mar 2009
    Location
    Brisbane, Australia
    Posts
    7,729
    Thanks
    13
    Thanked 1,610 Times in 1,537 Posts
    Qt products
    Qt4 Qt5
    Platforms
    Unix/X11 Windows
    Wiki edits
    17

    Default Re: Http Posting using QNetworkAccessManager

    Can you see the data in the network transfer using Wireshark (or Fiddler)?

  13. The following user says thank you to ChrisW67 for this useful post:

    Mohammadhzp (24th January 2014)

  14. #11
    Join Date
    Jan 2014
    Location
    Iran
    Posts
    15
    Thanks
    9
    Qt products
    Platforms
    Unix/X11 Windows

    Default Re: Http Posting using QNetworkAccessManager

    Yes I did
    these are the result:
    html form :
    html-form-monitor.jpg

    python program:
    python-monitor.jpg

    some headers are not sending while In my code I'm sending them,

  15. #12
    Join Date
    Jan 2014
    Location
    Iran
    Posts
    15
    Thanks
    9
    Qt products
    Platforms
    Unix/X11 Windows

    Default Re: Http Posting using QNetworkAccessManager

    can someone drive me to right direction please ?

  16. #13
    Join Date
    Mar 2009
    Location
    Brisbane, Australia
    Posts
    7,729
    Thanks
    13
    Thanked 1,610 Times in 1,537 Posts
    Qt products
    Qt4 Qt5
    Platforms
    Unix/X11 Windows
    Wiki edits
    17

    Default Re: Http Posting using QNetworkAccessManager

    Your multipart form data needs to include the other elements of the form. In this case the submit button.
    Qt Code:
    1. imagePart = QtNetwork.QHttpPart()
    2. imagePart.setHeader(QtNetwork.QNetworkRequest.ContentDispositionHeader,
    3. "form-data; name=\"%s\"; filename=\"%s\"" % (key, fileName))
    4. imagePart.setHeader(QtNetwork.QNetworkRequest.ContentTypeHeader,
    5. 'image/jpeg')
    6. imagePart.setBodyDevice(self._stream)
    7.  
    8. submitPart = QtNetwork.QHttpPart()
    9. submitPart.setHeader(QtNetwork.QNetworkRequest.ContentDispositionHeader,
    10. "form-data; name=\"submit\"")
    11. submitPart.setBody("submit")
    12.  
    13. self._multiPart.append(imagePart)
    14. self._multiPart.append(submitPart)
    To copy to clipboard, switch view to plain text mode 

  17. The following user says thank you to ChrisW67 for this useful post:

    Mohammadhzp (24th January 2014)

  18. #14
    Join Date
    Jan 2014
    Location
    Iran
    Posts
    15
    Thanks
    9
    Qt products
    Platforms
    Unix/X11 Windows

    Default Re: Http Posting using QNetworkAccessManager

    I tried this but no differences.still not working
    I don't know what to do anymore

  19. #15
    Join Date
    Mar 2009
    Location
    Brisbane, Australia
    Posts
    7,729
    Thanks
    13
    Thanked 1,610 Times in 1,537 Posts
    Qt products
    Qt4 Qt5
    Platforms
    Unix/X11 Windows
    Wiki edits
    17

    Default Re: Http Posting using QNetworkAccessManager

    Yes it is. Your code with only the web server and file path changed, the submit button encoded, and the close() call removed:
    Qt Code:
    1. from PyQt4 import QtCore, QtGui, QtNetwork
    2. import sys
    3. class Window(QtGui.QWidget):
    4. def __init__(self, parent=None):
    5. super(Window, self).__init__(parent)
    6.  
    7. self.netaccess = QtNetwork.QNetworkAccessManager(self)
    8. self._uploaders = {}
    9. row = 1 #this number will change per upload in real program,this is just demo
    10. self.address = 'http://dev/demo.php'
    11. stream = QtCore.QFile('icon.png')
    12. if stream.open(QtCore.QIODevice.ReadOnly):
    13. data = stream
    14.  
    15. uploader = self._uploaders[row] = Uploader(row, self.netaccess)
    16.  
    17. uploader.upload(data, self.address)
    18.  
    19. class Uploader(QtCore.QObject):
    20.  
    21. def __init__(self, key, parent):
    22. QtCore.QObject.__init__(self, parent)
    23. self._key = key
    24. self._reply = None
    25.  
    26.  
    27. def upload(self, data, url):
    28. if self._reply is None:
    29.  
    30. self._stream = data
    31.  
    32. self._multiPart = QtNetwork.QHttpMultiPart(QtNetwork.QHttpMultiPart.FormDataType)
    33.  
    34. fileName = QtCore.QFileInfo(self._stream.fileName()).fileName()
    35. key = 'file'
    36.  
    37. imagePart = QtNetwork.QHttpPart()
    38. imagePart.setHeader(QtNetwork.QNetworkRequest.ContentDispositionHeader,
    39. "form-data; name=\"%s\"; filename=\"%s\"" % (key, fileName))
    40. imagePart.setHeader(QtNetwork.QNetworkRequest.ContentTypeHeader,
    41. 'image/png')
    42. imagePart.setBodyDevice(self._stream)
    43.  
    44. submitPart = QtNetwork.QHttpPart()
    45. submitPart.setHeader(QtNetwork.QNetworkRequest.ContentDispositionHeader,
    46. "form-data; name=\"submit\"")
    47. submitPart.setBody("submit")
    48.  
    49. self._multiPart.append(imagePart)
    50. self._multiPart.append(submitPart)
    51.  
    52. request = QtNetwork.QNetworkRequest(QtCore.QUrl(url))
    53. request.setHeader(QtNetwork.QNetworkRequest.ContentTypeHeader,
    54. 'multipart/form-data; boundary=%s' % self._multiPart.boundary())
    55. request.setRawHeader('User-Agent','Mozilla/5.0 (X11; Linux i686) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/31.0.1650.63 Safari/537.36')
    56.  
    57. self._reply = self.parent().post(request, self._multiPart)
    58. self._reply.uploadProgress.connect(self.handleUploadProgress)
    59. self._reply.error.connect(self.handleError)
    60. self._reply.finished.connect(self.handleFinished)
    61.  
    62.  
    63.  
    64. def handleUploadProgress(self, sent, total):
    65. print sent, total
    66.  
    67. def handleFinished(self):
    68. print('Content: ',self._reply.readAll())#no output here :(
    69. self._stream.close()
    70. self._multiPart.deleteLater()
    71. self._reply.deleteLater()
    72. self._reply = None
    73. app.quit()
    74.  
    75. def handleError(self):
    76. print('Error String :',self._reply.errorString())
    77. print('Error number: ',self._reply.error())
    78.  
    79.  
    80. app = QtGui.QApplication(sys.argv)
    81. demo = Window()
    82. sys.exit(app.exec_())
    To copy to clipboard, switch view to plain text mode 
    Using this simple PHP file upload receiver:
    Qt Code:
    1. $ cat demo.php
    2. <html>
    3. <body>
    4. <form method="post" enctype="multipart/form-data">
    5. <label for="file">Filename:</label>
    6. <input type="file" name="file" id="file" />
    7. <br />
    8. <input type="submit" name="submit" value="Submit" />
    9. </form>
    10. <p>
    11. <?php
    12. if(isset($_POST['submit'])) {
    13. if ($_FILES["file"]["error"] > 0) {
    14. echo "Error: " . $_FILES["file"]["error"] . "<br />";
    15. } else {
    16. echo "Upload: " . $_FILES["file"]["name"] . "<br />";
    17. echo "Type: " . $_FILES["file"]["type"] . "<br />";
    18. echo "Size: " . ($_FILES["file"]["size"] / 1024) . " Kb<br />";
    19. echo "Stored in: " . $_FILES["file"]["tmp_name"];
    20. }
    21. }
    22. ?>
    23. </p>
    24. </body>
    25. </html>
    To copy to clipboard, switch view to plain text mode 
    Gives this output with an artificially large icon.png:
    Qt Code:
    1. 16384 530779
    2. 32768 530779
    3. ...
    4. 524288 530779
    5. 530779 530779
    6. ('Content: ', PyQt4.QtCore.QByteArray('<html>\n <body>\n <form method="post" enctype="multipart/form-data">\n <label for="file">Filename:</label>\n <input type="file" name="file" id="file" /> \n <br />\n <input type="submit" name="submit" value="Submit" />\n </form>\n <p>\n Upload: icon.png<br />Type: image/png<br />Size: 517.9921875 Kb<br />Stored in: /tmp/phpKg8FG7 </p>\n </body>\n</html>\n'))
    To copy to clipboard, switch view to plain text mode 
    Last edited by ChrisW67; 23rd January 2014 at 23:07. Reason: Better PHP

  20. The following user says thank you to ChrisW67 for this useful post:

    Mohammadhzp (24th January 2014)

  21. #16
    Join Date
    Jan 2014
    Location
    Iran
    Posts
    15
    Thanks
    9
    Qt products
    Platforms
    Unix/X11 Windows

    Default Re: Http Posting using QNetworkAccessManager

    Oh my God
    I can't believe finally solution is here
    I don't know how to say thank you,you helped me a lot,thanks Chris
    it's working like a charm
    but I also found the real issue in here
    I tried your code in python3 for the first time and like always I didn't get any answer(no file uploaded) I become so upset since your code didn't working too !
    anyway,I just thought maybe it's because PyQt4 have problem in python3,So I installed PyQt4 on python2 and Got exactly your result and file is uploading too
    so it's obviously a PyQt4 bug in python3(the exact code is working on python2 but not in python3)
    Do I need to report this ? how ?

  22. #17
    Join Date
    Mar 2009
    Location
    Brisbane, Australia
    Posts
    7,729
    Thanks
    13
    Thanked 1,610 Times in 1,537 Posts
    Qt products
    Qt4 Qt5
    Platforms
    Unix/X11 Windows
    Wiki edits
    17

    Default Re: Http Posting using QNetworkAccessManager

    I am running Python 2.7.5 and Python 3.2.5 with PyQt 4.10.2 on 64-bit Linux.

    My Python 3.2 on Linux also fails to send the data. The multipart message never makes it onto the wire correctly. Look closely at the two requests in Wireshark. With Python 2.7 the request goes on the wire with this header:
    Qt Code:
    1. MIME Multipart Media Encapsulation, Type: multipart/form-data, Boundary: "boundary_.oOo._Nzc0MjMxOTU4MTgyMzc5MTk0Mw==NzIxMTQzNjA4"
    To copy to clipboard, switch view to plain text mode 
    but with Python 3 the Boundary value gets mangled:
    Qt Code:
    1. MIME Multipart Media Encapsulation, Type: multipart/form-data, Boundary: "b'boundary_.oOo._NjY2OTgyMTQ3MTg1NTk1MzgyNw==NDY5Njg1NTMw'"
    To copy to clipboard, switch view to plain text mode 
    resulting in a malformed payload (because the payload is encoded with boundary = "boundary_.oOo._NjY2OTgyMTQ3MTg1NTk1MzgyNw==NDY5Nj g1NTMw"). The PyQt4 under Python 3 is outputting the boundary as a bytes literal not a string. This could be a python wrapper type mapping issue.

    You should address the issue to the PyQt mailing list or Riverbank Software directly if you have a commercial licence.

  23. The following user says thank you to ChrisW67 for this useful post:

    Mohammadhzp (24th January 2014)

  24. #18
    Join Date
    Jan 2014
    Location
    Iran
    Posts
    15
    Thanks
    9
    Qt products
    Platforms
    Unix/X11 Windows

    Default Re: Http Posting using QNetworkAccessManager

    I reported bug
    Thanks for help Chris

Similar Threads

  1. Replies: 2
    Last Post: 8th January 2014, 15:40
  2. Replies: 4
    Last Post: 2nd May 2012, 12:51
  3. QNetworkAccessManager and http redirection
    By grayfox in forum Qt Programming
    Replies: 5
    Last Post: 8th July 2011, 17:24
  4. HTTP Post from QNetworkAccessManager - no data sent
    By secureboot in forum Qt Programming
    Replies: 1
    Last Post: 13th April 2011, 18:46
  5. QNetworkAccessManager Http Basic Authentication?
    By jloundy in forum Qt Programming
    Replies: 5
    Last Post: 29th December 2010, 00:19

Tags for this Thread

Bookmarks

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •  
Digia, Qt and their respective logos are trademarks of Digia Plc in Finland and/or other countries worldwide.