2012-09-07 88 views
1

所以我使用curl命令如下:转换curl命令来pycurl

cmd = "curl --write-out %{http_code} -X PUT -T " + self.basedir + putfile + " -# -o /dev/null " + self.uri + "/" + self.dist + "/" + putfile 

我想从调用系统命令使用pycurl改变这一点。通过这种方式,我可以对其进行更细化的控制,并最终为其实施进度条。但是,当我尝试转换为python时,我的结果脚本失败。下面是我对Python脚本的努力:

f = open(filepath, "rb") 
fs = os.path.getsize(filepath) 
c = pycurl.Curl() 
c.setopt(c.URL, target_url) 
c.setopt(c.HTTPHEADER, ["User-Agent: Load Tool (PyCURL Load Tool)"]) 
c.setopt(c.PUT, 1) 
c.setopt(c.READDATA, f) 
c.setopt(c.INFILESIZE, int(fs)) 
c.setopt(c.NOSIGNAL, 1) 
c.setopt(c.VERBOSE, 1) 
c.body = StringIO() 
c.setopt(c.WRITEFUNCTION, c.body.write) 
try: 
     c.perform() 
except: 
     import traceback 
     traceback.print_exc(file=sys.stderr) 
sys.stderr.flush() 

f.close() 
c.close() 

sys.stdout.write(".") 
sys.stdout.flush() 

这里是输出:

* About to connect() to ************ port 8090 (#0) 
* Trying 16.94.124.53... * connected 
> PUT /incoming/ HTTP/1.1 
Host: *********** 
Accept: */* 
User-Agent: Load Tool (PyCURL Load Tool) 
Content-Length: 21 
Expect: 100-continue 

< HTTP/1.1 100 Continue 
* We are completely uploaded and fine 
< HTTP/1.1 500 Internal Server Error 
< Content-type: text/html 
* no chunk, no close, no size. Assume close to signal end 
< 

提前感谢您的帮助!

+0

我发现卷曲是相当直观的找到有关pycurl几乎所有的答案,但pycurl似乎使作出一切努力复制这个直觉。 我最近提出了一个非常类似的问题,并且StackOverflow社区的成员非常友好地提出'请求'模块。此第三方模块取代了urllib,urllib2和pycurl的API反乌托邦。 http://docs.python-requests.org/en/latest/index.html – ChrisGuest

回答

0

我已经做了上传工作模块,你可以在代码中找到你的答案。

enter image description here

''' 
Created on Oct 22, 2013 

@author: me 
''' 
import pycurl 
import os 
import wx 
import sys 
import hashlib 
from cStringIO import StringIO 

def get_file_hash(full_filename): 
    BLOCKSIZE = 65536 
    hasher = hashlib.md5() 
    with open(full_filename, 'rb') as afile: 
     buf = afile.read(BLOCKSIZE) 
     while len(buf) > 0: 
      hasher.update(buf) 
      buf = afile.read(BLOCKSIZE) 
    return hasher.hexdigest() 

class FtpUpload(object): 

    def __init__(self, server, username, password, **items): 
     self.server = server 
     self.username = username 
     self.password = password 
     self.gauge = items.get("gauge") 
     self.sb_speed = items.get("sb_speed") 
     self.upload_file_size = items.get("upload_file_size") 
     self.upload_file_speed = items.get("upload_file_speed") 
     self.filesize = 0 
     self.ftp_filehash = '0' 

    def sizeToNiceString(self, byteCount): 
     for (cutoff, label) in [(1024*1024*1024, "GB"), (1024*1024, "MB"), (1024, "KB")]: 
      if byteCount >= cutoff: 
       return "%.2f %s" % (byteCount * 1.0/cutoff, label) 
     if byteCount == 1: 
      return "1 byte" 
     else: 
      return "%d bytes" % byteCount 

    def initRange(self, filesize): 
     self.filesize = filesize 
     self.gauge.SetRange(filesize) 

    def updateValue(self, upload_d): 
     upload_d_int = int(upload_d) 
     self.gauge.SetValue(upload_d_int) 

     upload_d_str = self.sizeToNiceString(upload_d) 
     upload_percent = int((upload_d*100)/self.filesize) 

     upload_d_status = "{0}/{1} ({2}%)".format(upload_d_str, self.sizeToNiceString(self.filesize), upload_percent) 
     self.sb_speed.SetStatusText(upload_d_status, 1) 
     self.upload_file_size.SetLabel(upload_d_status) 
     self.upload_file_speed.SetLabel(upload_d_str) 

    def progress(self, download_t, download_d, upload_t, upload_d): 
     self.updateValue(upload_d) 

    def test(self, debug_type, debug_msg): 
     if len(debug_msg) < 300: 
      print "debug(%d): %s" % (debug_type, debug_msg.strip()) 

    def ftp_file_hash(self, buf): 
     sys.stderr.write("{0:.<20} : {1}\n".format('FTP RAW ', buf.strip())) 
     ftp_filehash = dict() 
     item = buf.strip().split('\n')[0] 
     ext = item.split('.')[1] 
     if len(ext) > 3: 
      ftp_filename = item[:-33] 
      ftp_filehash = item[-32:] 
     self.ftp_filehash = ftp_filehash 

    def get_ftp_file_hash(self, filename): 
     c = pycurl.Curl() 
     list_file_hash = 'LIST -1 ' + filename + "_*" 
     sys.stderr.write("{0:.<20} : {1} \n".format('FTP command ', list_file_hash)) 
     c.setopt(pycurl.URL, self.server) 
     c.setopt(pycurl.USERNAME, self.username) 
     c.setopt(pycurl.PASSWORD, self.password) 
     c.setopt(pycurl.VERBOSE, False) 
     c.setopt(pycurl.DEBUGFUNCTION, self.test) 
     c.setopt(pycurl.CUSTOMREQUEST, list_file_hash) 
     c.setopt(pycurl.WRITEFUNCTION, self.ftp_file_hash) 
     c.perform() 
     c.close() 

    def delete_ftp_hash_file(self, ftp_hash_file_old): 
     c = pycurl.Curl() 
     delete_hash_file = 'DELE ' + ftp_hash_file_old 
     sys.stderr.write("{0:.<20} : {1} \n".format('FTP command ', delete_hash_file)) 
     c.setopt(pycurl.URL, self.server) 
     c.setopt(pycurl.USERNAME, self.username) 
     c.setopt(pycurl.PASSWORD, self.password) 
     c.setopt(pycurl.VERBOSE, False) 
     c.setopt(pycurl.DEBUGFUNCTION, self.test) 
     c.setopt(pycurl.CUSTOMREQUEST, delete_hash_file) 
     try: 
      c.perform() 
     except Exception as e: 
      print e 
     c.close() 

    def upload(self, full_filename, filesize): 
     self.initRange(filesize) 
     filename = os.path.basename(full_filename) 
     sys.stderr.write("filename: %s\n" % full_filename) 

     c = pycurl.Curl() 
     c.setopt(pycurl.USERNAME, self.username) 
     c.setopt(pycurl.PASSWORD, self.password) 

     c.setopt(pycurl.VERBOSE, False) 
     c.setopt(pycurl.DEBUGFUNCTION, self.test) 

     c.setopt(pycurl.NOBODY, True) 
     c.setopt(pycurl.HEADER, False) 

     ftp_file_path = os.path.join(self.server, os.path.basename(full_filename)) 
     file_hash = get_file_hash(full_filename) 
     ftp_hash_file = ftp_file_path + "_%s" % file_hash 

     # Getting filesize if exist on server. 
     try: 
      c.setopt(pycurl.URL, ftp_file_path) 
      c.perform() 
      filesize_offset = int(c.getinfo(pycurl.CONTENT_LENGTH_DOWNLOAD)) 
     except Exception as error_msg: 
      print error_msg 
      wx.MessageBox(str(error_msg), 'Connection error!', 
       wx.OK | wx.ICON_ERROR) 
      # Exit upload function. 
      return True 

     ftp_file_append = True 
     # Get ftp file hash. 
     self.get_ftp_file_hash(filename) 

     offset = filesize_offset == -1 and '0' or filesize_offset 
     sys.stderr.write("L_file hash : {0:.<60}: {1:<40}\n".format(filename, file_hash)) 
     sys.stderr.write("F_file hash : {0:.<60}: {1:<40}\n".format(filename, self.ftp_filehash)) 
     sys.stderr.write("{0:15} : {1:.>15}\n".format('filesize:', filesize)) 
     sys.stderr.write("{0:15} : {1:.>15}\n".format('ftp_filesize', offset)) 
     sys.stderr.write("{0:15} : {1:.>15}\n".format('to upload:', filesize - int(offset))) 
     # File not exist on FTP server. 
     if filesize_offset == -1: 
      # file not exist: uploading from offset zero. 
      ftp_file_append = False 
      filesize_offset = 0 
     # Local and FTP file size and files MD5 are the same. 
     elif filesize_offset == self.filesize and file_hash == self.ftp_filehash: 
      sys.stderr.write("--- File exist on server! ---\n\n") 
      self.upload_file_speed.SetLabel("File exist on server!") 
      self.sb_speed.SetStatusText("File exist on server!", 1) 
      # Check next filename. 
      return False 
     # Ftp file and local file different data. 
     elif file_hash != self.ftp_filehash: 
      ftp_file_append = False 
      filesize_offset = 0 
      ftp_hash_file_old = filename + "_" + self.ftp_filehash 
      # delete old hash file. 
      self.delete_ftp_hash_file(ftp_hash_file_old) 

     c.setopt(pycurl.FTPAPPEND, ftp_file_append) 
     c.setopt(pycurl.UPLOAD, True) 
     c.setopt(pycurl.PROGRESSFUNCTION, self.progress) 

     with open('filehash.txt', 'w') as f: 
      f.write(file_hash) 

     for item in ("filehash.txt", full_filename): 
      # dont show progress by default. 
      noprogress = True 
      # upload ftp_hash_file first. 
      ftp_url = ftp_hash_file 

      with open(item, "rb") as f: 
       # chages ftp_url and show progress values, add filesize_offset. 
       if item != "filehash.txt": 
        f.seek(filesize_offset) 
        noprogress = False 
        ftp_url = ftp_file_path 

       c.setopt(pycurl.URL, ftp_url) 
       c.setopt(pycurl.NOPROGRESS, noprogress) 
       c.setopt(pycurl.READFUNCTION, f.read) 
       try: 
        c.perform() 
        if item != "filehash.txt": 
         sys.stderr.write("{0:15} : {1:.>15}\n\n".format("size uploaded", int(c.getinfo(pycurl.SIZE_UPLOAD)))) 
       except Exception as error_msg: 
        print error_msg 
        wx.MessageBox(str(error_msg), 'Connection error!', 
         wx.OK | wx.ICON_ERROR) 
        # Exit upload function. 
        return True 
     self.ftp_filehash = '0' 
     c.close() 

if __name__ == '__main__': 
    pass