Android端DataSnap发送PNG图片遇类型转换及内存溢出问题求助
问题解决:DataSnap传输图片流的类型转换与内存不足问题
问题1:Invalid Typecast(类型转换无效)
初始代码中服务端直接将参数声明为TMemoryStream,但DataSnap在传输流时,实际传递的是TDBXStream(DataSnap封装的流类型),而非原生的TMemoryStream,直接强制转换就会触发类型转换错误。
问题2:大文件传输内存不足
改为TStream后,若仍使用TMemoryStream加载整个文件到内存,在Android设备(内存资源有限)或传输较大文件时,容易触发内存不足错误。
解决方案
1. 统一流参数类型为TStream
服务端和客户端的方法参数都使用TStream而非具体的TMemoryStream,避免类型不匹配。同时注意:
- 客户端传递流前,必须将
Position重置为0 - 设置DataSnap参数的
FInstanceOwner为False,避免框架自动释放你需要控制的流对象
2. 使用TFileStream替代TMemoryStream
直接通过文件流读写,无需将整个文件加载到内存,从根源减少内存占用。
修改后的代码示例
客户端调用代码(替换原内存流加载逻辑)
LocationID := inireadInt(Files[0],'DATA','LocationID'); BatchName := inireadStr(Files[0],'DATA','BatchNumber'); ImageFile := ChangeFileExt(Files[0],'.img'); // 使用TFileStream直接读取文件,无需加载到内存 var ImageStream: TFileStream; begin ImageStream := TFileStream.Create(ImageFile, fmOpenRead or fmShareDenyWrite); try ImageStream.Position := 0; if FileType = 'BatchTrack' then begin if Temp.BATCH_TRACK(LocationID,BatchName,ImageStream) = 1 then begin System.SysUtils.DeleteFile(Files[0]); end; end; finally ImageStream.Free; end; end;
客户端BATCH_TRACK方法(调整参数类型与实例所有权)
function TServerMethods1Client.BATCH_TRACK(HeadID: integer; BatchNumber: string; Image: TStream): integer; begin if FBATCH_TRACKCommand = nil then begin FBATCH_TRACKCommand := FDBXConnection.CreateCommand; FBATCH_TRACKCommand.CommandType := TDBXCommandTypes.DSServerMethod; FBATCH_TRACKCommand.Text := 'TServerMethods1.BATCH_TRACK'; FBATCH_TRACKCommand.Prepare; end; FBATCH_TRACKCommand.Parameters[0].Value.SetInt32(HeadID); FBATCH_TRACKCommand.Parameters[1].Value.SetWideString(BatchNumber); // 设置FInstanceOwner为False,由我们自行管理流的生命周期 FBATCH_TRACKCommand.Parameters[2].Value.SetStream(Image, False); FBATCH_TRACKCommand.ExecuteUpdate; Result := FBATCH_TRACKCommand.Parameters[3].Value.GetInt32; end;
服务端BATCH_TRACK方法(优化流处理,减少内存占用)
function TServerMethods1.BATCH_TRACK(HeadID : integer; Batchnumber : string; Image : TStream) : integer; var SaveStream: TFileStream; SavePath: string; begin Result := -1; try // 定义保存路径(根据实际需求调整) SavePath := '你的服务器保存路径\' + Batchnumber + '_' + IntToStr(HeadID) + '.png'; SaveStream := TFileStream.Create(SavePath, fmCreate or fmShareDenyWrite); try // 直接将传入的流写入文件,无需在内存中复制 SaveStream.CopyFrom(Image, Image.Size); Result := 1; finally SaveStream.Free; end; except // 可添加具体的错误日志记录 Result := -1; end; end;
额外配置:调整DataSnap最大Blob大小
如果仍存在大文件传输限制,可在客户端和服务端的DataSnap连接参数中添加:
// 客户端连接配置 FDBXConnection.Params.Values['TDBXParameterMetaData.MaxBlobSize'] := '10485760'; // 设置为10MB,按需调整 // 服务端DataSnap服务器配置(在ServerContainer中) ServerContainer1.SQLConnection1.Params.Values['TDBXParameterMetaData.MaxBlobSize'] := '10485760';
内容的提问来源于stack exchange,提问作者user1937012
相关产品推荐
相关产品推荐

