Delphi 文件流到服务器
我正试图通过网络将mp3文件发送到服务器,在那里由媒体播放器播放。到目前为止,我的代码适用于字符串,但不适用于文件。有人能告诉我我做错了什么吗 这是源代码 客户:Delphi 文件流到服务器,delphi,filestream,Delphi,Filestream,我正试图通过网络将mp3文件发送到服务器,在那里由媒体播放器播放。到目前为止,我的代码适用于字符串,但不适用于文件。有人能告诉我我做错了什么吗 这是源代码 客户: procedure TForm1.Button1Click(Sender: TObject); var MyStream : TFileStream; MP3 : TFileName; Len : Int64; begin MP3 := GetCurrentDir + '\Clocks.mp3'; MyStream
procedure TForm1.Button1Click(Sender: TObject);
var
MyStream : TFileStream;
MP3 : TFileName;
Len : Int64;
begin
MP3 := GetCurrentDir + '\Clocks.mp3';
MyStream := TFilestream.Create(MP3, fmOpenRead);
try
Len := Length(MP3);
MyStream.WriteBuffer(Len, SizeOf(Len));
MyStream.WriteBuffer(Pointer(MP3)^, Len * SizeOf(MP3));
MyStream.Position := 0;
TcpClient1.Active := True;
TcpClient1.SendStream(MyStream);
TcpClient1.Active := False;
finally
MyStream.Free
end;
end;
服务器:
procedure TForm1.TcpServer1Accept(Sender: TObject;
ClientSocket: TCustomIpClient);
var
MP3 : TFileName;
Len: Int64;
begin
//Receives the message from the client
ClientSocket.ReceiveBuf(Len, SizeOf(Len),0);
SetLength(MP3, Len);
ClientSocket.ReceiveBuf(Pointer(MP3)^,Len * SizeOf(MP3), 0);
MediaPlayer1.FileName := MP3;
MediaPLayer1.Open;
MediaPlayer1.Play;
end;
当程序尝试写入流时,问题就开始了,所以我甚至不确定接收端是否工作
注:我是一名初级程序员首先,您发送的是宽字符串,这意味着您必须使用:
Len :=Length(mp3) * SizeOf(Char);
其次,你不需要演员阵容。这应该很好:
myStream.Write(mp3[1],Len);
第三,如果tcpSocket是非阻塞的,那么您不能在发送流之后直接禁用它,这将在连接启动之前切断连接。使用事件来了解数据何时发送
要避免所有这些,请在流上使用TReader和TWriter。这样,您就不必关心两侧的字符串数据大小,只需关心流大小
提示:始终先发送一个神奇值(常量值),这样您就可以在另一端检查它是否是有效的数据包
以下是一种方法:
Procedure TForm1.WriteMP3File(aFilename:string);
var
mData: TMemoryStream;
mFile: TFilestream;
mWriter: TWriter;
Begin
mData:=TMemoryStream.Create;
try
mFile:=TFileStream.Create(aFilename,fmOpenRead);
try
mWriter:=TWriter.Create(mData);
try
// Write header code, any number will do
mWriter.WriteInteger($BABE);
// Write the filename
mWriter.WriteString(ExtractFileName(aFilename));
//Write size of MP3 file
mWriter.WriteVariant(mFile.Size);
//Push all data into the mData stream
mWriter.FlushBuffer;
//Append MP3 file
mData.CopyFrom(mFile,mFile.Size);
finally
mWriter.Free;
end;
mData.Position:=0;
socket.sendstream(mData);
finally
mFile.Free;
end;
finally
mData.Free;
end;
end;
在服务器上以相反的方式读取:
Procedure TForm1.ReadMP3File(aMp3PlayPath:String;aStream:TStream);
var
mReader: TReader;
mFileData: TFileStream;
mName: String;
mSize: Int64;
Begin
try
mReader:=TReader.Create(aStream);
try
if mReader.ReadInteger=$BABE then
Begin
mName:=mReader.ReadString;
mSize:=mReader.ReadVariant;
end else
raise exception.Create('Invalid datapackage error');
finally
mReader.Free;
end;
if mSize>0 then
Begin
mFileData:=TFileStream.Create(aMp3PlayPath + mName,fmCreate);
try
mFiledata.CopyFrom(aStream,mSize);
finally
mFiledata.Free;
end;
end;
//Now you can play the file
finally
//Release stream or do it elsewhere
aStream.Free;
end;
end;
首先,该代码:
MyStream.WriteBuffer(Len, SizeOf(Len));
MyStream.WriteBuffer(Pointer(MP3)^, Len * SizeOf(MP3));
在这种情况下,您试图更改MP3文件内容,这会损坏您的MP3文件。幸运的是,您以fmOpenRead
的形式打开了文件,这就是MyStream.WriteBuffer
失败的原因
如果要将文件名发送到服务器,则必须单独发送(例如使用TTcpClient.SendBuf
)
在服务器端,您当前只读取文件名,而忽略文件内容本身
ClientSocket.ReceiveBuf(Len, SizeOf(Len),0); // this reads length of the filename
SetLength(MP3, Len);
ClientSocket.ReceiveBuf(Pointer(MP3)^,Len * SizeOf(MP3), 0); // this reads filename itself
// Now you should receive file contents itself and store it on the server
将文件存储在服务器上后,可以使用MediaPlayer1播放该文件。如果不将文件存储在服务器上,则只能在服务器和客户端位于同一台计算机上时播放该文件(除非media player使用url或网络路径作为文件名).我不打算只发送文件名。如何声明我处理的文件不是文件名,或者我甚至需要声明MyStream:=TFilestream.Create(GetCurrentDir+'\Clocks.mp3',fmOpenRead);如果是,如果我无法指向文件名变量,如何设置缓冲区的大小。在Answare中添加了一个示例:)添加一个like并在答案上增加值:)如果我的评级足够高,我会m8,我确实喜欢它,但当我开始实现您的代码时,我在这里收到一条错误消息:mWriter:=TWriter.Create(mData);这样行吗?mWriter:=TWriter.Create(mData,0);好的,当我将文件存储在内存中时,我可以开始播放它,只有当它播放完后,我才能释放流。我说的对吗?要从内存播放,你必须使用更复杂的directMedia。将文件保存到文件流,然后播放该文件。mp3格式是否与mediaDirect兼容,或者我是否应该开始查找windows支持的特定于voip的编解码器。如果你想从内存中播放谷歌“delphi mp3播放器”,你可能会发现很多。有很多delphi编解码器包装器,但为了简单起见,我坚持使用基于文件的解决方案。