Google App Engine urlfetch到POST文件

时间:2009-09-17 12:25:32

标签: python http google-app-engine

我正在尝试从GAE中的应用程序向torrage.com发送文件。 从用户上传收到文件后,该文件存储在内存中。

我希望能够使用此处提供的API发布此文件: http://torrage.com/automation.php但我遇到了一些问题,如果帖子的主体应该如何编码,我从API得到的最多是“文件为空”的消息。

3 个答案:

答案 0 :(得分:2)

我在POST界面上找到了torrage的API文档(与SOAP相反),这些文档与他们提供的示例C代码相当混乱和冲突。在我看来,在他们的PHP帖子的在线示例中,他们没有发送文件的内容(就像@kender的答案上面没有发送它),而他们是在SOAP示例和示例C代码中发送它。

C示例的相关部分(它们如何计算您要传递给urlfetch.fetch的标题)是:

  snprintf(formdata_header, sizeof(formdata_header) - 1,
    "Content-Disposition: form-data; name=\"torrent\"; filename=\"%s\"\n"
    "Content-Type: " HTTP_UPLOAD_CONTENT_TYPE "\n"
    "\n",
    torrent_file);
  http_content_len = 2 + strlen(content_boundary) + 1 + strlen(formdata_header) + st.st_size + 1 + 2 + strlen(content_boundary) + 3;
  LTdebug("http content len %u\n", http_content_len);
  snprintf(http_req, sizeof(http_req) - 1, 
    "POST /%s HTTP/1.1\n"
    "Host: %s\n"
    "User-Agent: libtorrage/" LTVERSION "\n"
    "Connection: close\n"
    "Content-Type: multipart/form-data; boundary=%s\n"
    "Content-Length: %u\n"
    "\n",
    cache_uri, cache_host, content_boundary, http_content_len);

“application / x-bittorrent”是HTTP_UPLOAD_CONTENT_TYPEst.st_size是内存缓冲区中包含所有文件数据的字节数(C样本从文件中读取该数据,但只要知道它的大小,将其放入内存并不重要) 。 content_boundary是一个字符串,它不存在于文件的内容中,它们将其构建为"---------------------------%u%uLT",每个%u被一个随机数替换(重复直到该字符串击中两个随机数字,使其成为不存在于文件中)。最后,帖子正文(打开HTTP套接字并发送其他标题后)按如下方式编写:

  if (write_error == 0) if (write(sock, "--", 2) <= 0) write_error = 1;
  if (write_error == 0) if (write(sock, content_boundary, strlen(content_boundary)) <= 0) write_error = 1;
  if (write_error == 0) if (write(sock, "\n", 1) <= 0) write_error = 1;
  if (write_error == 0) if (write(sock, formdata_header, strlen(formdata_header)) <= 0) write_error = 1;
  if (write_error == 0) if (write(sock, filebuf, st.st_size) <= 0) write_error = 1;
  if (write_error == 0) if (write(sock, "\n--", 3) <= 0) write_error = 1;
  if (write_error == 0) if (write(sock, content_boundary, strlen(content_boundary)) <= 0) write_error = 1;
  if (write_error == 0) if (write(sock, "--\n", 3) <= 0) write_error = 1;

其中filebuf是包含文件内容的缓冲区。

非常简单明了,但我希望这里有足够的信息可以找到一种方法来构建urlfetch.fetch的参数(为urllib.urlopen构建它们会同样困难,因为问题关于究竟是什么标题和内容以及你需要的编码方式的文档很少 - 而且那些记录不完整的信息需要从我在这里提出的内容进行反向设计,我认为。

或者,可以通过urlfetch破解SOAP请求;请参阅here了解卡森关于此事的尝试,困难和成功的长篇文章。祝你好运!

答案 1 :(得分:0)

为什么不使用Python的urllib2模块来创建POST请求,就像它们在PHP的示例中所示。它会是这样的:

import urrlib, urllib2
data = (
        ('name', 'torrent'), 
        ('type', 'application/x-bittorrent'),
        ('file', '/path/to/your/file.torrent'),
)
request = urllib2.urlopen('http://torrage.com/autoupload.php', urllib.urlencode(data))

答案 2 :(得分:0)

从C代码来看,它使用的是“multipart / form-data”格式,这种格式非常复杂,很容易出错。我不会像这样手工编写帖子。

我使用了这个博客的功能,它从独立程序中为我工作。你可能想在app引擎中尝试一下,

http://peerit.blogspot.com/2007/07/multipartposthandler-doesnt-work-for.html