使用kbmmw 的REST 服务实现上传大文件
我们在使用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 服务实现上传大文件的更多相关文章
- IIS7下swfupload上传大文件出现404错误
要求上传附件大小限制在2G,原本以为可以轻松搞定.在编译模式下可以上传大文件,可是在IIS7下(自己架的服务器),一上传大的文件就会出现 Http 404错误,偶尔有的文件还有IO. error错误. ...
- tp5+layui 实现上传大文件
前言: 之前所写的文件上传类通常进行考虑的是文件的类型.大小是否符合要求条件.当上传大文件时就要考虑到php的配置和服务器的配置问题.之前简单的觉得只要将php.ini中的表单上传的 大小,单脚本执行 ...
- tornado上传大文件以及多文件上传
tornado上传大文件问题解决方法 tornado默认上传限制为低于100M,但是由于需要上传大文件需求,网上很多说是用nginx,但我懒,同时不想在搞一个服务了. 解决方法: server = H ...
- HTTP上传大文件的注意点
使用HttpWebRequest上传大文件时,服务端配置中需要进行以下节点配置: <system.web> <compilation debug="true" t ...
- asp.net core流式上传大文件
asp.net core流式上传大文件 首先需要明确一点就是使用流式上传和使用IFormFile在效率上没有太大的差异,IFormFile的缺点主要是客户端上传过来的文件首先会缓存在服务器内存中,任何 ...
- vue上传大文件的解决方案
众所皆知,web上传大文件,一直是一个痛.上传文件大小限制,页面响应时间超时.这些都是web开发所必须直面的. 本文给出的解决方案是:前端实现数据流分片长传,后面接收完毕后合并文件的思路. 实现文件夹 ...
- Web上传大文件的解决方案
需求:项目要支持大文件上传功能,经过讨论,初步将文件上传大小控制在500M内,因此自己需要在项目中进行文件上传部分的调整和配置,自己将大小都以501M来进行限制. 第一步: 前端修改 由于项目使用的是 ...
- JS上传大文件的解决方案
最近遇见一个需要上传百兆大文件的需求,调研了七牛和腾讯云的切片分段上传功能,因此在此整理前端大文件上传相关功能的实现. 在某些业务中,大文件上传是一个比较重要的交互场景,如上传入库比较大的Excel表 ...
- java上传大文件解决方案
需求:项目要支持大文件上传功能,经过讨论,初步将文件上传大小控制在10G内,因此自己需要在项目中进行文件上传部分的调整和配置,自己将大小都以10G来进行限制. 第一步: 前端修改 由于项目使用的是BJ ...
随机推荐
- laravel5.6上传图片
第一种:修改config里边的filesystems.php文件,在disks中加入下列代码 'local' => [ 'driver' => 'local', 'root' => ...
- 尚硅谷springboot学习34-整合SpringData JPA
SpringData简介
- v8:: fatalProcessOutOfMemory
express项目,用于画图读写图片数据, pm2 作为进城守护. 生产环节报警:v8:: fatalProcessOutOfMemory,xxxx等,一时不知道什么原因. linux系统下使用如下命 ...
- python中logging模块
1. 日志的等级 DEBUG.INFO.NOTICE.WARNING.ERROR.CRITICAL.ALERT.EMERGENCY 级别 何时使用 DEBUG 详细信息,典型地调试问题时会感兴趣. 详 ...
- 用js实现一个简单的mvvm
这里利用的object.defineproperty() 方法; <input id='input'><p id='p'><p/>js: const dat ...
- Excel基本操作
一.excel公式下拉 1.选择最长一列excel ,按CTRL+↓移到最后一个单元格,2光标移到下拉公式的那一列,3.再按CTRL+SHIFT+↑,4.再按CTRL+D 二.输入身份证号等长数字 方 ...
- 给统计人讲python(1)模拟城市_数据分析
为让学校统计学社的同学了解python在数据处理方面的功能,将手游模拟城市的工厂生产进行建模,让同学在建模与处理非结构数据的过程中学习和了解python.将准备的内容放在此让更多需要的人特别是统计人( ...
- 19-05【icloud】照片备份
icloud提供了免费的存储空间,5G,超过这个量需要单独购买空间:我用的是50G,每月6元. 如果在mac或者iphone上开启了本地的照片流,则会自动同步到icloud,同时各个设备的客户端(ip ...
- UIButton设置UIControlContentHorizontalAlignment调整文字对齐方式
UIButton 继承自UIControl,所以可以对UIControlContentHorizontalAlignment进行设置 btn.setImage(UIImage.init(named: ...
- 2018-2019-2 20165315《网络攻防技术》Exp6 信息搜集与漏洞扫描
2018-2019-2 20165315<网络攻防技术>Exp6 信息搜集与漏洞扫描 目录 一.实验内容 二.实验步骤 1.各种搜索技巧的应用 2.DNS IP注册信息的查询 3.基本的扫 ...