我正在尝试使用Curl :: Easy.http_put,但是数据参数存在一些问题

时间:2014-03-13 16:15:57

标签: ruby http-put curb

我正在努力使用红宝石脚本使用他们的http界面将一些图片上传到moodstocks

这是我到目前为止的代码

curb = Curl::Easy.new
curb.http_auth_types = :digest
curb.username = MS_API
curb.password = MS_SECRET
curb.multipart_form_post = true

Dir.foreach(images_directory) do |image|
  if image.include? '.jpg'
    path = images_directory + image
    filename = File.basename(path, File.extname(path))

    puts "Upload #{path} with id #{filename}"

    raw_url = 'http://api.moodstocks.com/v2/ref/' + filename
    encoded_url = URI.parse URI.encode raw_url

    curb.url = encoded_url
    curb.http_put(Curl::PostField.file('image_file', path))
  end
end

这是我得到的错误

/Library/Ruby/Gems/2.0.0/gems/curb-0.8.5/lib/curl/easy.rb:57:in `add': no implicit        conversion of nil into String (TypeError)
    from /Library/Ruby/Gems/2.0.0/gems/curb-0.8.5/lib/curl/easy.rb:57:in `perform'
    from upload_moodstocks.rb:37:in `http_put'
    from upload_moodstocks.rb:37:in `block in <main>'
    from upload_moodstocks.rb:22:in `foreach'
    from upload_moodstocks.rb:22:in `<main>'

我认为问题出在我如何将参数提供给http_put方法,但我试图寻找一些Curl :: Easy.http_put的例子,到目前为止还没有找到。

有人能指出一些有关它的文件或帮我解决这个问题。

提前谢谢

1 个答案:

答案 0 :(得分:2)

这里有几个问题:

<强> 1。 URI :: HTTP而不是String

首先,您遇到的TypeError来自于您将URI::HTTP实例(encoded_url)作为curb.url而不是普通的Ruby字符串传递的事实。

您可能想要使用encoded_url.to_s,但问题是为什么要在此处进行解析/编码?

<强> 2。 PUT w / multipart / form-data

第二个问题与curb有关。在撰写本文时(v0.8.5),curb NOT 支持使用multipart/form-data编码执行HTTP PUT请求的能力。

如果您参考源代码,您可以看到:

  1. multipart_form_post设置仅用于POST请求,
  2. put_data setter不支持Curl::PostField - s

  3. 要解决您的问题,您需要一个可以结合摘要式身份验证,多部分/表单数据和HTTP PUT的HTTP客户端库。

    在Ruby中,您可以使用rufus-verbs,但是您需要使用rest-client来构建多部分正文。

    还有HTTParty,但它与Digest Auth有问题。

    这就是为什么我强烈建议继续使用Python并使用Requests

    import requests
    from requests.auth import HTTPDigestAuth
    import os
    
    MS_API_KEY = "kEy"
    MS_API_SECRET = "s3cr3t"
    
    filename = "sample.jpg"
    
    with open(filename, "r") as f:
      base = os.path.basename(filename)
      uid = os.path.splitext(base)[0]
    
      r = requests.put(
        "http://api.moodstocks.com/v2/ref/%s" % uid,
        auth = HTTPDigestAuth(MS_API_KEY, MS_API_SECRET),
        files = {"image_file": (base, f.read())}
      )
    
      print(r.status_code)