Выборка URL-адресов Google App Engine для ПУБЛИКАЦИИ файлов

#python #http #google-app-engine

#python #http #google-app-engine

Вопрос:

Я пытаюсь отправить файл в torrage.com из приложения в GAE. файл сохраняется в памяти после получения от пользователя при загрузке.

Я хотел бы иметь возможность опубликовать этот файл, используя API, доступный здесь: http://torrage.com/automation.php но у меня возникли некоторые проблемы с определением того, как должно быть закодировано тело сообщения, максимум, что я получил от API, — это сообщение «файл пуст».

Ответ №1:

Я нахожу документы API torrage в интерфейсе POST (в отличие от SOAP) довольно запутанными и противоречащими образцу кода C, который они также предоставляют. Мне кажется, что в их онлайн-примере PHP post они не отправляют содержимое файла (точно так же, как ответ @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 %un", http_content_len);
  snprintf(http_req, sizeof(http_req) - 1, 
    "POST /%s HTTP/1.1n"
    "Host: %sn"
    "User-Agent: libtorrage/" LTVERSION "n"
    "Connection: closen"
    "Content-Type: multipart/form-data; boundary=%sn"
    "Content-Length: %un"
    "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 (после открытия 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 находится буфер с содержимым файла.

Вряд ли это четко и просто, но я надеюсь, что здесь достаточно информации, чтобы выработать способ построения аргументов для a urlfetch.fetch (создать их для a urllib.urlopen было бы так же сложно, поскольку проблема заключается в нехватке документации о том, какие именно заголовки и какой контент и как закодированы вам нужны — и эта недостаточно хорошо документированная информация нуждается в обратном проектировании из того, что я здесь представляю, я думаю).

В качестве альтернативы может оказаться возможным взломать запрос SOAP с помощью urlfetch; смотрите Здесь длинный пост Карсона о его попытках, трудностях и успехах в этом вопросе. И удачи!

Ответ №2:

Почему бы просто не использовать модуль 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))
  

Комментарии:

1. В App Engine нет файлов, мне нужно использовать то, что у меня есть в памяти, для отправки файла.

2. Поскольку в примере PHP используется некоторая функциональность PHP, которая создает запрос multipart / form-data, не запрос в кодировке формы, который создается в вашем примере.

Ответ №3:

Судя по коду C, он использует формат «multipart / form-data», который очень сложный, и очень легко сделать что-то неправильно. Я бы не стал вручную кодировать текст сообщения подобным образом.

Я использовал функцию из этого блога, и она работала у меня в автономной программе. Возможно, вы захотите попробовать это в app engine,

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