Recent

Author Topic: Download mp3 file and save to computer  (Read 12255 times)

m4u_hoahoctro

  • Full Member
  • ***
  • Posts: 160
Download mp3 file and save to computer
« on: August 06, 2015, 09:42:37 am »
Hi all
I am learning about how to download a file from internet and save it to computer

I made this code:

Code: [Select]
procedure TForm1.FormCreate(Sender: TObject);
begin
 stream1:=TMemoryStream.Create;
 http1:=tfphttpclient.Create(self);
end;

procedure TForm1.Button1Click(Sender: TObject);
var tl:tstringlist;
begin
 tl:=tstringlist.create;
try
http1.HTTPMethod('GET','http://v3.mp3.zing.vn/download/vip/song/ZW6F97CU',stream1,[100,302]);
for i:=0 to http1.ResponseHeaders.Count-1 do
begin
s:=http1.ResponseHeaders.Strings[i];
if pos('Location:',s)>0 then
begin
s:=stringreplace(trim(stringreplace(s,'Location:','',[])),' ','%20',[rfreplaceall]);
break;
end;
end;
finally
http1.free;
end;

try
http1.HTTPMethod('GET',s,stream1,[100,302]);
finally
http1.free;
end; 

stream1.savetofile('D:/music.mp3');
showmessage('done');         

when I press button, it show an error
Raise exception:SIGSEGV

I tested again, and may be reason is with code

Code: [Select]
try
http1.HTTPMethod('GET',s,stream1,[100,302]);
finally
http1.free;
end;           
stream1.savetofile('D:/music.mp3');

but i haven't known how to fix it yet.

Need your help, thanks very much  :)

HeavyUser

  • Sr. Member
  • ****
  • Posts: 397
Re: Download mp3 file and save to computer
« Reply #1 on: August 06, 2015, 09:50:05 am »
Code: [Select]
procedure TForm1.Button1Click(Sender: TObject);
var tl:tstringlist;
begin
  tl:=tstringlist.create;
  try
    http1.HTTPMethod('GET','http://v3.mp3.zing.vn/download/vip/song/ZW6F97CU',stream1,[100,302]);
    for i:=0 to http1.ResponseHeaders.Count-1 do
    begin
      s:=http1.ResponseHeaders.Strings[i];
      if pos('Location:',s)>0 then
      begin
        s:=stringreplace(trim(stringreplace(s,'Location:','',[])),' ','%20',[rfreplaceall]);
        break;
      end;
    end;
  finally
    http1.free;
  end;

  try
    http1.HTTPMethod('GET',s,stream1,[100,302]);
    stream1.savetofile('D:/music.mp3');
    showmessage('done');
  except
    on E:Exception do showmessage(e.message)
  end;
end;

m4u_hoahoctro

  • Full Member
  • ***
  • Posts: 160
Re: Download mp3 file and save to computer
« Reply #2 on: August 06, 2015, 10:41:18 am »
Code: [Select]
procedure TForm1.Button1Click(Sender: TObject);
var tl:tstringlist;
begin
  tl:=tstringlist.create;
  try
    http1.HTTPMethod('GET','http://v3.mp3.zing.vn/download/vip/song/ZW6F97CU',stream1,[100,302]);
    for i:=0 to http1.ResponseHeaders.Count-1 do
    begin
      s:=http1.ResponseHeaders.Strings[i];
      if pos('Location:',s)>0 then
      begin
        s:=stringreplace(trim(stringreplace(s,'Location:','',[])),' ','%20',[rfreplaceall]);
        break;
      end;
    end;
  finally
    http1.free;
  end;

  try
    http1.HTTPMethod('GET',s,stream1,[100,302]);
    stream1.savetofile('D:/music.mp3');
    showmessage('done');
  except
    on E:Exception do showmessage(e.message)
  end;
end;

still have error :(

HeavyUser

  • Sr. Member
  • ****
  • Posts: 397
Re: Download mp3 file and save to computer
« Reply #3 on: August 06, 2015, 10:46:38 am »
Code: [Select]
procedure TForm1.Button1Click(Sender: TObject);
var tl:tstringlist;
begin
  tl:=tstringlist.create;
  try
    http1.HTTPMethod('GET','http://v3.mp3.zing.vn/download/vip/song/ZW6F97CU',stream1,[100,302]);
    for i:=0 to http1.ResponseHeaders.Count-1 do
    begin
      s:=http1.ResponseHeaders.Strings[i];
      if pos('Location:',s)>0 then
      begin
        s:=stringreplace(trim(stringreplace(s,'Location:','',[])),' ','%20',[rfreplaceall]);
        break;
      end;
    end;
  finally
    ///http1.free;
  end;

  try
    http1.HTTPMethod('GET',s,stream1,[100,302]);
    stream1.savetofile('D:/music.mp3');
    showmessage('done');
  except
    on E:Exception do showmessage(e.message)
  end;
end;
Stop freeing the http1 component.

m4u_hoahoctro

  • Full Member
  • ***
  • Posts: 160
Re: Download mp3 file and save to computer
« Reply #4 on: August 06, 2015, 11:31:42 am »
I found another way, thanks for your comment
[Problem was solved]

derek.john.evans

  • Guest
Re: Download mp3 file and save to computer
« Reply #5 on: August 06, 2015, 11:55:11 am »
Should be as simple as this?

Code: Pascal  [Select][+][-]
  1. uses fphttpclient;
  2.  
  3. procedure UrlCopyFile(const ASourceUrl, ADestFileName: String);
  4. var
  5.   LFileStream: TFileStream;
  6. begin
  7.   LFileStream := TFileStream.Create(ADestFileName, fmCreate);
  8.   try
  9.     TFPCustomHTTPClient.SimpleGet(ASourceUrl, LFileStream);
  10.   finally
  11.     FreeAndNil(LFileStream);
  12.   end;
  13. end;    
  14.  
« Last Edit: October 02, 2015, 03:36:36 am by Geepster »

rvk

  • Hero Member
  • *****
  • Posts: 6989
Re: Download mp3 file and save to computer
« Reply #6 on: August 06, 2015, 12:33:27 pm »
Should be as simple as this?
No, it's not.

The URL "http://v3.mp3.zing.vn/download/vip/song/ZW6F97CU" gives a 302 redirection in the headers. So you need to get the source from that redirection.

Does fphttpclient have a method to automatically follow redirections???

Leledumbo

  • Hero Member
  • *****
  • Posts: 8836
  • Programming + Glam Metal + Tae Kwon Do = Me
Re: Download mp3 file and save to computer
« Reply #7 on: August 06, 2015, 01:20:29 pm »
Does fphttpclient have a method to automatically follow redirections???
Yes, but not in one of the convenient single method call version. You must construct TFPHTTPClient object and set AllowRedirect to true, then call Get. Could be a good option to make an optional parameter in the convenient single method call version.
« Last Edit: August 06, 2015, 02:23:50 pm by Leledumbo »

derek.john.evans

  • Guest
Re: Download mp3 file and save to computer
« Reply #8 on: August 06, 2015, 01:59:09 pm »
Should be as simple as this?
No, it's not.

The URL "http://v3.mp3.zing.vn/download/vip/song/ZW6F97CU" gives a 302 redirection in the headers. So you need to get the source from that redirection.

Does fphttpclient have a method to automatically follow redirections???

Touché, Right you are!

Here is a redirection extension for TFPCustomHTTPClient, plus an updated UrlCopyFile() function.
Ive tested it on 'http://v3.mp3.zing.vn/download/vip/song/ZW6F97CU', but it needs more testing.

Code: Pascal  [Select][+][-]
  1. uses fphttpclient, HTTPDefs, StrUtils;
  2.  
  3. type
  4.  
  5.   TFPCustomHTTPClient2 = class(TFPCustomHTTPClient)
  6.   public
  7.     procedure GetWithRedirect(AUrl: String; const AStream: TStream; AMaxRedirection: Integer);
  8.   end;
  9.  
  10. procedure TFPCustomHTTPClient2.GetWithRedirect(AUrl: String; const AStream: TStream;
  11.   AMaxRedirection: Integer);
  12. begin
  13.   ResponseHeaders.NameValueSeparator := ':';
  14.   repeat
  15.     try
  16.       Get(AUrl, AStream);
  17.       Exit;
  18.     except
  19.       if (ResponseStatusCode = 302) and (AMaxRedirection > 0) then
  20.       begin
  21.         Dec(AMaxRedirection);
  22.         AUrl := AnsiReplaceStr(Trim(ResponseHeaders.Values[fieldLocation]), ' ', '+');
  23.       end else begin
  24.         raise;
  25.       end;
  26.     end;
  27.   until False;
  28. end;    
  29.  

Code: Pascal  [Select][+][-]
  1. procedure UrlCopyFile(AUrl, AFileName: String);
  2. var
  3.   LFileStream: TFileStream;
  4. begin
  5.   LFileStream := TFileStream.Create(AFileName, fmCreate);
  6.   try
  7.     with TFPCustomHTTPClient2.Create(nil) do
  8.     begin
  9.       try
  10.         GetWithRedirect(AUrl, LFileStream, 4);
  11.       finally
  12.         Free;
  13.       end;
  14.     end;
  15.   finally
  16.     FreeAndNil(LFileStream);
  17.   end;
  18. end;  
  19.  


Now, im going to sit back and listen to Khong Phai Dang Vua Dau.
« Last Edit: October 02, 2015, 03:36:10 am by Geepster »

rvk

  • Hero Member
  • *****
  • Posts: 6989
Re: Download mp3 file and save to computer
« Reply #9 on: August 06, 2015, 02:30:42 pm »
Code: [Select]
      if (ResponseStatusCode = 302) and (AMaxRedirection > 0) then
You might want to use the function IsRedirect() from TFPCustomHTTPClient. It checks for 301, 302, 303, 307 and 308 which are all redirect codes.

Yes, but not in one of the convenient single method call version. You must construct TFPHTTPClient object and set AllowRedirect to true, then call Get. Could be a good option to make an optional parameter.
Yeah, that also doesn't work. The Get method is really inflexible. It calls HTTPMethod with GET but with AllowedResponseCodes of [200] (despite what is filled in AllowRedirect). Even if you create a new GET with
Code: [Select]
      HTTPClient.AllowRedirect := True;
      HTTPClient.RequestHeaders.Add('Connection: Close');
      HTTPClient.HTTPMethod('GET', ASourceUrl, LFileStream, [200, 301, 302, 303, 307, 308]);
it seems to be problematic giving me an unexpected 400 result.
« Last Edit: August 06, 2015, 02:38:18 pm by rvk »

rvk

  • Hero Member
  • *****
  • Posts: 6989
Re: Download mp3 file and save to computer
« Reply #10 on: August 06, 2015, 02:39:14 pm »
Code: [Select]
procedure TFPCustomHTTPClient2.GetWithRedirect(AUrl: String; const AStream: TStream;
  AMaxRedirection: Integer);
begin
  ResponseHeaders.NameValueSeparator := ':';
  repeat
    try
      Get(AUrl, AStream);
      Exit;
    except
...
And... This also doesn't work  %) You can't do a Get in your TFPCustomHTTPClient2.GetWithRedirect. The Get() in TFPCustomHTTPClient is implemented to only allow a response of 200. So you need to implement a new Get() which call HTTPMethod() with a more elaborate AllowResponses set.

Did it download the MP3 for you, with this code?
« Last Edit: August 06, 2015, 02:41:51 pm by rvk »

derek.john.evans

  • Guest
Re: Download mp3 file and save to computer
« Reply #11 on: August 06, 2015, 02:46:15 pm »
And... This also doesn't work  %) You can't do a Get in your TFPCustomHTTPClient2.GetWithRedirect. The Get() in TFPCustomHTTPClient is implemented to only allow a response of 200. So you need to implement a new Get() which call HTTPMethod() with a more elaborate AllowResponses set.

Works for me. CheckResponseCode is called after ReadResponseHeaders, which means if the response code is not in AllowResponses, then then header will still be valid. The content is skipped.

Which is suitable for redirection. ie: You get an exception, but the header information is valid.

rvk

  • Hero Member
  • *****
  • Posts: 6989
Re: Download mp3 file and save to computer
« Reply #12 on: August 06, 2015, 02:55:16 pm »
Works for me. CheckResponseCode is called after ReadResponseHeaders, which means if the response code is not in AllowResponses, then then header will still be valid. The content is skipped.

Which is suitable for redirection. ie: You get an exception, but the header information is valid.
Woops, yeah, sorry. You're working with the exception there. Not really pretty and definitely not suitable for production-code. It will work but realying on an exception like that...  %)

I would not use the Get() directly but just call
Code: [Select]
// Get(AUrl, AStream);
RequestHeaders.Add('Connection: Close'); // (needed ??)
HTTPMethod('GET', AUrl, AStream, [200, 301, 302, 303, 307, 308]);
That way you wouldn't have to work with exception which show a dialog in the IDE.

Something like this:
Code: [Select]
procedure TFPCustomHTTPClient2.GetWithRedirect(AUrl: string;
  const AStream: TStream; AMaxRedirection: integer = 10);
begin
  ResponseHeaders.NameValueSeparator := ':';
  repeat
    // Get(AUrl, AStream);
    RequestHeaders.Add('Connection: Close'); // (is this needed ??)
    HTTPMethod('GET', AUrl, AStream, [200, 301, 302, 303, 307, 308]);
    if IsRedirect(ResponseStatusCode) and (AMaxRedirection > 0) then
    begin
      Dec(AMaxRedirection);
      AUrl := AnsiReplaceStr(Trim(ResponseHeaders.Values[fieldLocation]), ' ', '+');
    end
    else
      break;
  until False;
end;
« Last Edit: August 06, 2015, 03:02:49 pm by rvk »

derek.john.evans

  • Guest
Re: Download mp3 file and save to computer
« Reply #13 on: August 06, 2015, 03:19:47 pm »
Woops, yeah, sorry. You're working with the exception there. Not really pretty and definitely not suitable for production-code. It will work but realying on an exception like that...  %)

True. kinda. I'm an exception fan, which does require me to turn off exceptions in the IDE. Unsure about the "production-code" comment, but then im not up for a debate, other than exception coding has served me very well. Pas2Php & Geep Jeez are totally covered in exceptions, but, yes, I should probably tighten up my style.

The problem is, if by allowing all the responses, is possible that data will be added to the stream in ReadResponse() ? Its a small chance, but possible.

The next break out point (in ReadResponse)  is via HeadersOnly, but then with redirection, you dont know if the first get will be the "real" data.

All of this is a little moot, since I would use Indy over fphttpclient, but, then im happy to know I can do this if need be.

« Last Edit: August 06, 2015, 03:24:03 pm by derek.john.evans »

rvk

  • Hero Member
  • *****
  • Posts: 6989
Re: Download mp3 file and save to computer
« Reply #14 on: August 06, 2015, 03:37:24 pm »
True. kinda. I'm an exception fan, which does require me to turn off exception in the IDE. Unsure about the "production-code" comment, but then im not up for a debate, other than exception coding has served me very well. Pas2Php & Geep Jeez are totally covered in exceptions, but, yes, I should probably tighten up my style.
Overall there is nothing wrong with using exceptions when they are used correctly. But somehow I have the feeling they should be avoided if some of this code would end up in LCL or CCR. Not everyone (almost no one :)) has their exceptions turned off in the IDE and it would result in lots of dialog popups. Using this code just in your own program would be perfectly fine.

The problem is, if by allowing all the responses, is possible that data will be added to the stream in ReadResponse() ? Its a small chance, but possible.
True... that's why the AllowRedirect should be used. In that case the ReadResponse is exited before the stream is filled. Actually if AllowRedirect would be used all the redirection would be taken case of. But there is a flaw in AllowRedirect with possible parameters (which I will post next as a response to Leledumbo).

All of this is a little moot, since I would use Indy over fphttpclient, but, then im happy to know I can do this if need be.
My communication-library of choice would be Ararat Synapse. Everyone has their own favorite  :)

 

TinyPortal © 2005-2018