Форум программистов «Весельчак У»
  *
Добро пожаловать, Гость. Пожалуйста, войдите или зарегистрируйтесь.
Вам не пришло письмо с кодом активации?

  • Рекомендуем проверить настройки временной зоны в вашем профиле (страница "Внешний вид форума", пункт "Часовой пояс:").
  • У нас больше нет рассылок. Если вам приходят письма от наших бывших рассылок mail.ru и subscribe.ru, то знайте, что это не мы рассылаем.
   Начало  
Наши сайты
Помощь Поиск Календарь Почта Войти Регистрация  
 
Страниц: [1]   Вниз
  Печать  
Автор Тема: WinINet: Реально ли получить имя файла ?  (Прочитано 14154 раз)
0 Пользователей и 4 Гостей смотрят эту тему.
kisilevski
Постоялец

ru
Offline Offline
Пол: Мужской

WWW
« : 19-11-2008 08:38 » 

Ситуация такая: С помощью WinINet функций загружаю с сервера файлы.
Ну, типа HttpOpenRequest, HttpSendRequest, InternetReadFile итд. Всё работает.

Проблема в следующем:
Если есть ссылка типа h**p://www.codeproject.com/KB/dialog/CGlassDialog/cglassdialog_source.zip, то у меня в явном аиде имеется имя файла, с которым я могу сохранить полученное.
Если есть ссылка, для которой в теге <А href="чегототам">Filename.ext</А> явным образом прописано имя файла - тоже всё понятно.

Если же есть такая ссылка: h**p://www.gz-volga.ru/pls/kea/utl.download_attach?p_id=365926
или такая: <А href="h**p://spl.gz-kuban.ru/spl.gz-kuban.ru/blob;jsessionid=8282F7DD226BBBC1F7CBB6B4EB7640FB?id=152710">Скачать</А>,

то тогда у меня вообще нет имени файла. Однако, если делать через IE -> SaveTargetAs - он каким-то образом получает имя файла при закачке, то есть это как-то возможно.
Просмотрел список фозможных флагов для HttpQueryInfo - ничего подходящего не нашлось.

Подскажите, пожалуйста, каким образом можно всё-таки получить в процессе закачки файла его имя. Вообще не представляю себе с какого конца к этой проблеме подступиться.
« Последнее редактирование: 19-11-2008 10:17 от Вад » Записан

Ложки нет. See MSDN for details.
zubr
Гость
« Ответ #1 : 19-11-2008 09:19 » 

Цитата
<А href="h**p://spl.gz-kuban.ru/spl.gz-kuban.ru/blob;jsessionid=8282F7DD226BBBC1F7CBB6B4EB7640FB?id=152710">Скачать</А>
Это ссылка не на сам файл, а на страницу, с ссылкой на файл. Загрузка файла уже осуществляется или пользователем или скриптом автоматически.
Как выход - имитировать действия пользователя, кликом на ссылке.
« Последнее редактирование: 19-11-2008 10:18 от Вад » Записан
kisilevski
Постоялец

ru
Offline Offline
Пол: Мужской

WWW
« Ответ #2 : 19-11-2008 09:35 » 

Цитата
<А href="h**p://spl.gz-kuban.ru/spl.gz-kuban.ru/blob;jsessionid=8282F7DD226BBBC1F7CBB6B4EB7640FB?id=152710">Скачать</А>
Это ссылка не на сам файл, а на страницу, с ссылкой на файл.

Насколько я понимаю, это не совсем так.
Через IE - Save Target AS получается файл с дивным именем "КД+по+Лоту+6030.rar".
Через InternetReadFile, ручками, приходит тот же массив размером 168 кБайт. То есть сервер отдаёт файл именно по той ссылке, безо всякой промежуточной страницы со скриптом. И как-то IE умудряется получить его имя..

К тому же кликнуть-то по ней можно, но после этого нужно ручками указывать куда сохранять итд. А должно всё само работать, без участия персонала.
« Последнее редактирование: 19-11-2008 10:25 от kisilevski » Записан

Ложки нет. See MSDN for details.
kisilevski
Постоялец

ru
Offline Offline
Пол: Мужской

WWW
« Ответ #3 : 19-11-2008 16:20 » 

Всё, решение основного вопроса найдено.
Выглядит более, чем просто:

Код:
   TCHAR szContentDSP[512];
   DWORD dwDSPSize = 512;
   BOOL b=::HttpQueryInfo(m_hHttpFile,
        HTTP_QUERY_CONTENT_DISPOSITION , szContentDSP, &dwDSPSize, NULL);

В строчке szContentDSP получаем заголовок ответа сервера, типа такого: "attachment; filename=%D0%9A%D0%94+%D0%BF%D0%BE+%D0%9B%D0%BE%D1%82%D1%83+6030.rar".

Осталось только понять, как превратить чудо-строку в читабельный текст Улыбаюсь
Есть ли готовое решение, или это нужно перекодировать вручную?
Записан

Ложки нет. See MSDN for details.
Вад
Модератор

ru
Offline Offline
Пол: Мужской

« Ответ #4 : 20-11-2008 09:03 » 

Не знаю насчёт готовых решений, но если вручную - считываешь %NN, записываешь в строку символ с кодом 0xNN, плюсы игнорируются, остальное (чему не предшествует'%') - добавляется в строку как есть. Похоже, так.
Записан
RXL
Технический
Администратор

Offline Offline
Пол: Мужской

WWW
« Ответ #5 : 20-11-2008 10:15 » 

kisilevski, это чудо-строка имеет url-encoded формат (см. RFC):
%XX - шестнадцатеричный код
+ - пробел

По кодам вижу, что это UTF-8.
Записан

... мы преодолеваем эту трудность без синтеза распределенных прототипов. (с) Жуков М.С.
kisilevski
Постоялец

ru
Offline Offline
Пол: Мужской

WWW
« Ответ #6 : 20-11-2008 16:35 » 

Спасибо,
я поступил самым на тот момент простым для меня способом:

Код:
    CString StrFNDSP(szContentDSP); if(StrFNDSP!=""){
     StrFNDSP.Replace("%D0%90", "А");
     StrFNDSP.Replace("%D0%91", "Б");
     StrFNDSP.Replace("%D0%92", "В");
     StrFNDSP.Replace("%D0%93", "Г");
     StrFNDSP.Replace("%D0%94", "Д");
     .....

всё работает Улыбаюсь
Записан

Ложки нет. See MSDN for details.
Алексей++
глобальный и пушистый
Глобальный модератор

ru
Offline Offline
Сообщений: 13


« Ответ #7 : 20-11-2008 16:40 » new

kisilevski, я бы тоже так сделал, кстати Улыбаюсь
Записан

kisilevski
Постоялец

ru
Offline Offline
Пол: Мужской

WWW
« Ответ #8 : 20-11-2008 16:46 » 

Улыбаюсь
Записан

Ложки нет. See MSDN for details.
zubr
Гость
« Ответ #9 : 20-11-2008 17:46 » 

kisilevski, и что весь алфавит русский с латинским переписывал? Это круто. А если бы кодировка была другая?
Я когда бот делал, то URL перекодировал так:
Код:
bool CIEHelper::CharToHex(const TCHAR str[], const int& size, int& sum)
{
  sum=0x0;
  int k=size-1, hx;
  for (int i=0; i<size; i++)
  {
    switch (toupper(str[i]))
    {
      case '0':
        hx=0x0;
        break;
      case '1':
        hx=0x01;
        break;
      case '2':
        hx=0x02;
        break;
      case '3':
        hx=0x03;
        break;
      case '4':
        hx=0x04;
        break;
      case '5':
        hx=0x05;
        break;
      case '6':
        hx=0x06;
        break;
      case '7':
        hx=0x07;
        break;
      case '8':
        hx=0x08;
        break;
      case '9':
        hx=0x09;
        break;
      case 'A':
        hx=0x0A;
        break;
      case 'B':
        hx=0x0B;
        break;
      case 'C':
        hx=0x0C;
        break;
      case 'D':
        hx=0x0D;
        break;
      case 'E':
        hx=0x0E;
        break;
      case 'F':
        hx=0x0F;
        break;
      default:
        return(0);
    }
    hx=hx<<(4*k);
    sum+=hx;
    k--;
  }
  return (1);
};

void CIEHelper::DecodeURL (CString& sUrl)
{
int k = 0;
int sum;
char c;
CString s (_T("xx"));

if (sUrl.GetLength() == 0)
return;

k = sUrl.Find (_T('+'));
while (k != -1)
{
sUrl.Delete (k);
sUrl.Insert (k, _T(' '));
        k = sUrl.Find (_T('+'));
}

    k = sUrl.Find (_T('%'));
    while (k != -1)
{
s.CopyChars (s.GetBuffer(), sUrl.GetBuffer()+k+1, 2);
sUrl.ReleaseBuffer();
sUrl.Delete (k, 3);
        CharToHex (s.GetBuffer(), 2, sum);
        s.ReleaseBuffer();
        c = char(sum);
sUrl.Insert (k, c);
        k = sUrl.Find (_T('%'));
}
};
Ну а чтоб определить кодировку, надо по всей видимости вызывать HttpQueryInfo с флагом HTTP_QUERY_ACCEPT_ENCODING.
Записан
kisilevski
Постоялец

ru
Offline Offline
Пол: Мужской

WWW
« Ответ #10 : 20-11-2008 19:05 » 

Только русский. Мб наивным было с моей стороны предположить, что английские буквы прийдут как есть. Мало пока статистики, тк дома у меня CDMA, вот поработает программа ночь на сервере, тогда буду знать, что с нерусскими буквами, ежели встретятся. Кодировки действительно имеет смысл проверять, хорошая мысль, доберусь и до этого. Спасибо за пример про перекодировку. Полтора года не программировал, теперь вот вспоминаю, что и как.
Записан

Ложки нет. See MSDN for details.
Страниц: [1]   Вверх
  Печать  
 

Powered by SMF 1.1.21 | SMF © 2015, Simple Machines