Страница 2 из 3

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

Добавлено: 03 Март 2015, 10:46
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

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

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

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

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

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

3. Нет ответа на главный вопрос: как вернуть из процедуры адрес строки неизвестной длины ?

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

Добавлено: 03 Март 2015, 11:07
Admin
finsoftrz писал(а):Далее код процедуры загрузка файла порциями, со строкой можно просто вынести определение размера файла в отдельную процедуру.
Друзья. Не забываем портянки в Code заворачивать

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

Добавлено: 03 Март 2015, 11:11
Admin
Короче если мозг не ломать то заведи глобальную очередь c ID закачки и ссылку на буфер.
Развели тут "панимаишь" :)

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

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

Самое интересное, что в сях этот вопрос выеденного яйца не стоит ... ;)

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

Добавлено: 03 Март 2015, 11:29
Игорь Столяров
Yufil писал(а):Хмм. А мои классы CHTTP и CSTR не прокатят?
Подскажите пожалуйста, где можно посмотреть классы, о которых пишет Юрий ?
Поиск по сайту ничего не дал ...

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

Добавлено: 03 Март 2015, 11:34
finsoftrz
Можно передавать в процедуру адрес локальной кьюшки и адрес ее строки (string). Результат из cstring завертываем в кьюшку. А после возврата из процедуры кьюшку развертываем в cstring или string. Завертывание и развертывание оформляем в виде стандартных процедур.
Еще более простой вариант - оформить в виде класса.

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

Добавлено: 03 Март 2015, 12:26
Дед Пахом
Почему не так?

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

sRef  &STRING
  CODE
  sRef = MyProcReturningString()

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

Добавлено: 03 Март 2015, 12:30
Игорь Столяров
Дед Пахом писал(а):Почему не так?

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

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) ! - Здесь ничего нет

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

Добавлено: 03 Март 2015, 12:40
kreator
Наверно, всё же вот так:

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

MyProcReturningString Procedure(),string

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

Добавлено: 03 Март 2015, 12:48
Игорь Столяров
Ну мы же уже об этом говорили. Я не могу принять результат из процедуры в виде строки, потому что не знаю ее длины.
Чему присвоить эту строку ?

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

Добавлено: 03 Март 2015, 12:58
Дед Пахом
да, надо предварительно NEW() для sRef делать. Ну тогда я вижу 2 пути: 1) IDynStr 2) ANY с её разбором через UFO интерфейс.

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

Добавлено: 03 Март 2015, 13:02
Игорь Столяров
Дед Пахом писал(а): да, надо предварительно NEW() для sRef делать.
Я не могу сделать NEW() перед вызовом процедуры, поскольку не знаю размер строки ...
Размер узнаю только внутри процедуры.

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

Добавлено: 03 Март 2015, 13:03
Дед Пахом
хотя вот так работает:

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

  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 

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

Добавлено: 03 Март 2015, 13:43
Yufil
Отправил классы в личку. Отвечу :)