使用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 ...
随机推荐
- 3sum 求三数之和等于0,不允许重复
https://leetcode.com/problems/3sum/ 套路比较常见了,最重要的是去重.还是没法一次通过. class Solution { public: vector<vec ...
- Hibernate 中出现 users is not mapped 问题
Hibernate 中出现 users is not mapped 问题: 解答:HQL语句中表名应该是ORM映射的类名,所以应该改成: (如果是用注解生成实体类,那就是注解的那个类)String ...
- SuRF: Practical Range Query Filtering with Fast Succinct Tries 阅读笔记
SuRF(Succinct Range Filter)是一种快速而紧凑的过滤器,同时支持点查询和范围查询(包括开区间查询.闭区间查询.范围计数),可以在RocksDB中用SuRF来替换Bloom过滤器 ...
- java使用c3p0连接mysql,写中文数据乱码的问题
此文说的乱码,是指所有中文的字符都变成了?. 首先,网上普遍搜索到的解决方案都是告诉你要在数据库连接字符串里面增加编码的定义,完整的连接字符串如下: url="jdbc:mysql://12 ...
- python学习Day13 函数的嵌套定义、global、nonlocal关键字、闭包及闭包的运用场景、装饰器
复习 1.函数对象:函数名 => 存放的是函数的内存地址1)函数名 - 找到的是函数的内存地址2)函数名() - 调用函数 => 函数的返回值 eg:fn()() => fn的返回值 ...
- JQ滚动条监听事件
版权归作者所有,任何形式转载请联系作者.作者:帅阿猪(来自豆瓣)来源:https://www.douban.com/note/637256366/ 先来一个小例子: $(document).ready ...
- 如何利用webpack4.0搭建一个vue项目
作为一个初学者,记录自己踩过的坑是个好的习惯.我本身比较懒,这里刚好有时间把自己的搭建过程记录一下这里是参考文章 https://www.jianshu.com/p/1fc5b5151abf文章里 ...
- StringUtils.isEmpty StringUtils.isBlank
两个方法都是判断字符是否为空的.前者是要求没有任何字符,即str==null 或 str.length()==0:后者要求是空白字符,即无意义字符.其实isBlank判断的空字符是包括了isEmpty ...
- Polar Code(1)关于Polar Code
Polar Codes于2008年由土耳其毕尔肯大学Erdal Arikan教授首次提出,Polar Codes提出后各通信巨头都进行了研究.2016年11月18日(美国时间2016年11月17日), ...
- Ubuntu 16.04 安装Kinect V2驱动
1.下载源代码 git clone https://github.com/OpenKinect/libfreenect2.git 2.依赖项安装 sudo apt-get install build- ...