国产 无码 综合区,色欲AV无码国产永久播放,无码天堂亚洲国产AV,国产日韩欧美女同一区二区

lazarus、delphi文件Http下載斷點(diǎn)續(xù)傳的實(shí)現(xiàn)

這篇具有很好參考價(jià)值的文章主要介紹了lazarus、delphi文件Http下載斷點(diǎn)續(xù)傳的實(shí)現(xiàn)。希望對大家有所幫助。如果存在錯誤或未考慮完全的地方,請大家不吝賜教,您也可以點(diǎn)擊"舉報(bào)違法"按鈕提交疑問。

下載大文件時,斷點(diǎn)續(xù)傳是很有必要的,特別是網(wǎng)速度慢且不穩(wěn)定的情況下,很難保證不出意外,一旦意外中斷,又要從頭下載,會很讓人抓狂。斷點(diǎn)續(xù)傳就能很好解決意外中斷情況,再次下載時不需要從頭下載,從上次中斷處繼續(xù)下載即可,這樣下載幾G或十幾G大小的一個文件都沒問題。本文介紹利用miniframe開源Web框架分別在lazarus、delphi下實(shí)現(xiàn)文件HTTP下載斷點(diǎn)續(xù)傳的功能。

本文Demo還實(shí)現(xiàn)了批量下載文件,同步服務(wù)器上的文件到客戶端的功能。文件斷點(diǎn)續(xù)傳原理:分塊下載,下載后客戶端逐一合并,同時保存已下載的位置,當(dāng)意外中斷再次下載時從保存的位置開始下載即可。這其中還要保證,中斷后再次下載時服務(wù)器上相應(yīng)的文件如果更新了,還得重新下載,不然下載到的文件是錯了。說明:以下代碼lazarus或delphi環(huán)境下都能使用。全部源碼及Demo請到miniframe開源web框架下載:?https://www.wyeditor.com/miniframe/或https://github.com/dajingshan/miniframe。

服務(wù)器端代碼

文件下載斷點(diǎn)續(xù)傳服務(wù)器端很簡單,只要提供客戶端要求下載的開始位置和指定大小的塊即可。

以下是服務(wù)器獲取文件信息和下載一個文件一塊的代碼:

  1. <%@//Script頭、過程和函數(shù)定義
  2. program codes;
  3. %>
  4. ?
  5. <%!//聲明變量
  6. var
  7. i,lp: integer;
  8. FileName, RelativePath, FromPath, ErrStr: string;
  9. json: TminiJson;
  10. FS: TFileStream;
  11. function GetOneDirFileInfo(Json: TminiJson; Path: string): string;
  12. var
  13. Status: Integer;
  14. SearchRec: TSearchRec;
  15. json_sub: TminiJson;
  16. begin
  17. Path := PathWithSlash(Path);
  18. SearchRec := TSearchRec.Create;
  19. Status := FindFirst(Path + '*.*', faAnyFile, SearchRec);
  20. try
  21. while Status = 0 do
  22. begin
  23. if SearchRec.Attr and faDirectory = faDirectory then
  24. begin
  25. if (SearchRec.name <> '.') and (SearchRec.name <> '..') then
  26. GetOneDirFileInfo(Json, Path + SearchRec.Name + '\');
  27. end else
  28. begin
  29. FileName := Path + SearchRec.Name;
  30. try
  31. if FileExists(FileName) then
  32. begin
  33. json_sub := Pub.GetJson;
  34. json_sub.SO; //初始化 或 json.Init;
  35. json_sub.S['filename'] := SearchRec.name;
  36. json_sub.S['RelativePath'] := GetDeliBack(FileName, FromPath);
  37. json_sub.S['FileTime'] := FileGetFileTimeA(FileName);
  38. json_sub.I['size'] := SearchRec.Size;
  39. json.A['list'] := json_sub;
  40. end;
  41. except
  42. //print(ExceptionParam)
  43. end;//}
  44. end;
  45. Status := FindNext(SearchRec);
  46. end;
  47. finally
  48. FindClose(SearchRec);
  49. SearchRec.Free;
  50. end;//*)
  51. end;
  52. %>
  53. <%
  54. begin
  55. FromPath := 'D:\code\delphi\sign\發(fā)行文件'; //下載源目錄
  56. json := Pub.GetJson; //這樣創(chuàng)建json對象不需要自己釋放,系統(tǒng)自動管理
  57. json.SO; //初始化 或 json.Init;
  58. // 驗(yàn)證是否登錄代碼
  59. {if not Request.IsLogin('Logined') then
  60. begin
  61. json.S['retcode'] := '300';
  62. json.S['retmsg'] := '你還沒有登錄(no logined)!';
  63. print(json.AsJson(true));
  64. exit;
  65. end;//}
  66. json.S['retcode'] := '200';
  67. json.S['retmsg'] := '成功!';
  68. if Request.V('opr') = '1' then
  69. begin //獲取服務(wù)上指定目錄的文件信息
  70. GetOneDirFileInfo(Json, FromPath);
  71. end else
  72. if Request.V('opr') = '2' then
  73. begin //下載指定文件給定大小的塊
  74. FromPath := PathWithSlash(FromPath);
  75. RelativePath := Request.V('fn');
  76. FileName := FromPath + RelativePath;
  77. Fs := Pub.GetFS(FileName, fmShareDenyWrite, ErrStr);
  78. if trim(ErrStr) <> '' then
  79. begin
  80. json.S['retcode'] := '300';
  81. json.S['retmsg'] := ErrStr;
  82. print(json.AsJson(true));
  83. exit;
  84. end;
  85. Fs.Position := StrToInt(Request.V('pos'));
  86. Response.ContentStream := TMemoryStream.Create; //注意不能用 Pub.GetMs,這是因?yàn)镻ub.GetMs創(chuàng)建的對象在動態(tài)腳本運(yùn)行完就釋放了
  87. Response.ContentStream.CopyFrom(Fs, StrToInt(Request.V('size')));
  88. //返回流數(shù)據(jù)
  89. Response.ContentType := 'application/octet-stream';
  90. end;
  91. print(json.AsJson(true));
  92. end;
  93. %>

客戶端代碼

客戶端收到塊后,進(jìn)行合并。全部塊下載完成后,還要把新下載的文件的文件修改為與服務(wù)器上的文件相同。以下是客戶端實(shí)現(xiàn)的主代碼:

  1. procedure TMainForm.UpgradeBlock_Run(var ThreadRetInfo: TThreadRetInfo);
  2. const
  3. BlockSize = 1024*1024; //1M
  4. var
  5. HTML, ToPath, RelativePath, FN, Tmp, TmpFileName, FailFiles, SuccFiles, Newfn, TmpToPath: string;
  6. Json, TmpJson: TminiJson;
  7. lp, I, Number, HadUpSize, AllSize, AllBlockCount, MySize, MyNumber: Int64;
  8. Flag: boolean;
  9. SL, SLDate, SLSize, SLTmp: TStringlist;
  10. MS: TMemoryStream;
  11. Fs: TFileStream;
  12. procedure HintMsg(Msg: string);
  13. begin
  14. FMyMsg := Msg; // '正在獲取文件列表。。。';
  15. ThreadRetInfo.Self.Synchronize(ThreadRetInfo.Self, MyUpdateface); //為什么不直接用匿名,因?yàn)閘az不支持
  16. end;
  17. begin
  18. ToPath := 'D:\superhtml'; //如果是當(dāng)前程序更新 ExtractFilePath(ParamStr(0))
  19. ?
  20. ThreadRetInfo.Ok := false;
  21. ?
  22. HintMsg('正在獲取文件列表。。。');
  23. if not HttpPost('/接口/同步文件到客戶端.html?opr=1',
  24. '', ThreadRetInfo.ErrStr, ThreadRetInfo.HTML) then exit;
  25. if Pos('{', ThreadRetInfo.HTML) <> 1 then
  26. begin
  27. ThreadRetInfo.ErrStr :='請先檢查腳本源碼是否配置正確!';
  28. exit;
  29. end;
  30. ToPath := Pub.PathWithSlash(ToPath);
  31. ?
  32. Json := TminiJson.Create;
  33. SL := TStringlist.Create;
  34. SLDate := TStringlist.Create;
  35. SLSize := TStringlist.Create;
  36. SLTmp := TStringlist.Create;
  37. try
  38. Json.LoadFromString(ThreadRetInfo.HTML);
  39. if json.S['retcode'] = '200' then
  40. begin
  41. TmpJson := json.A['list'];
  42. for lp := 0 to TmpJson.length - 1 do
  43. begin
  44. HintMsg(lp.ToString + '/' + TmpJson.length.ToString + '正在檢查文件:' + RelativePath);
  45. RelativePath := TmpJson[lp].S['RelativePath'];
  46. if trim(RelativePath) = '' then Continue;
  47. Flag := FileExists(ToPath + RelativePath);
  48. if Flag then
  49. begin
  50. if (PubFile.FileGetFileTimeA(ToPath + RelativePath) = TmpJson[lp].S['FileTime']) and
  51. (PubFile.FileGetFileSize(ToPath + RelativePath) = TmpJson[lp].I['Size']) then
  52. else
  53. Flag := false;
  54. end;
  55. if not Flag then //此文件需要更新
  56. begin
  57. SL.Add(RelativePath);
  58. SLDate.Add(TmpJson[lp].S['FileTime']);
  59. SLSize.Add(TmpJson[lp].S['Size']);
  60. end;
  61. end;
  62. ?
  63. //開始下載
  64. FailFiles := '';
  65. SuccFiles := '';
  66. HintMsg('需要更新的文件共有' + IntToStr(SL.Count) + '個。。。');
  67. for lp := 0 to SL.Count - 1 do
  68. begin
  69. RelativePath := SL[lp];
  70. if RelativePath[1] = '\' then RelativePath := Copy(RelativePath, 2, MaxInt);
  71. FN := ToPath + RelativePath;
  72. ?
  73. //先計(jì)算要分幾個包,以處理進(jìn)度
  74. Number := 0;
  75. HadUpSize := 0;
  76. AllSize := StrToInt64(SLSize[lp]);
  77. AllBlockCount := 0;
  78. while true do
  79. begin
  80. AllBlockCount := AllBlockCount + 1;
  81. if AllSize - HadUpSize >= BlockSize then
  82. MySize := BlockSize
  83. else
  84. MySize := AllSize - HadUpSize;
  85. HadUpSize := HadUpSize + MySize;
  86. if HadUpSize >= AllSize then
  87. break;
  88. end;
  89. ?
  90. //開始分塊下載
  91. Number := 0;
  92. HadUpSize := 0;
  93. //AllSize := Fs.Size;
  94. //TmpToPath := PubFile.FileGetTemporaryPath;
  95. Newfn := '@_' + PubPWD.GetMd5(SLDate[lp] + SLSize[lp]) + ExtractFileName(FN); //Pub.GetClientUniqueCode;
  96. ?
  97. if FileExists(ToPath + Newfn) and (FileExists(FN)) then
  98. begin
  99. SLTmp.LoadFromFile(ToPath + Newfn);
  100. MyNumber := StrToInt64(trim(SLTmp.Text));
  101. Fs := TFileStream.Create(FN, fmOpenWrite);
  102. end else
  103. begin
  104. MyNumber := 0;
  105. Fs := TFileStream.Create(FN, fmCreate);
  106. end;
  107. try
  108. while true do
  109. begin
  110. HintMsg('正在下載文件[' + Pub.GetDeliBack(RelativePath, '@@') + ']第[' + IntToStr(Number + 1) + '/' + IntToStr(AllBlockCount) + ']個包。。。');
  111. ?
  112. if AllSize - HadUpSize >= BlockSize then
  113. MySize := BlockSize
  114. else
  115. MySize := AllSize - HadUpSize;
  116. Number := Number + 1;
  117. if (MyNumber = 0) or (Number >= MyNumber) or (HadUpSize + MySize >= AllSize) then
  118. begin
  119. for I := 1 to 2 do //意外出錯重試一次
  120. begin
  121. if not HttpPost('/接口/同步文件到客戶端.html?opr=2fn=' + UrlEncode(RelativePath) +
  122. 'pos=' + UrlEncode(IntToStr(HadUpSize)) + 'size=' + UrlEncode(IntToStr(MySize)),
  123. '', ThreadRetInfo.ErrStr, ThreadRetInfo.HTML, MS) then
  124. begin
  125. if I = 2 then
  126. begin
  127. ThreadRetInfo.ErrStr := Json.S['retmsg'];
  128. exit;
  129. end else
  130. Continue;
  131. end;
  132. if Pos('{', ThreadRetInfo.HTML) < 1 then
  133. begin
  134. if I = 2 then
  135. begin
  136. ThreadRetInfo.ErrStr := Json.S['retmsg'];
  137. exit;
  138. end else
  139. Continue;
  140. end;
  141. ?
  142. Json.LoadFromString(ThreadRetInfo.HTML);
  143. if json.S['retcode'] <> '200' then
  144. begin
  145. if I = 2 then
  146. begin
  147. ThreadRetInfo.ErrStr := Json.S['retmsg'];
  148. exit;
  149. end else
  150. Continue;
  151. end;
  152. break;
  153. end;
  154. ?
  155. if MS = nil then
  156. begin
  157. ThreadRetInfo.ErrStr := '沒能下載到文件[' + RelativePath + ']!' + json.S['retmsg'];
  158. exit;
  159. end else
  160. begin
  161. Fs.Position := HadUpSize;
  162. MS.Position := 0;
  163. Fs.CopyFrom(MS, MS.Size);
  164. MS.Free;
  165. MS := nil;
  166. SLTmp.Text := Number.ToString;
  167. try
  168. SLTmp.SaveToFile(ToPath + Newfn);
  169. except
  170. end;
  171. end;
  172. end;
  173. HadUpSize := HadUpSize + MySize;
  174. ?
  175. if HadUpSize >= AllSize then
  176. begin //全部下載完成
  177. Fs.Free;
  178. Fs := nil;
  179. Sleep(10);
  180. PubFile.FileChangeFileDate(Fn, SLDate[lp]);
  181. DeleteFile(ToPath + Newfn);
  182. SuccFiles := SuccFiles + #13#10 + RelativePath;
  183. break;
  184. end;
  185. end;
  186. finally
  187. if Fs <> nil then
  188. Fs.Free;
  189. end;
  190. end;
  191. ThreadRetInfo.HTML := '';
  192. if trim(SuccFiles) <> '' then
  193. ThreadRetInfo.HTML := '本次更新了以下文件:'#13#10 + SuccFiles;
  194. //if trim(FailFiles) <> '' then
  195. //ThreadRetInfo.HTML := trim(ThreadRetInfo.HTML + #13#10'以下文件更新失?。?span id="n5n3t3z" class="str">'#13#10 + FailFiles);
  196. end;
  197. finally
  198. SLTmp.Free;
  199. SLSize.Free;
  200. SL.Free;
  201. Json.Free;
  202. SLDate.Free;
  203. end;
  204. ThreadRetInfo.Ok := true;
  205. end;
  206. ?

以下是Demo運(yùn)行界面:文章來源地址http://www.zghlxwxcb.cn/news/detail-642106.html

金蜘蛛網(wǎng)頁設(shè)計(jì)器
?2020-2023版權(quán)所有
?

到了這里,關(guān)于lazarus、delphi文件Http下載斷點(diǎn)續(xù)傳的實(shí)現(xiàn)的文章就介紹完了。如果您還想了解更多內(nèi)容,請?jiān)谟疑辖撬阉鱐OY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!

本文來自互聯(lián)網(wǎng)用戶投稿,該文觀點(diǎn)僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務(wù),不擁有所有權(quán),不承擔(dān)相關(guān)法律責(zé)任。如若轉(zhuǎn)載,請注明出處: 如若內(nèi)容造成侵權(quán)/違法違規(guī)/事實(shí)不符,請點(diǎn)擊違法舉報(bào)進(jìn)行投訴反饋,一經(jīng)查實(shí),立即刪除!

領(lǐng)支付寶紅包贊助服務(wù)器費(fèi)用

相關(guān)文章

  • Spring-Boot實(shí)現(xiàn)HTTP大文件斷點(diǎn)續(xù)傳分片下載-大視頻分段漸進(jìn)式播放

    服務(wù)端如何將一個大視頻文件做切分,分段響應(yīng)給客戶端,讓瀏覽器可以漸進(jìn)式地播放。 Spring Boot實(shí)現(xiàn)HTTP分片下載斷點(diǎn)續(xù)傳,從而實(shí)現(xiàn)H5頁面的大視頻播放問題,實(shí)現(xiàn)漸進(jìn)式播放,每次只播放需要播放的內(nèi)容就可以了,不需要加載整個文件到內(nèi)存中。 文件的斷點(diǎn)續(xù)傳、文件多

    2024年02月11日
    瀏覽(31)
  • 基于vue-simple-uploader封裝文件分片上傳、秒傳及斷點(diǎn)續(xù)傳的全局上傳

    基于vue-simple-uploader封裝文件分片上傳、秒傳及斷點(diǎn)續(xù)傳的全局上傳

    1. 前言 文件上傳 小文件(圖片、文檔、視頻)上傳可以直接使用很多ui框架封裝的上傳組件,或者自己寫一個input 上傳,利用FormData 對象提交文件數(shù)據(jù),后端使用spring提供的MultipartFile進(jìn)行文件的接收,然后寫入即可。但是對于比較大的文件,比如上傳2G左右的文件(http上傳

    2024年02月06日
    瀏覽(22)
  • 【前端面試】中大文件上傳/下載:中等文件代理服務(wù)器放行+大文件切片傳輸+并發(fā)請求+localstorage實(shí)現(xiàn)斷點(diǎn)續(xù)傳

    【前端面試】中大文件上傳/下載:中等文件代理服務(wù)器放行+大文件切片傳輸+并發(fā)請求+localstorage實(shí)現(xiàn)斷點(diǎn)續(xù)傳

    目錄 切片上傳~spark-md5 原理:流式計(jì)算+分塊處理 文件標(biāo)識spark-md5:A-B A.切片哈希值合并 B.首尾切片+其他切片前中后各取2M 計(jì)算hash:A-B(參考React的Fiber架構(gòu)) A.線程:web-worker B.空閑:requestIdleCallback 異步并發(fā)控制:A-B(參考http2的多路復(fù)用) A.promise.allSettled() B.并發(fā)數(shù)max=

    2024年02月12日
    瀏覽(30)
  • 斷點(diǎn)續(xù)傳下載:深入理解 HTTP Header 中的 Range 和 Content-Range 參數(shù)

    [外鏈圖片轉(zhuǎn)存失敗,源站可能有防盜鏈機(jī)制,建議將圖片保存下來直接上傳(img-bAhEY9hc-1687309020087)(https://example.com/resume-download-image)] 在進(jìn)行文件下載時,我們經(jīng)常會遇到網(wǎng)絡(luò)不穩(wěn)定或其他中斷情況。為了提供更好的用戶體驗(yàn)和節(jié)省帶寬資源,斷點(diǎn)續(xù)傳技術(shù)應(yīng)運(yùn)而生。HTTP 協(xié)議通過

    2024年02月10日
    瀏覽(22)
  • 斷點(diǎn)續(xù)傳下載引出的http header的range和content-range參數(shù)

    最近同事在做安卓的斷點(diǎn)續(xù)傳下載,然后遇到了在請求頭添加RANGE參數(shù)設(shè)置時: 網(wǎng)絡(luò)上找的資料都是設(shè)置contentLength,同時測試后,發(fā)現(xiàn)中間下載無法返回206成功,最終發(fā)現(xiàn)是需要end參數(shù)-1.此處稍微記錄一下,主要了解一下相關(guān)的知識。 HTTP1.1 協(xié)議(RFC2616)開始支持獲取文件的

    2024年02月10日
    瀏覽(26)
  • Java實(shí)現(xiàn)文件斷點(diǎn)續(xù)傳

    文件斷點(diǎn)續(xù)傳代碼 測試代碼

    2024年03月09日
    瀏覽(27)
  • 舊版Xcode文件較大導(dǎo)致下載總是失敗但又不能斷點(diǎn)續(xù)傳重新開始的解決方法

    舊版Xcode文件較大導(dǎo)致下載總是失敗但又不能斷點(diǎn)續(xù)傳重新開始的解決方法

    舊版mac下載舊版Xcode時需要進(jìn)入https://developer.apple.com/download/all/?q=xcode下載,但是下載這些文件需要登錄。登錄后下載中途很容易失敗,失敗后又必須重新下載。 下載這里面的內(nèi)容都需要登錄,經(jīng)過分析需提供其cookie,我這里使用的是motrix。需要下載時先通過搜索找到你要下載

    2024年02月15日
    瀏覽(27)
  • Minio大文件分片上傳、斷點(diǎn)續(xù)傳實(shí)現(xiàn)

    Minio大文件分片上傳、斷點(diǎn)續(xù)傳實(shí)現(xiàn)

    使用minio api實(shí)現(xiàn)分片上傳及斷點(diǎn)續(xù)傳功能。 前端準(zhǔn)備:獲取大文件的MD5值,將文件分片,5M為一分片,排好順序,并按順序命名(1,2,3這種后面比較好合并) 在上傳分片階段,前端有上傳進(jìn)度條 1、檢驗(yàn)文件MD5值 1.1 redis中查看MD5是否存在 1.2 判斷臨時文件夾是否存在 boolean d

    2024年02月09日
    瀏覽(27)
  • 大文件切片上傳+斷點(diǎn)續(xù)傳解決方案-前后端實(shí)現(xiàn)(附源碼)

    上傳文件大家應(yīng)該都做過,前端直接把file文件傳給后端就ok了,但是大文件這樣傳就會造成頁面假死,體驗(yàn)極差。如果遇到網(wǎng)絡(luò)不穩(wěn)定的時候,中途上傳失敗的話,又要從頭開始傳,本來文件就大,還慢。所以今天我們用一種新方法-切片上傳+斷點(diǎn)續(xù)傳 頁面上很簡單,我就放

    2024年02月09日
    瀏覽(32)
  • 【SpringBoot整合系列】SpringBoot 實(shí)現(xiàn)大文件分片上傳、斷點(diǎn)續(xù)傳及秒傳

    【SpringBoot整合系列】SpringBoot 實(shí)現(xiàn)大文件分片上傳、斷點(diǎn)續(xù)傳及秒傳

    小文件(圖片、文檔、視頻)上傳可以直接使用很多ui框架封裝的上傳組件,或者自己寫一個input 上傳,利用FormData 對象提交文件數(shù)據(jù),后端使用spring提供的MultipartFile進(jìn)行文件的接收,然后寫入即可。 但是對于比較大的文件,比如上傳2G左右的文件(http上傳),就需要將文件

    2024年04月16日
    瀏覽(37)

覺得文章有用就打賞一下文章作者

支付寶掃一掃打賞

博客贊助

微信掃一掃打賞

請作者喝杯咖啡吧~博客贊助

支付寶掃一掃領(lǐng)取紅包,優(yōu)惠每天領(lǐng)

二維碼1

領(lǐng)取紅包

二維碼2

領(lǐng)紅包