我们在使用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=**; //上传文件大小不能超过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>** then
begin
result:=errmsg+'blocksize too big.';
exit;
end; if ((final<>'') and (final<>'')) then
begin
result:=errmsg+'final error.';
exit;
end; if final='' then
ffinal:=False
else
ffinal:=True; FileToken:=strtoint(token); path:= UPLOADPATH+filepath;
// Determine file mode.
if FileToken=- 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>= then
begin
if (maxsize>) and (FOfs+sz>maxSize) then
begin
result:=errmsg+'File too big';
exit;
end; if FileSeek(h,FOfs,)< then
begin
result:=errmsg+'Cant position in file';
exit; end;
end
else
begin
newofs:=FileSeek(h,,);
if newofs< then
begin
result:=errmsg+'Cant append to file';
exit;
end; if (maxsize>) 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=**; 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:='';
try
while true do
begin
if Stream.Size= then
pct:=
else
pct:=trunc((Stream.Position / Stream.Size) * ); position:=Stream.Position.ToString;
sz:=Stream.Size.ToString; RequestStream.Clear;
n:=FBlockSize;
ofs:=Stream.Position;
bs:=Stream.Size-ofs;
if bs<= then break;
if bs<=n then
begin
n:=bs;
final:='';
end;
RequestStream.CopyFrom(Stream,n); RequestStream.Position:=;
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)> 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 服务实现上传大文件的更多相关文章

  1. IIS7下swfupload上传大文件出现404错误

    要求上传附件大小限制在2G,原本以为可以轻松搞定.在编译模式下可以上传大文件,可是在IIS7下(自己架的服务器),一上传大的文件就会出现 Http 404错误,偶尔有的文件还有IO. error错误. ...

  2. tp5+layui 实现上传大文件

    前言: 之前所写的文件上传类通常进行考虑的是文件的类型.大小是否符合要求条件.当上传大文件时就要考虑到php的配置和服务器的配置问题.之前简单的觉得只要将php.ini中的表单上传的 大小,单脚本执行 ...

  3. tornado上传大文件以及多文件上传

    tornado上传大文件问题解决方法 tornado默认上传限制为低于100M,但是由于需要上传大文件需求,网上很多说是用nginx,但我懒,同时不想在搞一个服务了. 解决方法: server = H ...

  4. HTTP上传大文件的注意点

    使用HttpWebRequest上传大文件时,服务端配置中需要进行以下节点配置: <system.web> <compilation debug="true" t ...

  5. asp.net core流式上传大文件

    asp.net core流式上传大文件 首先需要明确一点就是使用流式上传和使用IFormFile在效率上没有太大的差异,IFormFile的缺点主要是客户端上传过来的文件首先会缓存在服务器内存中,任何 ...

  6. vue上传大文件的解决方案

    众所皆知,web上传大文件,一直是一个痛.上传文件大小限制,页面响应时间超时.这些都是web开发所必须直面的. 本文给出的解决方案是:前端实现数据流分片长传,后面接收完毕后合并文件的思路. 实现文件夹 ...

  7. Web上传大文件的解决方案

    需求:项目要支持大文件上传功能,经过讨论,初步将文件上传大小控制在500M内,因此自己需要在项目中进行文件上传部分的调整和配置,自己将大小都以501M来进行限制. 第一步: 前端修改 由于项目使用的是 ...

  8. JS上传大文件的解决方案

    最近遇见一个需要上传百兆大文件的需求,调研了七牛和腾讯云的切片分段上传功能,因此在此整理前端大文件上传相关功能的实现. 在某些业务中,大文件上传是一个比较重要的交互场景,如上传入库比较大的Excel表 ...

  9. java上传大文件解决方案

    需求:项目要支持大文件上传功能,经过讨论,初步将文件上传大小控制在10G内,因此自己需要在项目中进行文件上传部分的调整和配置,自己将大小都以10G来进行限制. 第一步: 前端修改 由于项目使用的是BJ ...

随机推荐

  1. jsfl 添加代码

    var __name=""; var __author=""; var __book=[]; var newJz=""; for(var d ...

  2. 没有upcast 也不会发生多态

    class A{ public: virtual void f(){ cout << "A::f()"<<endl;} }; class B:public ...

  3. java 深度复制与浅复制 copyOf、arraycopy、copyOfRange

    1.copyOf 原型:public static <T> T[] copyOf(T[] original, int newLength) original:原数组 newLength:要 ...

  4. 阿里巴巴 Weex

    原文链接:https://blog.csdn.net/zz901214/article/details/79168707/ 分享嘉宾:侑夕 阿里巴巴高级前端工程师(上张帅哥的图镇楼,看完,更有动力学习 ...

  5. js 解析url

    以前解析uri都是去找网上的代码,用起来不怎么顺手,刚好自己前段时间做项目的时候需要用到,于是就自己写了一个,欢迎个位提出宝贵意见. getUrlParam (name) { //解析url var ...

  6. L2-018 多项式A除以B(模拟)

    这仍然是一道关于A/B的题,只不过A和B都换成了多项式.你需要计算两个多项式相除的商Q和余R,其中R的阶数必须小于B的阶数. 输入格式: 输入分两行,每行给出一个非零多项式,先给出A,再给出B.每行的 ...

  7. django xadmin后台页面实现二级联动

    思路 先找到控件id ,这样就可以监听change事件 然后把自己写的js加入xadmin中 添加url和view,接受ajax请求和发送数据 第一步:找到联动上下级的ID 在浏览器中通过F12查看 ...

  8. 010 Editor 8.0.1 之 逆向分析及注册机编写

    前言一.工具及软件介绍二.逆向分析2.1.找到提示错误注册弹窗2.2.分析跳转处代码2.3.=2D 函数分析2.3.1.获取注册码处分析2.3.2.3处分支分析2.3.2.1.9C情况2.3.2.2. ...

  9. shp2pgsql向postgresql导入shape数据

    1. 准备好Shape文件(不仅仅是.shp文悠扬,还要有其他相关数据文件,包括.shx..prj..dbf文件). 2. 使用命令将Shape数据转换为*.sql文件 shp2pgsql -s 38 ...

  10. RestSharp发送请求得到Json数据

    NUGET安装:RestSharp code: public string Post(string url, string content) { string contentType = " ...