Uczę się C++ już prawie rok (pół roku na Turbo C, miesiąc na DevC++, teraz na builder6).
Chciałem napisać program do ściągania plików z internetu. Przy pomocy źródła paru funkcji, udało mi się to osiągnąć. Teraz przerabiam program tak, aby ściągać pliki z wrzuta.pl. I tu jest problem, gdyż nie chce pobierać (adress i host wydaje mi się prawidłowy).
/*
//---------------------------------------------------------------------------
#include <vcl.h>
#pragma hdrstop
#include "Unit1.h"
//---------------------------------------------------------------------------
#pragma package(smart_init)
#pragma link "CGAUGES"
#pragma resource "*.dfm"
TForm1 *Form1;
TFileStream *TPlik;
String Plik,Host;
bool get_header,Continue;
AnsiString Buffer;
char szBuffer[8191];
char szBufferHeader;
int ReturnCode;
//---------------------------------------------------------------------------
__fastcall TForm1::TForm1(TComponent* Owner)
: TForm(Owner)
{
}
//---------------------------------------------------------------------------
void __fastcall TForm1::FormCreate(TObject *Sender)
{
get_header=true;
}
//---------------------------------------------------------------------------
void __fastcall TForm1::PobierzClick(TObject *Sender)
{
if (Pobierz->Caption == "Anuluj") {
get_header=true;
Pobierz->Caption = "Pobierz";
Postep->Progress = 0;
Label1->Caption = "Pobieranie anulowano!";
ClientSocket->Active = false;
}
else {
Plik = Adres->Text;
int FindAudio = Plik.Pos( "/audio/" ), // szukanie pozycji mp3
FindMovie = Plik.Pos( "/film/" ); // szukanie pozycji filmu
if ( FindAudio != 0 ) {
Plik = Plik.Delete( FindAudio+1, 5);
Plik = Plik.Insert("sr/f", FindAudio+1); // zmiana adresu do pliku
SaveDialog->Filter=".mp3|.mp3"; // ustawienie formaty pliku
}
else if ( FindMovie != 0 ){
Plik = Plik.Delete( FindAudio+1, 4);
Plik = Plik.Insert("sr/v", FindMovie+1); // zmiana adresu do pliku
SaveDialog->Filter=".flv|.flv"; // ustawienie formaty pliku
}
if (Plik.Pos("http:") > 0) /* Wycinamy niepotrzebne dane z adresu */
Plik.Delete(1,7);
Host = Plik;
if (Host.Pos("/") > 1) {
Host = Host.SubString(1,Host.Pos("/")-1); /* Host */
Plik.Delete(1,Plik.Pos("/")-1); /* Wyciągamy z adresu nazwe pliku do pobrania */
}
else
Plik = "/";
int i;
for (i = Plik.Length(); i>0; i--) {
if (Plik[i] == '/') break;
}
SaveDialog->FileName = Plik.SubString(i+1,Plik.Length());
Edit1->Text = Plik;
Edit2->Text = Host;
if (SaveDialog->Execute()) {
if (FileExists(SaveDialog->FileName))
if (MessageBox(Handle,"Plik istnieje, kontynuowac sciaganie?", "Plik istnieje", MB_YESNO|MB_ICONQUESTION) == ID_YES)
Continue = true;
else
Continue = false;
else
Continue = false;
ClientSocket->Port = 80;
ClientSocket->Host = Host;
ClientSocket->Active = true;
Application->ProcessMessages();
}
}
}
//---------------------------------------------------------------------------
void __fastcall TForm1::ClientSocketConnect(TObject *Sender,
TCustomWinSocket *Socket)
{
Label1->Caption = "Połączony.";
if (Continue) {
/* Jeżeli plik istnieje i kontynujemy sciąganie otwieramy plik w trybie dopisywania danych */
TPlik=new TFileStream(SaveDialog->FileName, fmOpenWrite);
/* Ustalamy pozycje na koniec pliku */
TPlik->Position = TPlik->Size;
} else
TPlik=new TFileStream(SaveDialog->FileName, fmCreate);
/* Wysyłamy zapytanie HTTP do serwera.
GET nazwa pliku
HTTP/1.1 <- korzystamy z protokołu HTTP 1.1, w HTTP 1.0 nie ma możliwosci wznawiania sciagania
Host <- służący do rozpoznania hosta
Accept: * /* <- akceptowane typy plików
Range: bytes=0- (caly plik) <- najważniejsza czesc, tutaj przekazujemy informacje, od kórego bajtu i do którego serwer ma wysyłac dane, tzn.
wielkosc danych juz pobranych
User-Agent: <- nazwa aplikacji klienckiej np:
adres: http://jakisserwer.pl/download/pliczek.rar
GET /download/pliczek.rar HTTP/1.1\r\n
Host: jakisserwer.pl\r\n
Accept: * /*\r\n
Range: bytes=0-\r\n
User-Agent: GetFiles(ver. 0.1)\r\n\r\n
Informacja dla serwera o rozpoczęciu wysyłania danych jest: \r\n\r\n
- znak powrotu karetki i wysunięcia strony (CRLF))
*/
String s = "GET "+Plik+" HTTP/1.1\r\nHost: "+Host+"\r\nAccept: */*\r\nRange: bytes="+TPlik->Size+"-\r\nUser-Agent: Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1)\r\n\r\n";
/* Wysyłamy dane. */
Socket->SendBuf(s.c_str(), s.Length());
}
//---------------------------------------------------------------------------
void __fastcall TForm1::ClientSocketRead(TObject *Sender,
TCustomWinSocket *Socket)
{
/*
W odpowiedzi serwer przesyła status kodu (OK, plik nie istnieje itd.).
Jeżeli plik istnieje przesłane są informacje dotyczące typu pliku, wielkosci
oraz w przypadku wznawiania sciągania informacje od (do) którego bajtu sa wysyłane dane.
Dodatkowo przesłane są też inne informacje.
Więcej informacji (wszystko) na temat protokołu HTTP 1.1 znajdziecie pod tym adresem:
http://www.w3.org/Protocols/rfc2616/rfc2616.html
Własciwe dane są rozdzielone od odpowiedzi serwera podwójym znakiem CRLF.
*/
Application->ProcessMessages();
if(get_header) { /* Odebrane dane to nagłówek */
ReturnCode = Socket->ReceiveBuf(&szBufferHeader, 1);
Buffer+=szBufferHeader;
if(szBufferHeader == '\r') { /* CR */
ReturnCode = Socket->ReceiveBuf(&szBufferHeader, 1);
Buffer+=szBufferHeader;
if(szBufferHeader == '\n') { /* LF */
//mamy jeden koniec lini
ReturnCode = Socket->ReceiveBuf(&szBufferHeader, 1);
Buffer+=szBufferHeader;
if(szBufferHeader == '\r') /* CR */
{
ReturnCode = Socket->ReceiveBuf(&szBufferHeader, 1);
Buffer+=szBufferHeader;
if(szBufferHeader == '\n') /* LF */
{
/* W przypadku gdy rozmair pliku jest > od 0
(kontynujemy sciąganie), należy sprawdzic,
czy jest mozliwosc dalszego pobierania.
Informacja ta jest zawarta w odpowiedzi serwera
na zapytanie HTTP - kod 206
*/
if (!IsPartialContent(Buffer) && (TPlik->Size > 0)) {
ClientSocket->Active = false;
Label1->Caption = "Nie można kontynuowac pabierania pliku! Pobieraie anulowane";
} else {
/*
Funkcja GetLengthFile() pobiera wielkosc pliku.
Zmieniamy wartosc get_header na false.
*/
Postep->MaxValue = TPlik->Size + GetLengthFile(Buffer);
Postep->Progress = TPlik->Size;
Label1->Caption = "Pobieranie pliku...";
get_header=false;
Pobierz->Caption = "Anuluj";
}
memset(&Buffer, 0, sizeof(Buffer));
memset(&szBufferHeader, 0, sizeof(szBufferHeader));
/*
Należałoby obsłużyc pozostałe kody błędów w przypadku
pobierania danych (3xx, 4xx, 5xx).
Po więcej informacji odsyłam do:
http://www.w3.org/Protocols/rfc2616/rfc2616-sec10.html#sec10
*/
}
}
}
}
}
else {
/* Pobranie własciwych danych i zapisanie do pliku */
/* Czyscimy buffer */
memset(szBuffer, 0, sizeof(szBuffer));
/* Zapisujemy do buffora */
ReturnCode = Socket->ReceiveBuf(szBuffer,sizeof(szBuffer)-1);
/* Zapisujemy do pliku */
TPlik->Write(szBuffer, ReturnCode);
/* Zwiększamy pasek postępu */
Postep->Progress = TPlik->Size;
/* Pobieranie zakończone, zamykamy plik, rozłączamy się z serwerem,
oraz ustawiamy wartosc zmiennej get_header na true */
if (Postep->Progress >= Postep->MaxValue) {
ClientSocket->Active = false;
get_header=true;
Pobierz->Caption = "Pobierz";
}
}
}
//---------------------------------------------------------------------------
int TForm1::GetLengthFile(AnsiString szString)
{
/*
Funkcja pobiera z odpowiedzi serwera WWW wielkosc pliku.
Informacje podana jest w parametrze CONTENT-LENGTH.
*/
int pos;
/* Zamieniamy na duże litery -> serwery różnie wysyłają */
szString = szString.UpperCase();
pos = szString.Pos("CONTENT-LENGTH: ");
if (pos ==0)
return 0;
else {
szString.Delete(1,pos+15);
pos = szString.Pos("\r\n");
szString.Delete(pos,szString.Length());
return szString.ToInt();
}
}
//---------------------------------------------------------------------------
bool TForm1::IsPartialContent(AnsiString szString)
{
/*
Funkcja pobiera z odpowiedzi serwera WWW kod stanu.
W przypadku kodu 206 jest możliwosc wznawiania pobierania.
*/
szString = szString.SubString(szString.Pos(" "),4);
if (szString.ToInt() == 206)
return true;
else
return false;
}
//---------------------------------------------------------------------------
void __fastcall TForm1::ClientSocketConnecting(TObject *Sender,
TCustomWinSocket *Socket)
{
Label1->Caption = "Łącze...";
}
//---------------------------------------------------------------------------
void __fastcall TForm1::ClientSocketDisconnect(TObject *Sender,
TCustomWinSocket *Socket)
{
if (TPlik) delete TPlik;
Label1->Caption = "Rozłączony.";
}
//---------------------------------------------------------------------------
void __fastcall TForm1::AdresKeyDown(TObject *Sender, WORD &Key,
TShiftState Shift)
{
if (Key == 13)
Pobierz->Click();
}
//---------------------------------------------------------------------------
void __fastcall TForm1::ClientSocketError(TObject *Sender,
TCustomWinSocket *Socket, TErrorEvent ErrorEvent, int &ErrorCode)
{
ErrorCode=0;
}
//---------------------------------------------------------------------------
void __fastcall TForm1::Label5Click(TObject *Sender)
{
ShellExecute(0, "open","http://rafal9661.za.pl/AutoIndex/", "", "",SW_SHOWNORMAL);
}
//---------------------------------------------------------------------------
void __fastcall TForm1::Label4Click(TObject *Sender)
{
ShellExecute(0, "open","http://rafal9661.za.pl/AutoIndex/", "", "",SW_SHOWNORMAL);
}
//---------------------------------------------------------------------------
Proszę o pomoc, a najlepiej o wyjasnienie problemu.