【发布时间】:2009-09-17 12:25:31
【问题描述】:
我正在尝试从 GAE 中的应用程序向 torrage.com 发送文件。 该文件在从用户上传后被存储在内存中。
我希望能够使用此处提供的 API 发布此文件: http://torrage.com/automation.php 但我有一些问题不知道应该如何编码帖子的正文,我从 API 得到的最多的是“文件为空”的消息。
【问题讨论】:
标签: python http google-app-engine
我正在尝试从 GAE 中的应用程序向 torrage.com 发送文件。 该文件在从用户上传后被存储在内存中。
我希望能够使用此处提供的 API 发布此文件: http://torrage.com/automation.php 但我有一些问题不知道应该如何编码帖子的正文,我从 API 得到的最多的是“文件为空”的消息。
【问题讨论】:
标签: python http google-app-engine
我发现 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_TYPE。 st.st_size 是内存缓冲区中包含所有文件数据的字节数(C 示例从文件中读取该数据,但无论您如何将其放入内存,只要您知道它的大小即可)。 content_boundary 是一个不存在于文件内容中的字符串,他们将其构建为 "---------------------------%u%uLT",每个 %u 由一个随机数替换(重复直到该字符串遇到两个使其不存在于文件中的随机数) .最后,post body(在打开 HTTP 套接字并发送其他 headers 之后)他们写如下:
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 了解卡森在这件事上的尝试、困难和成功的长期帖子。还有,祝你好运!
【讨论】:
为什么不直接使用 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))
【讨论】:
从C代码来看,使用的是“multipart/form-data”格式,非常复杂,很容易出错。我不会像那样手动编码帖子正文。
我使用了这个博客中的功能,它在独立程序中对我有用。您可能想在应用引擎中尝试一下,
http://peerit.blogspot.com/2007/07/multipartposthandler-doesnt-work-for.html
【讨论】: