Загрузка бинарного файла на http-сервер

Discussion in 'PHP' started by lukmus, 6 Feb 2010.

  1. lukmus

    lukmus Elder - Старейшина

    Joined:
    18 Nov 2009
    Messages:
    366
    Likes Received:
    115
    Reputations:
    23
    Как браузер закачивает файл на web-сервер, на примере vk0нтакта?

    Пытался анализировать трафик, но осталось слишком много белых пятен.

    Как обстоят дела:
    1. в браузере выбираем файл -> браузер формирует POST-запрос на сервер 'key=profile_photo_flood&item_id=@@USER_ID@@' + заголовок с cookie
    2. браузер по TCP походу отправляет сам бинарник, на все тот же 80-ый порт cs-сервера, имя которого можно прочитать на странице загрузки, в строке:
    3. обменявщись OK-ями, браузер формирует такой GET-запрос:
    Все параметры этого запроса, кроме photo мы можем узнать из страницы загрузки.

    Вопрос: откуда береться photo? Как собственно закачивать файл, тупо открывать сокет, коннектиться к серверу и кидать содержимое бинарника?
     
  2. Gifts

    Gifts Green member

    Joined:
    25 Apr 2008
    Messages:
    2,494
    Likes Received:
    807
    Reputations:
    614
    lukmus Вы вроде собирались прочитать RFC2616 про HTTP протокол. Там будет ссылка на другой рфц, который собственно интересует вас сейчас RFC1867 (http://www.faqs.org/rfcs/rfc1867.html) А параметр photo видимо отдается после загрузки фотографии. Скорее всего в хидере Location

    З.Ы, Если рфц - сложно, погуглите на тему "multipart/form-data"
    З.Ы.Ы. Перестаньте плодить темы, для таких вопросов есть прикрепленные темы
     
    _________________________
    1 person likes this.
  3. lukmus

    lukmus Elder - Старейшина

    Joined:
    18 Nov 2009
    Messages:
    366
    Likes Received:
    115
    Reputations:
    23
    Да простит меня Gifts, но я продолжу ковырять эту тему.
    Никак не могу догнать в каком же все-таки запросе посылаеться содержимое файла.
    Вот дамп пакета, как это делает ФФ:
    [​IMG]
    Вот как делаю я (ruby):
    Code:
     
    Class Account
    ...
    def create(uri, pars)
        post = Net::HTTP::Post.new(uri.path)
        boundary = (rand*1000000000).to_i.to_s
        post.set_content_type("multipart/form-data", {:boundary => boundary})
        
        body = ""
        pars.each do |key, value|
          body << "--#{boundary}\r\n"
          append_post_parameter(body, key, value)
        end
        body << "--#{boundary}--"
        
        post.content_length = body.length
        post.body = body 
        return post
      end
      
      def append_post_parameter(body, key, value)    
        if value.class == File
          body << "Content-disposition: form-data; name=\"#{key}\";\ 
    filename=\"#{File.basename(value.path)}\"\r\n"
          body << "Content-type: multipart/form-data;\r\n"
          body << "Cookie: remixlang=0; remixchk=5; remixsid=#{@cook}; remixclosed_tabs=0\r\n"
          body << "User-agent: Mozilla/5.0 (Windows; U; Windows NT 6.1; en-US; rv:1.9.1.5) Gecko/20091102 Firefox/3.5.5 (.NET CLR 3.5.30729)\r\n"
          body << "Content-Transfer-Encoding: binary\r\n\r\n"
          body << value.binmode.read
          body << "\r\n"
        else
          body << "Content-disposition: form-data; name=\"#{key}\"\r\n\r\n"
          body << "#{value}\r\n"
        end
      end
    
    def upload_ava()
    #Тут идет какой-то предварительный запрос, не знаю его смысл, я просто повторил за браузером
                      @http=Net::HTTP.new('vk.com', 80)
                       path="/captchaFlood.php"
    	data="key=profile_photo_flood&item_id=1.....4"
    	resp, data = @http.post(path,data,self.get_headers)
    #метод класса get_headers создает стандартный для запроса заголовок, с куками и прочей фигней
    #######################
    #Сам запрос
    uri = URI.parse('http://vk.com/upload.php?act=profile&mid=1........4&hash=2..........74&rhash=a..........de&vk=1')    
    post = self.create(uri, { :file => File.open("1.jpg"), :another => "parameter" })
    res = Net::HTTP.start("cs9651.vk.com", 80) do |http|
      http.request(post)
    end
    
    end
    end#class
    
    acc=Account.new(login,pass)
    acc.upload_ava
    
    в результате res возвращает что-то типа
    и конечно ничего не работает
     
    #3 lukmus, 16 Feb 2010
    Last edited: 16 Feb 2010
  4. lukmus

    lukmus Elder - Старейшина

    Joined:
    18 Nov 2009
    Messages:
    366
    Likes Received:
    115
    Reputations:
    23
    функции def create(uri, pars) и def append_post_parameter(body, key, value) я позаимствовал с одного блога, они как раз и разбираються с обычным сайтом.
    Буду очень благодарен за скрипт на php, perl, ruby итд который просто загружает аватарку, по кукам, логину:паролю, hash:rhash итд
     
  5. krypt3r

    krypt3r Elder - Старейшина

    Joined:
    27 Apr 2007
    Messages:
    1,507
    Likes Received:
    389
    Reputations:
    101
    Даже если и напишем, то вряд ли будем на голых сокетах писать - либо курл, либо лвп)