Получить из Procedure() то, сам не знаю что ....

Clarion, Clarion 7

Модератор: Дед Пахом

Правила форума
При написании вопроса или обсуждении проблемы, не забывайте указывать версию Clarion который Вы используете.
А так же пользуйтесь спец. тегами при вставке исходников!!!
Аватара пользователя
finsoftrz
✯ Ветеран ✯
Сообщения: 5239
Зарегистрирован: 06 Ноябрь 2014, 12:48
Благодарил (а): 12 раз
Поблагодарили: 65 раз

Получить из Procedure() то, сам не знаю что ....

Сообщение finsoftrz »

Добрый день, Игорь.

HttpQueryInfo(hUrl,HTTP_QUERY_STATUS_CODE,Buffer,BufferLength,IndexNum) !запросить наличие remote-файла в Buffer

HttpQueryInfo(hUrl,HTTP_QUERY_CONTENT_LENGTH,Buffer,BufferLength,IndexNum) !запросить размер remote-файла в байтах

Далее код процедуры загрузка файла порциями, со строкой можно просто вынести определение размера файла в отдельную процедуру.

Код: Выделить всё

WebLoadFile          FUNCTION (lop:rFileName,lop:lFileName,lop:progr,lop:break) ! Объявление процедуры
FilesOpened          LONG
Loc:Ok               BYTE
Loc:Bytes            LONG
Loc:Status           LONG
hSession    HINTERNET      !ссылка на сессию
hUrl        HINTERNET      !ссылка на remote-файл
MyUrl       CSTRING(255)   !имя remote-файла
LocalFile   CSTRING(255)   !имя локального файла
hLocal      HANDLE         !ссылка на локальный файл

Agent       CSTRING('WebCopy 0.000001b')  !агент

BufferSize      EQUATE(1024)   !значение размера буфера для загрузки файла
Buffer          Group          !буфер для загрузки файла
                  BYTE,DIM(BufferSize)
                End

BufferLength    DWORD    !размер буфера для загрузки файла (как переменная для передачи адреса в функциях api)
IndexNum        DWORD    !номер индекса для функции HttpQueryInfo
FileSize        DWORD    !размер загружаемого файла

Total           LONG   !счетчик загруженных байт
  CODE                                           ! Начало исполняемого кода
      MyUrl = clip(lop:rFileName)      !имя remote-файла
      LocalFile = Clip(lop:lFileName)  !имя локального файла
      loc:ok=0   !установить признак, что файл не загружен
      hSession = InternetOpen(Agent,INTERNET_OPEN_TYPE_PRECONFIG,,,0)  !открыть сессию
      if hSession   !если сессия открыта успешно
        !hUrl = InternetOpenUrl(hSession, myUrl,,0,0,0)   !открыть ссылку на remote-файл
        hUrl = InternetOpenUrl(hSession, myUrl,,0,INTERNET_FLAG_RELOAD,0)   !открыть ссылку на remote-файл
        BufferLength=BufferSize   !установить размер буфера для передачи данных
        HttpQueryInfo(hUrl,HTTP_QUERY_STATUS_CODE,Buffer,BufferLength,IndexNum)  !запросить наличие remote-файла
        Loc:Status=Buffer         !сохранить признак наличия remote-файла
        if lop:progr<>0 and Loc:Status=HTTP_STATUS_OK   !если передана ссылка на прогрессор и remote-файл есть
           BufferLength=BufferSize   !установить размер буфера для передачи данных
           HttpQueryInfo(hUrl,HTTP_QUERY_CONTENT_LENGTH,Buffer,BufferLength,IndexNum)  !запросить размер remote-файла в байтах
           FileSize=Buffer                       !сохранить размер remote-файла
           lop:progr{PROP:RangeLow}=0            !установить диапазон для прогрессора
           lop:progr{PROP:RangeHigh}=FileSize
        .
        BufferLength=0   !обнулить размер буфера для загрузки файла
        if hUrl          !если есть ссылка на remote-файл
          if Loc:Status=HTTP_STATUS_OK    !если remote-файл существует
             hLocal = CreateFile(LocalFile, GENERIC_READ+GENERIC_WRITE, |   !создать ссылку на локальный файл
                              FILE_SHARE_READ + FILE_SHARE_WRITE, ,|
                              CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL,0)
             loc:ok = 1    !установить признак успешной загрузки
             loop          !загрука remote-файла порциями
                Buffer = All('<0>')     !инициализация буфера
                InternetReadFile(hUrl, Buffer, Buffersize, BufferLength)  !чтение порции
                if BufferLength <> 0       !если что-то прочитано
                   Total += BufferLength   !увеличиваем счетчик загруженных байт
                   if lop:progr<>0         !обновляем прогрессор
                      lop:progr{PROP:Progress}=Total
                   .
                   if ~WriteFile(hLocal, Buffer, BufferLength, BufferLength)  !записываем в локальный файл
                      loc:ok = 0  !при ошибке сбрасываем признак успешной загрузки
                      break
                   .
                   if lop:break<>0  !обработка кнопки прерывания процесса
                      do break_r
                      if loc:ok=0
                         break
                      .
                   .
                .
             until BufferLength = 0
             CloseHandle(hLocal)  !закрываем локальный файл
          .
          InternetCloseHandle(hUrl)  !закрываем remote-файл
        .
        InternetCloseHandle(hSession)  !закрываем сессию
      .
  
  RETURN(Loc:Ok)

break_r routine
  0{PROP:TIMER}=1
  Cycles#=0
  accept
     case field()
        of lop:break
          case event()
             of event:accepted
                loc:ok=0
                break
          .
     .
     if event()=event:timer
        Cycles#+=1
        if Cycles#>1
           break
        .
     .
  .
  0{PROP:TIMER}=0
C6/C12, ШВС, tps/btrieve.
Аватара пользователя
Игорь Столяров
Ветеран движения
Сообщения: 8031
Зарегистрирован: 07 Июль 2005, 10:19
Откуда: г. Ростов-на-ДоМу
Благодарил (а): 28 раз
Поблагодарили: 96 раз

Получить из Procedure() то, сам не знаю что ....

Сообщение Игорь Столяров »

finsoftrz писал(а): Далее код процедуры загрузка файла порциями
Спасибо, но к сожалению - нет, не подходит ........

1. Это загрузка информации в файл. Если не заморачиваться с индикатором загрузки, то все это делается
одной командой API WinINet: If URLDownloadToFile(0,sSourceUrl,sLocalFile,BINDF_GETNEWESTVERSION,NULL) = 0.

2. Нельзя разделять запросы на получение размера информации и непосредственно получение самой информации.
В общем случае, например если мы запрашиваем информацию по динамическому PHP скрипту,
то ответ на два отдельных запроса по одной и той же ссылке может быть разным.

Здесь хорошо работает самый простой вариант загрузки с InternetReadFile() и динамическим наращиванием длины строки.

3. Нет ответа на главный вопрос: как вернуть из процедуры адрес строки неизвестной длины ?
Последний раз редактировалось Игорь Столяров 03 Март 2015, 11:23, всего редактировалось 3 раза.
Make Clarion Great Again ! 😎
Аватара пользователя
Admin
Администратор
Сообщения: 4010
Зарегистрирован: 05 Июль 2005, 15:59
Откуда: Хабаровск
Благодарил (а): 53 раза
Поблагодарили: 33 раза
Контактная информация:

Получить из Procedure() то, сам не знаю что ....

Сообщение Admin »

finsoftrz писал(а):Далее код процедуры загрузка файла порциями, со строкой можно просто вынести определение размера файла в отдельную процедуру.
Друзья. Не забываем портянки в Code заворачивать
Рай совершает ошибки ничуть не реже чем ад. Просто у него хорошая пресса
Аватара пользователя
Admin
Администратор
Сообщения: 4010
Зарегистрирован: 05 Июль 2005, 15:59
Откуда: Хабаровск
Благодарил (а): 53 раза
Поблагодарили: 33 раза
Контактная информация:

Получить из Procedure() то, сам не знаю что ....

Сообщение Admin »

Короче если мозг не ломать то заведи глобальную очередь c ID закачки и ссылку на буфер.
Развели тут "панимаишь" :)
Рай совершает ошибки ничуть не реже чем ад. Просто у него хорошая пресса
Аватара пользователя
Игорь Столяров
Ветеран движения
Сообщения: 8031
Зарегистрирован: 07 Июль 2005, 10:19
Откуда: г. Ростов-на-ДоМу
Благодарил (а): 28 раз
Поблагодарили: 96 раз

Получить из Procedure() то, сам не знаю что ....

Сообщение Игорь Столяров »

Admin писал(а): Короче если мозг не ломать то заведи глобальную очередь c ID закачки и ссылку на буфер.Развели тут "панимаишь"
Да, это решает вопрос - я об этом писал ниже.
Но сразу наступаем на другие грабли Clarion: работа с глобальными данными Thread в Multi DLL приложении.

Самое интересное, что в сях этот вопрос выеденного яйца не стоит ... ;)
Make Clarion Great Again ! 😎
Аватара пользователя
Игорь Столяров
Ветеран движения
Сообщения: 8031
Зарегистрирован: 07 Июль 2005, 10:19
Откуда: г. Ростов-на-ДоМу
Благодарил (а): 28 раз
Поблагодарили: 96 раз

Получить из Procedure() то, сам не знаю что ....

Сообщение Игорь Столяров »

Yufil писал(а):Хмм. А мои классы CHTTP и CSTR не прокатят?
Подскажите пожалуйста, где можно посмотреть классы, о которых пишет Юрий ?
Поиск по сайту ничего не дал ...
Make Clarion Great Again ! 😎
Аватара пользователя
finsoftrz
✯ Ветеран ✯
Сообщения: 5239
Зарегистрирован: 06 Ноябрь 2014, 12:48
Благодарил (а): 12 раз
Поблагодарили: 65 раз

Получить из Procedure() то, сам не знаю что ....

Сообщение finsoftrz »

Можно передавать в процедуру адрес локальной кьюшки и адрес ее строки (string). Результат из cstring завертываем в кьюшку. А после возврата из процедуры кьюшку развертываем в cstring или string. Завертывание и развертывание оформляем в виде стандартных процедур.
Еще более простой вариант - оформить в виде класса.
C6/C12, ШВС, tps/btrieve.
Аватара пользователя
Дед Пахом
Старичок
Сообщения: 3289
Зарегистрирован: 07 Июль 2005, 16:51
Откуда: Москва, Россия
Благодарил (а): 15 раз
Поблагодарили: 49 раз
Контактная информация:

Получить из Procedure() то, сам не знаю что ....

Сообщение Дед Пахом »

Почему не так?

Код: Выделить всё

sRef  &STRING
  CODE
  sRef = MyProcReturningString()
С уважением, ДП
Аватара пользователя
Игорь Столяров
Ветеран движения
Сообщения: 8031
Зарегистрирован: 07 Июль 2005, 10:19
Откуда: г. Ростов-на-ДоМу
Благодарил (а): 28 раз
Поблагодарили: 96 раз

Получить из Procedure() то, сам не знаю что ....

Сообщение Игорь Столяров »

Дед Пахом писал(а):Почему не так?

Код: Выделить всё

sRef  &STRING
  CODE
  sRef = MyProcReturningString()
Первое что попробовал. Ошибки нет, но и результата тоже. :(

Код: Выделить всё

MyProcReturningString Procedure(),*string
  
Loc:Str &String
  
   Code
   
   Loc:Str &= New(String(30))   
   Loc:Str = 'Привет !'
   Return(Loc:Str)
   
   ! --------------------
   
   Code

sRef  &STRING
  CODE
  sRef = MyProcReturningString()
  Message(sRef) ! - Здесь ничего нет
Make Clarion Great Again ! 😎
kreator
✯ Ветеран ✯
Сообщения: 5161
Зарегистрирован: 28 Май 2009, 15:54
Откуда: Москва
Благодарил (а): 11 раз
Поблагодарили: 26 раз

Получить из Procedure() то, сам не знаю что ....

Сообщение kreator »

Наверно, всё же вот так:

Код: Выделить всё

MyProcReturningString Procedure(),string
We are hard at work… for you. :)
Аватара пользователя
Игорь Столяров
Ветеран движения
Сообщения: 8031
Зарегистрирован: 07 Июль 2005, 10:19
Откуда: г. Ростов-на-ДоМу
Благодарил (а): 28 раз
Поблагодарили: 96 раз

Получить из Procedure() то, сам не знаю что ....

Сообщение Игорь Столяров »

Ну мы же уже об этом говорили. Я не могу принять результат из процедуры в виде строки, потому что не знаю ее длины.
Чему присвоить эту строку ?
Make Clarion Great Again ! 😎
Аватара пользователя
Дед Пахом
Старичок
Сообщения: 3289
Зарегистрирован: 07 Июль 2005, 16:51
Откуда: Москва, Россия
Благодарил (а): 15 раз
Поблагодарили: 49 раз
Контактная информация:

Получить из Procedure() то, сам не знаю что ....

Сообщение Дед Пахом »

да, надо предварительно NEW() для sRef делать. Ну тогда я вижу 2 пути: 1) IDynStr 2) ANY с её разбором через UFO интерфейс.
С уважением, ДП
Аватара пользователя
Игорь Столяров
Ветеран движения
Сообщения: 8031
Зарегистрирован: 07 Июль 2005, 10:19
Откуда: г. Ростов-на-ДоМу
Благодарил (а): 28 раз
Поблагодарили: 96 раз

Получить из Procedure() то, сам не знаю что ....

Сообщение Игорь Столяров »

Дед Пахом писал(а): да, надо предварительно NEW() для sRef делать.
Я не могу сделать NEW() перед вызовом процедуры, поскольку не знаю размер строки ...
Размер узнаю только внутри процедуры.
Make Clarion Great Again ! 😎
Аватара пользователя
Дед Пахом
Старичок
Сообщения: 3289
Зарегистрирован: 07 Июль 2005, 16:51
Откуда: Москва, Россия
Благодарил (а): 15 раз
Поблагодарили: 49 раз
Контактная информация:

Получить из Procedure() то, сам не знаю что ....

Сообщение Дед Пахом »

хотя вот так работает:

Код: Выделить всё

  PROGRAM

  MAP
    MyProcReturningString(), *STRING
  END

sRef                          &STRING

  CODE
  sRef &= MyProcReturningString()
  MESSAGE(sRef)
  
MyProcReturningString         PROCEDURE()
str                             &STRING
  CODE
  str &= NEW STRING(100)
  str = 'MyProcReturningString'
  RETURN str 
С уважением, ДП
Yufil
Ветеран движения
Сообщения: 1277
Зарегистрирован: 16 Май 2006, 14:34
Контактная информация:

Получить из Procedure() то, сам не знаю что ....

Сообщение Yufil »

Отправил классы в личку. Отвечу :)
Ответить