Board index » delphi » Sending files to a web server

Sending files to a web server


2006-05-09 04:54:41 PM
delphi154
HI,
I want to send files to a web server (www.mysite.gr) via HTTP using PUT
function (not POST).
After many tries and searches I wrote the code bellow. It seems to work. No
errors. BytesWritten are allways same as bytesReaded and the label shows the
true size of tranmission. The network trafic shows that the entire file has
tranfered. But were is it stored ? I can not see it anywhere at the web
server.
What happens ?
if can somebody help me, I am desperate
thanks in advance
*********************************************************
unit UnitPUT1;
interface
uses
Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs,
StdCtrls, winInet;
type
TForm1 = class(TForm)
Button1: TButton;
OpenDialog1: TOpenDialog;
Label1: TLabel;
procedure Button1Click(Sender: TObject);
private
{ Private declarations }
public
{ Public declarations }
end;
var
Form1: TForm1;
implementation
{$R *.DFM}
procedure TForm1.Button1Click(Sender: TObject);
Const BUFFERSIZE = 4096 ;
var Data : array[0..BUFFERSIZE - 1] of Byte;
BufferIn : INTERNET_BUFFERS;
hSession,
hConnect,
hRequest : HINTERNET;
OK : boolean;
bytesReaded,
bytesWritten,
BytesWrittenTotal,
dw : dword;
lpMsgBuf : pChar;
begin
if not OpenDialog1.Execute then exit;
hSession := InternetOpen('Test', INTERNET_OPEN_TYPE_PRECONFIG,
PChar(''), PChar(''), 0);
hConnect := InternetConnect(hSession, pchar('www.mysite.gr'),
INTERNET_DEFAULT_HTTP_PORT, PChar('myusername'), PChar('myPassword'),
INTERNET_SERVICE_HTTP, 0, 0);
hRequest := HttpOpenRequest(hConnect, PChar('PUT'),
PChar('www.mysite.gr/'+extractFileName(OpenDialog1.FileName)),
PChar(''), PChar(''), 0, INTERNET_FLAG_NO_CACHE_WRITE, 0);
BufferIn.dwStructSize := sizeof(BufferIn);
BufferIn.dwBufferTotal := 0;
BufferIn.dwBufferLength := 0;
BufferIn.dwHeadersLength:= 0;
BufferIn.dwHeadersTotal := 0;
BufferIn.dwOffsetHigh := 0;
BufferIn.dwOffsetLow := 0;
BufferIn.lpcszHeader := 0;
BufferIn.lpvBuffer := 0;
BufferIn.Next := 0;
with TFilestream.Create(OpenDialog1.FileName,fmOpenRead) do try
BufferIn.dwBufferTotal := Size;
OK := HttpSendRequestEx(hRequest, @BufferIn, 0, 0, 0);
if not OK then begin
dw := GetLastError;
FormatMessage(
FORMAT_MESSAGE_ALLOCATE_BUFFER or FORMAT_MESSAGE_FROM_SYSTEM,
nil,
dw,
LANG_NEUTRAL,
LPTSTR(lpMsgBuf),
0, nil);
showmessage(lpMsgBuf);
end;
BytesWrittenTotal := 0;
while OK do begin
bytesReaded := read(Data[0],BUFFERSIZE);
OK := (bytesReaded>0)
and InternetWriteFile(hRequest, @Data, bytesReaded,
BytesWritten);
if OK then begin
BytesWrittenTotal := BytesWrittenTotal + BytesWritten;
label1.Caption := intToStr(BytesWrittenTotal);
application.ProcessMessages;
end;
end;
OK := HttpEndRequest(hRequest, 0, 0, 0);
free;
except end;
InternetCloseHandle(hRequest);
InternetCloseHandle(hConnect);
InternetCloseHandle(hSession);
end;
end.
************************************************
 
 

Re:Sending files to a web server

I forgot to tell that the site is hosted on a commerecial server that runs
APACHE 2.0 .
I don't know if it has any restrictions to HTTP uploading. I am sure that it
hasn't for FTP uploading.
And it permits me to upload files with microsoft frontpage.
 

Re:Sending files to a web server

"dpap" <XXXX@XXXXX.COM>writes
Quote
But were is it stored ?
That is up to the server to decide.
Quote
if can somebody help me, I am desperate
None of your WinInet code is doing any error checking at all. Try this code
instead:
procedure TForm1.Button1Click(Sender: TObject);
const
BUFFERSIZE = 4096 ;
var
Data : array[0..BUFFERSIZE - 1] of Byte;
BufferIn : INTERNET_BUFFERS;
hSession, hConnect, hRequest : HINTERNET;
OK : boolean;
bytesWritten, bytesWrittenTotal : DWORD;
bytesRead: Integer;
FS : TFileStream;
Size: Integer;
begin
if not OpenDialog1.Execute then Exit;
FS := TFileStream.Create(OpenDialog1.FileName, fmOpenRead or
fmShareDenyWrite);
try
hSession := InternetOpen('Test', INTERNET_OPEN_TYPE_PRECONFIG,
nil, nil, 0);
if hSession = 0 then RaiseLastOSError;
try
hConnect := InternetConnect(hSession,
PChar('www.mysite.gr'), INTERNET_DEFAULT_HTTP_PORT, PChar('myusername'),
PChar('myPassword'), INTERNET_SERVICE_HTTP, 0, 0);
if hConnect = 0 then RaiseLastOSError;
try
hRequest := HttpOpenRequest(hConnect, PChar('PUT'),
PChar('www.mysite.gr/' + ExtractFileName(OpenDialog1.FileName)), nil,
nil, 0, INTERNET_FLAG_NO_CACHE_WRITE, 0);
if hRequest = 0 then RaiseLastOSError;
try
Size := FS.Size;
FillChar(@BufferIn, SizeOf(BufferIn), 0);
BufferIn.dwStructSize := sizeof(BufferIn);
BufferIn.dwBufferTotal := Size;
if not HttpSendRequestEx(hRequest, @BufferIn, nil,
0, 0) then RaiseLastOSError;
bytesWrittenTotal := 0;
while FS.Position < Size do
begin
bytesRead := FS.Read(Data[0], BUFFERSIZE);
if bytesRead < 1 then RaiseLastOSError;
if not InternetWriteFile(hRequest, Data[0],
bytesRead, bytesWritten) then RaiseLastOSError;
Inc(bytesWrittenTotal, bytesWritten);
Label1.Caption := IntToStr(bytesWrittenTotal);
Application.ProcessMessages;
end;
if not HttpEndRequest(hRequest, nil, 0, 0) then
RaiseLastOSError;
finally
InternetCloseHandle(hRequest);
end;
finally
InternetCloseHandle(hConnect);
end;
finally
InternetCloseHandle(hSession);
end;
finally
FS.Free;
end;
end.
With that said, have you considered using a ready-made HTTP component yet?
HTTP is a complex protocol to implement manually. For example, you can use
the HTTP component from Indy (www.indyproject.org):
procedure TForm1.Button1Click(Sender: TObject);
var
FS : TFileStream;
begin
if OpenDialog1.Execute then
begin
FS := TFileStream.Create(OpenDialog1.FileName, fmOpenRead or
fmShareDenyWrite);
try
IdHTTP1.Put('www.mysite.gr/' +
ExtractFileName(OpenDialog1.FileName), FS);
finally
FS.Free;
end;
end;
end.
Gambit
 

Re:Sending files to a web server

Quote
>But were is it stored ?

That is up to the server to decide.
Doesn't server store data in specified directory and filename ? Then why we
send this information ?
I try your code with the same results with mine. No errors, no file created
at server site. The data travel across the wire. it is obvious but ........
I have try indyHTTP component many times, and one more time now with your
snipet, but allways i receive error "HTTP/1.1 403 Forbidden" . The same
error code i receive with ics component. I am worring if there are some
restrictions on server.
Have you any idea ?
thanks again
 

Re:Sending files to a web server

Quote
I have try indyHTTP component many times, and one more time now with your
snipet, but allways i receive error "HTTP/1.1 403 Forbidden" . The same
error code i receive with ics component. I am worring if there are some
restrictions on server.
Have you any idea ?
This is a webserver issue, not a HTTP component issue. that is why you have
same result with indy and ICS. I can not help you with Apache configuration.
You should probably post a question in an Apache newsgroup.
Contribute to the SSL Effort. Visit www.overbyte.be/eng/ssl.html
 

Re:Sending files to a web server

dpap writes:
Quote
Doesn't server store data in specified directory and filename ? Then
why we send this information ?
Cool. So you think I can upload a text file and tell the server to store it
as "c:\ntldr"? Not really...
--
Ben
 

Re:Sending files to a web server

"dpap" <XXXX@XXXXX.COM>writes
Quote
Doesn't server store data in specified directory and filename ?
The file is uploaded to the specified URL. Where the URL physically resides
on the server is a matter of configuration on the server's end.
Quote
I try your code with the same results with mine. No errors, no file
created
at server site. The data travel across the wire. it is obvious but
........
Did you try having WinInet retreive the HTTP response to the PUT command?
My guess would be that the PUT command is failing with an error message from
the server.
Quote
I have try indyHTTP component many times, and one more time now with
your snipet, but allways i receive error "HTTP/1.1 403 Forbidden" .
Then you are obviously trying to upload a file to a URL that you are not
allowed to upload to. In your code snippets, you are trying to upload to
the root folder of the web site. That folder is usually read-only. You
will likely need to have your server admin set asside a writable folder on
the server that you can upload your files to, ie:
hRequest := HttpOpenRequest(hConnect, PChar('PUT'),
PChar('www.mysite.gr/uploads/' +
ExtractFileNameOpenDialog1.FileName)), nil, nil, 0,
INTERNET_FLAG_NO_CACHE_WRITE, 0);
Quote
The same error code i receive with ics component.
All the more reason to think you are simply uploading to the wrong folder in
the first place, if you are having the same problem with three different
libraries.
Quote
I'm worring if there are some restrictions on server.
Yes, there is.
Gambit
 

Re:Sending files to a web server

Quote
Cool. So you think I can upload a text file and tell the server to store
it
as "c:\ntldr"? Not really...
No. If you see my code, I meen (and InternetConnect function requires)
password protected and with write permition URLs on server. The same that I
already can do with FTP but using HTTP
thanks
 

Re:Sending files to a web server

Quote
Did you try having WinInet retreive the HTTP response to the PUT command?
My guess would be that the PUT command is failing with an error message
from
the server.
No I haven't try it. I rely to InternetWriteFile's result.
Quote
Then you are obviously trying to upload a file to a URL that you are not
allowed to upload to.
No. I have write permition to this and all the inner directories (I already
use them for uploading with FTP succesfuly)
I search for APACHE HTTP server and PUT command. I found that it can't
manage directly this command. It needs a CGI script to do this. Now I'm
trying to find out how can do it.
Any help is valuable
thanks again
 

Re:Sending files to a web server

dpap writes:
Quote
No. If you see my code, I meen (and InternetConnect function requires)
password protected and with write permition URLs on server. The same
that I already can do with FTP but using HTTP
An FTP and HTTP server can only save files within their directory tree; and
only those to which the account running the server has [write] access. The
root of the site usually is not writeably by the http server.
--
Ben
 

Re:Sending files to a web server

"dpap" <XXXX@XXXXX.COM>writes
Quote
No I haven't try it. I rely to InternetWriteFile's result.
That is not enough. All that does is tells you whether the file data was
written to the socket, not whether the server accepted the data. You still
need to look at the HTTP response information to know whether the server
accepted or rejected the PUT command itself.
Quote
No. I have write permition to this and all the inner directories (I
already
use them for uploading with FTP succesfuly)
The FTP folders have nothing to do with the HTTP folders. Just because you
have write permissions on the FTP server does NOT mean you also have write
permissions on the HTTP server. The two are completely separate from each
other.
Quote
I search for APACHE HTTP server and PUT command. I found that it
can't manage directly this command. It needs a CGI script to do this.
You need to use the POST command then.
Gambit
 

Re:Sending files to a web server

Quote
An FTP and HTTP server can only save files within their directory tree;
and
only those to which the account running the server has [write] access. The
root of the site usually is not writeably by the http server.
In my code I use root directory only for simplicity. Actualy I use inner
dirs although I have write access even at root directory (I'm able to FTP
files in it). The problem isn't this.
I found this in APACHE forums :
"One of the most common questions we get asked is whether Apache supports
web publishing with the PUT method. Netscape Navigator Gold, AOLPress and
Amaya all support this method of publishing pages. Technically the answer is
yes, Apache supports that method. However it does not come with any scripts
or programs which actually implement the publishing behaviour"
So I download some cgi examples and I am trying to make them to work.
unfortunatly without succes until now because I am novice.
I hope some experts can help me
thanks again
 

Re:Sending files to a web server

dpap writes:
Quote
In my code I use root directory only for simplicity. Actualy I use
inner dirs although I have write access even at root directory (I'm
able to FTP files in it). The problem isn't this.
Bear in mind that FTP and HTTP are two quite different things - the FTP
server runs under the logged-in user's context while the HTTP server often
uses a service account of its own (I know that IIS can impersonate the
authenticated user, though).
Quote
I found this in APACHE forums :
"One of the most common questions we get asked is whether Apache
supports web publishing with the PUT method. Netscape Navigator Gold,
AOLPress and Amaya all support this method of publishing pages.
Technically the answer is yes, Apache supports that method. However it
does not come with any scripts or programs which actually implement
the publishing behaviour" So I download some cgi examples and I'm
trying to make them to work. unfortunatly without succes until now
because I am novice. I hope some experts can help me
Do you have a '{*word*192}' Apache or does it support PHP?
usphp.com/manual/en/features.file-upload.put-method.php
Is there a special reason you are using PUT rather than POST?
www.tizag.com/phpT/fileupload.php
--
Ben
 

Re:Sending files to a web server

"dpap" <XXXX@XXXXX.COM>writes
Quote
"One of the most common questions we get asked is whether Apache supports
web publishing with the PUT method. Netscape Navigator Gold, AOLPress
and Amaya all support this method of publishing pages. Technically the
answer
is yes, Apache supports that method. However it does not come with any
scripts or programs which actually implement the publishing behaviour"
The PUT command doesn't require any CGI scripts in order to function. It is
a native HTTP command that saves the uploaded file directly to the server's
file system. If a server supports the PUT command, then it already has
everything it needs. CGI scripts are only needed for the POST command.
Gambit
 

Re:Sending files to a web server

Quote
Do you have a '{*word*192}' Apache or does it support PHP?
yes.
Quote
Is there a special reason you are using PUT rather than POST?
No. I thought it was the easiest way because POST requirs an HTML form to
invoke the PHP script or CGI, but I found that POST is easiest.
Finally I manage it. I made a HTML page and a PHP script following the
links you send me, and it works !
many thanks