分享web开发知识

注册/登录|最近发布|今日推荐

主页 IT知识网页技术软件开发前端开发代码编程运营维护技术分享教程案例
当前位置:首页 > 运营维护

使用kbmmw 的REST 服务实现上传大文件

发布时间:2023-09-18 22:47责任编辑:蔡小小关键词:暂无标签

我们在使用kbmmw的REST 服务时,经常会下载和上传大文件。例如100M以上的。kbmmw的rest服务中

提供标准的文件下载,上传功能,基本上就是打开文件,发送,接收,没有做特殊处理。这些对于文件比较小的

时候,问题不大,但是如果文件比较大,就会占用大量的服务器内存,导致服务器出现问题或者不响应。

为了解决这个问题,我们需要对文件上传、下载做特殊处理。以便节省服务器端的内存。

由于下载大文件有其他的一些方法,例如可以单独建立一个iis,apache,nginx等,或者可以利用httpsys 的静态文件

下载功能(以后有机会的话,我来讲一下)。

今天来实现以下大文件上传的方法,(当然,你也可以参照这个做一个大文件下载的功能)。主要思路是按照kbmmw 本身的

文件服务原理,把大文件切成小块,然后再上传。

首先在服务器端做一个上传文件服务。

 [kbmMW_Rest(‘method:post, path:uploadfile,anonymousResult:False,freeResult:true‘)] ?????[kbmMW_Method] ?????function uploadfile( ?????????[kbmMW_Rest(‘value: "$filepath", required: true‘)] const filepath:string; ?????????[kbmMW_Rest(‘value: "$token", required: true‘)] const token:string; ?????????[kbmMW_Rest(‘value: "$position", required: true‘)] const position:string; ?????????[kbmMW_Rest(‘value: "$size", required: true‘)] const size:string; ?????????[kbmMW_Rest(‘value: "$final", required: true‘)] const ?final:string):string;
function TkbmMWCustomHTTPSmartService1.uploadfile(const filepath, token, ?position, size, final: string): string;const ??UPLOADPATH=‘d:\upload\‘; ??MaxFileSize=200*1024*1024; //上传文件大小不能超过200M ??errmsg=‘ERROR:‘;var ??fa:TkbmMWFileAccessPermissions; ??h:THandle; ??FileToken:integer; ??path:string; ??p:Pbyte; ?// l:integer; ??ref:TkbmMWFileReference; ??fofs,sz,newofs,maxsize:int64; ??bGC:boolean; ??FFinal:boolean;begin ??if not Assigned(FilePool) then ?????begin ???????result:=errmsg+‘No FilePool defined.‘; ???????exit; ?????end; ??if filepath=‘‘ then ???begin ???????result:=errmsg+‘No filepath.‘; ???????exit; ?????end; ??if token=‘‘ then ??????begin ???????result:=errmsg+‘No token.‘; ???????exit; ?????end; ??if position=‘‘ then ??????begin ???????result:=errmsg+‘No position.‘; ???????exit; ?????end; ???fofs:=strtoint(position); ???if size=‘‘ then ???begin ???????result:=errmsg+‘No size.‘; ???????exit; ?????end; ??sz:=strtoint(size); ?if sz>10*1024*1024 then ????begin ????????result:=errmsg+‘blocksize too big.‘; ???????exit; ????end; ???if ((final<>‘0‘) and (final<>‘1‘)) then ???begin ???????result:=errmsg+‘final error.‘; ???????exit; ???end; ?if final=‘0‘ then ???ffinal:=False ??else ??ffinal:=True; ????FileToken:=strtoint(token); ????path:= UPLOADPATH+filepath; ???// Determine file mode. ????if FileToken=-1 then ????begin ?????????// Check if file already exists and not overwrite permissions. ?????????if FileExists(path) and (not (mwfapOverwrite in fa)) then ??????????begin ????????????result:=errmsg+‘Permission denied‘; ????????????exit; ??????????end; ????end; ?????// Append block to file. ????bGC:=false; ????ref:=FilePool.Access(path,mwfamOpenWrite,FileToken,h); ????try ???????ref.DuringUpdate:=true; ???????maxsize:=MaxFileSize; ???????if FOfs>=0 then ???????begin ????????????if (maxsize>0) and (FOfs+sz>maxSize) then ?????????????begin ???????????????result:=errmsg+‘File too big‘; ???????????????exit; ?????????????end; ????????????if FileSeek(h,FOfs,0)<0 then ????????????begin ???????????????result:=errmsg+‘Cant position in file‘; ???????????????exit; ????????????end; ???????end ???????else ???????begin ????????????newofs:=FileSeek(h,0,2); ????????????if newofs<0 then ?????????????begin ???????????????result:=errmsg+‘Cant append to file‘; ???????????????exit; ?????????????end; ????????????if (maxsize>0) and (newofs+sz>maxSize) then ?????????????begin ???????????????result:=errmsg+‘File too big‘; ???????????????exit; ?????????????end; ???????end; ???????// Write requeststream to file. ???????p:=RequestStream.Memory; ???????if FileWrite(h,p^,sz)<>sz then ???????begin ????????????ref.Invalidate; ???????????????????????????ref.DeleteOnGC:=true; ????????????bGC:=true; ????????????????????result:=errmsg+‘写文件失败.‘; ??????????exit; ???????end; ????finally ??????if FFinal then ?????????ref.DuringUpdate:=false; ???????FilePool.ReleaseAccess(ref,h,FFinal); ???????if bGC then ??????????FilePool.GarbageCollect; ????end; ????Result:=FileToken.ToString ;end;

编译运行即可。

客户端我们就直接增加一个上传过程。

procedure TForm1.Button3Click(Sender: TObject);const FBlockSize=2*1024*1024; baseurl=‘http://127.0.0.1/xalionrest‘; basepath=‘d:\‘;var ?HttpClient:TNetHTTPClient; ?requrl:string; ?filetoken:string; ?resp:IHTTPResponse; ?final:string; ?terminate:boolean; ?Stream:TFileStream; ?fm:integer; ?position,sz:string; ?pct:integer; ?RequestStream:Tmemorystream; ?LocalPath,filename:string; ?n,bs,ofs:integer;begin ??filename:= ‘delphi5.rar‘; ??localpath:=basepath+filename; ?fm:=fmOpenRead+fmShareDenyWrite; ?Stream:=TFileStream.Create(LocalPath,fm); ?HttpClient:= TNetHTTPClient.create(nil); ?RequestStream:= Tmemorystream.Create; ?filetoken:=‘-1‘; ?final:=‘0‘; try ?while true do ???????begin ????????????if Stream.Size=0 then ???????????????pct:=100 ????????????else ????????????????pct:=trunc((Stream.Position / Stream.Size) * 100); ?????????????????????????????????????position:=Stream.Position.ToString; ????????????sz:=Stream.Size.ToString; ????????????RequestStream.Clear; ????????????n:=FBlockSize; ????????????ofs:=Stream.Position; ????????????bs:=Stream.Size-ofs; ????????????if bs<=0 then break; ????????????if bs<=n then ????????????begin ?????????????????n:=bs; ?????????????????final:=‘1‘; ????????????end; ????????????RequestStream.CopyFrom(Stream,n); ???????????????RequestStream.Position:=0; ?????????????????try ????????????????????requrl:= baseurl+‘/uploadfile?‘+‘filepath=‘+filename+‘&token=‘+filetoken+‘&position=‘+position+‘&size=‘+n.ToString+‘&final=‘+final; ????????????????????resp:=httpclient.Post(requrl,RequestStream);// ????????????????????filetoken:=resp.ContentAsString(); ????????????????????if pos(‘ERROR:‘,filetoken)>0 then ??????????????????????begin ????????????????????????showmessage(filetoken); ????????????????????????exit; ??????????????????????end; ?????????????????????????????????????except ?????????????????????showmessage(‘上传失败!‘); ?????????????????????exit; ??????????????????end; ????????????????????if n<FBlockSize then ???????????????break; ????????????????????end; ??showmessage(‘上传成功!‘); ????????finally ?????????????Stream.Free; ????????HttpClient.Free; ???????RequestStream.free; ????end;end;

运行起来。

我们看看服务器端的内存占用。
你可以看见服务的内存增长了,但是远远小于文件的大小。

使用kbmmw 的REST 服务实现上传大文件

原文地址:https://www.cnblogs.com/xalion/p/10779308.html

知识推荐

我的编程学习网——分享web前端后端开发技术知识。 垃圾信息处理邮箱 tousu563@163.com 网站地图
icp备案号 闽ICP备2023006418号-8 不良信息举报平台 互联网安全管理备案 Copyright 2023 www.wodecom.cn All Rights Reserved