Solved

Posting a file to an HTTP server

Posted on 2000-02-28
21
179 Views
Last Modified: 2010-05-02
I have a CGI type web page that recieves an image file from a form that looks like:

<form enctype="multipart/form-data" action="http://server/accept.pl" method="post">
<input name="my_file" type="file" size="20">
</form>

The server accepts the file and saves it.

This works fine when posted from a web page but I need to be able to invoke it from VB. I've been trying to use the Internet Transfer Control with an Execute command but with no luck.

I don't have the option to transfer the file using FTP.

Thanks
0
Comment
Question by:baralong
  • 9
  • 8
  • 4
21 Comments
 

Author Comment

by:baralong
ID: 2571249
Adjusted points to 500
0
 

Author Comment

by:baralong
ID: 2572955
Adjusted points to 1000
0
 
LVL 2

Expert Comment

by:vmv
ID: 2575605
The easiest way is to use the WebBrowser control. Create a html file with your form and show it in the control. It is possible to submit your form with the Document property of this control.
0
 
LVL 14

Expert Comment

by:mcrider
ID: 2576119
Using the Navigate method of the webbrowser control you can send data...

To add this control to your program, right-click on the toolbox and select "Components..." then select "Microsoft Internet Controls" (SHDOCVW.DLL) from the Controls box.

The help file for this control is not installed on your system, but it is on the Visual Basic CD, in the directory:

  \TOOLS\UNSUPPRT\WEBBRWSR

Here is the help page for navigate:

NAVIGATE METHOD

Navigates to the resource identified by a Universal Resource Locator (URL), or to the file identified by a full path.

Syntax

object.Navigate url, flags, TargetFrameName, PostData, Headers

The GetProperty method syntax has these parts:

Part       Description
object      An object expression that evaluates to an object in the Applies To list.
Url      Required. A string expression that evaluates to the URL of the resource to display, or the full path of the file to display.
Flags      Optional. A constant or value that specifies whether to add the resource to the history list, whether to read from or write to the cache, and whether to display the resource in a new window. It can be a combination of the following values. See Settings below.
TargetFrameName      Optional. A string expression that evaluates to the name of a frame in which to display the resource.
PostData      Optional. Data to send to the server during the HTTP POST transaction. For example, the POST transaction is used to send data gathered by an HTML form. If this parameter does not specify any post data, the Navigate method issues an HTTP GET transaction. This parameter is ignored if URL is not an HTTP URL.
Headers      Optional. A value that specifies additional HTTP headers to send to the server. These headers are added to the default Internet Explorer headers. The headers can specify such things as the action required of the server, the type of data being passed to the server, or a status code. This parameter is ignored if URL is not an HTTP URL.
Settings

The settings for flags are:

Constant      Value      Description
navOpenInNewWindow      1      Open the resource or file in a new window.
navNoHistory      2      Do not add the resource or file to the history list. The new page replaces the current page in the list.
navNoReadFromCache      4      Do not read from the disk cache for this navigation.
navNoWriteToCache      8      Do not write the results of this navigation to the disk cache.



Cheers!
0
 
LVL 2

Expert Comment

by:vmv
ID: 2576394
mcrider, your method is too hard - you have to encode the file and do all other stuff yourself while it can be done by the WebBrowser control... And your answer is very incomplete, please post such answers as comments.
0
 
LVL 14

Expert Comment

by:mcrider
ID: 2576481
vmv, I know when to post an answer... I suggest you find my name in the top 15 experts in this category.

As for having to URLencode the Post buffer being sent, Adding the following to a module and calling the URLencode function will accomplish this.


    Function ReplaceInString(Source As String, TheString As String, TheReplaceString As String) As String
        Dim iVal As Integer
        Dim Workspace As String
        Workspace = Source
        iVal = 1
        Do
            iVal = InStr(iVal, Workspace, TheString, 1)
            If iVal = 0 Then Exit Do
            Workspace = Left$(Workspace, iVal - 1) + TheReplaceString + Mid$(Workspace, iVal + Len(TheString))
            iVal = iVal + 1
        Loop
        ReplaceInString = Workspace
    End Function
    Function StripHTML(Source As String) As String
        Dim iVal As Long
        Dim Buf As String
        Dim lBuf As String
        Dim rBbuf As String
        iVal = InStr(1, Source, "<")
        If iVal = 0 Then
            StripHTML = Source
            Exit Function
        End If
        lBuf = Left$(Source, iVal - 1)
        iVal = InStr(iVal, Source, ">")
        rbuf = Mid$(Source, iVal + 1)
        Buf = lBuf + " " + rbuf
       
        Do
            iVal = InStr(1, Buf, "<")
            If iVal = 0 Then
                StripHTML = Buf
                Exit Do
            End If
            lBuf = Left$(Buf, iVal - 1)
            iVal = InStr(iVal, Buf, ">")
            rbuf = Mid$(Buf, iVal + 1)
            Buf = lBuf + " " + rbuf
        Loop
    End Function
    Function URLdecode(Source As String) As String
        Dim lBuf As String
        Dim iVal As Long
        lBuf = ReplaceInString(Source, "+", " ")
        iVal = 1
        Do
            iVal = InStr(iVal, lBuf, "%")
            If iVal = 0 Then Exit Do
            lBuf = Left$(lBuf, iVal - 1) _
                + Chr$(CLng("&H" + Mid$(lBuf, iVal + 1, 2))) _
                + Mid$(lBuf, iVal + 3)
            iVal = iVal + 1
        Loop
        URLdecode = lBuf
    End Function
    Function URLencode(Source As String) As String
        Dim iVal As Long
        Dim lBuf As String
        Dim lArray As Variant
        lBuf = Source
        For Each lArray In Array("%", "&", "+", "~", "`", "!", "@", "#", "$", "^", "*" _
            , "(", ")", "-", "_", "=", "{", "[", "}", "]", "|", "\", ":", ";", "'", "<" _
            , ">", "?", ",", ".", "/", Chr$(34))
            lBuf = ReplaceInString(lBuf, CStr(lArray), "%" + Right$("0" + Hex(Asc(lArray)), 2))
        Next
        lBuf = ReplaceInString(lBuf, " ", "+")
        iVal = 0
        Do
            iVal = iVal + 1
            If iVal > Len(lBuf) Then Exit Do
            lArray = Mid$(lBuf, iVal, 1)
            If Asc(lArray) <= 31 Or Asc(lArray) >= 127 Then
                lBuf = ReplaceInString(lBuf, CStr(lArray), "%" + Right$("0" + Hex(Asc(lArray)), 2))
            End If
        Loop
        URLencode = lBuf
    End Function
0
 
LVL 2

Expert Comment

by:vmv
ID: 2578781
mcrider,
>I suggest you find my name in the top 15 experts in this category.

This just means that you was here for a long time posting comments as answers.

>As for having to URLencode the Post buffer

Why you want to write kilobytes of unneded (maybe buggy) code while all this stuff is already implemented in the WebBrowser? Why you don't post assembly source for this?
0
 

Author Comment

by:baralong
ID: 2579159
Thanks for the help so far.

mcrider, I don't see how any of the functions help me send a binary file. I realise I need to encode the file but how?

I haven't had a chance to try either approach out, and won't until Monday.
0
 
LVL 14

Expert Comment

by:mcrider
ID: 2579772
baralong,

Basically, you do this:

Dim PostData As String
Dim FileData As String

'Put your code to read the file into the string variable "FileData" here...

'Convert the string into a URL Encoded string...
PostData = URLencode(FileData)

'Send the encoded data to your server...
WebBrowser1.Navigate "http://server/accept.pl", , , PostData


Cheers!
0
 

Author Comment

by:baralong
ID: 2590898
mcrider, sorry but I can't get this to work. My CGI script can't doesn't recieve the file correctly

vmv, your method seems promising. I have to admit I'm quite a novice when it comes to VB so I'm probably making this more complex than it needs to be.

The problem I'm having with this is: I get the Document property but can't seem to get any lower, I thought it would be an "HTMLDocument" but it's not working well.

if the form detail is:

<form enctype="multipart/form-data" action="http://server/accept.pl" method="post" id="form1">
<input name="my_file" type="file" size="20" id="my_file">
<input type="submit" id="sub">
</form>

can you post code to set the value of "my_file" and then submit the form.

I have been trying with:

Dim HTMLDoc As HTMLDocument
Set HTMLDoc = WB.Document ' OK up to here

Dim Elem As HTMLFormElement
Set Elem = HTMLDoc.Forms("form1") ' here is where it breaks.

Thanks
0
Top 6 Sources for Identifying Threat Actor TTPs

Understanding your enemy is essential. These six sources will help you identify the most popular threat actor tactics, techniques, and procedures (TTPs).

 
LVL 14

Expert Comment

by:mcrider
ID: 2591017
baralong,

Post a copy of your perl CGI script...


Cheers!®©
0
 
LVL 2

Expert Comment

by:vmv
ID: 2591040
Unfortunately I never tried to do something similar, so I don't know how to get this to work - that comment was just an idea of a way to work on. I suggest you to look for some example in the MSDN.
0
 
LVL 14

Expert Comment

by:mcrider
ID: 2591050
baralong,

If you dont have Service Pack 2 or 3 installed, the INET "post" will not work.  See the following microsoft KB articles:

FIX: Internet Transfer Control 5.0 "POST" Request Doesn't Work
http://support.microsoft.com/support/kb/articles/Q167/7/06.asp?LNG=ENG&SA=MSDN&FR=0
 
INFO: Visual Studio 97 Service Packs - What, Where, and Why
http://support.microsoft.com/support/kb/articles/Q170/3/65.ASP

INFO: Visual Basic 5.0 Fixes in Visual Studio 97 Service Pack 2
http://support.microsoft.com/support/kb/articles/Q171/5/54.asp?LNG=ENG&SA=MSDN&FR=0
 

Cheers!®©

 
0
 

Author Comment

by:baralong
ID: 2591384
mcrider,

I'm at home and I don't have a copy of the script but the detail that saves the file, but it's basically something like:

use CGI;
$query= new CGI;
$fileup = $query->param('my_file');

# extract its name
$strFilename = $fileup;
$strFilename =~ s/.*\\([^\s\\]+)$/$1/;

# build a name for the file on the server
$localFile =~ s/\\[^\s\\]+$//;
$localFile .= "\path\" . $strFilename;
 
# save the file
open (OUTFILE,">$localFile");
binmode($fileup);
binmode(OUTFILE);
while ($bytesread=read($fileup,$buffer,1024)) {
print OUTFILE $buffer;
}

I think the problem with the URLEncode function you posted is that it doen't encode the file and other parameters in a multipart format.

I've found it frustrating, and surprisingly dificult, trying to send and recieve a file over HTTP using VB and ASP (I couldn't get the posting acceptor to work, so I switched to perl). My background has more perl and it seems much esier to do things that way.

Thanks for the help so far, but I think vmv's approach might workout faster, any pointers on that method?
0
 
LVL 14

Expert Comment

by:mcrider
ID: 2591490
Have you read this from microsoft:

HOWTO: Use the PostData Parameter in WebBrowser Control
http://support.microsoft.com/support/kb/articles/Q174/9/23.ASP?LNG=ENG&SA=MSDN&FR=0
 
By the way, you never said... Are you using Service Pack 3???  If not, you will need to install it...


Cheers!®©
0
 
LVL 14

Accepted Solution

by:
mcrider earned 1000 total points
ID: 2608037
Have you read this from microsoft:

HOWTO: Use the PostData Parameter in WebBrowser Control
http://support.microsoft.com/support/kb/articles/Q174/9/23.ASP?LNG=ENG&SA=MSDN&FR=0
 
By the way, you never said... Are you using Service Pack 3???  If not, you will need to install it...


Cheers!®©

0
 

Author Comment

by:baralong
ID: 2632812
Hi mcrider,

Sorry it's been a while, well I've nearly got your answer working, I've found documentation on how to encode the file.

The only trouble is that the header parameter gets trashed between the Navagate method and the beforeNavagate2 event.  Any ideas?

Thanks
0
 
LVL 14

Expert Comment

by:mcrider
ID: 2633386
What do you mean... "Gets trashed"?
0
 

Author Comment

by:baralong
ID: 2634367
OK if my header for the navigate is "content-type: multipart/formdata; boundary=gc0p4Jq0M2Yt08j34c0p"

When I get to the beforeNavigate2 event the contents of the header reads something like "content-typcontent-type: multipart/formdata; boundary=gc0p4Jq0M2Yt08j34c0p"

the parameter is read only so I can't modify it.  I'll double check the service pack status later.

0
 

Author Comment

by:baralong
ID: 2635287
Well I finally got it to work.

I've worked around the trashing of the headers by adding a string of spaces to the end of the header. (BTW I do have SP3 installed)

When sending a binary file you have to read it into a byte array and then convert it to unicode and store it in a string (it makes life a bit easier) build up the rest of the string and then convert it back from unicode and store it in a byte array.

I had a bit more trouble with the perl script at the other end but found that if I put in two boundaries in a row then it would see the attachment.

Thanks again.

Any way here is the code:

Private Sub post_Click()
    Dim iHandle As Integer
    Dim sFile As String
    Dim sTemp As String
    Dim sHeaders As String
    Dim sBoundry As String
    Dim sPost As String
    Dim lSpot As Long
    Dim lFind As Long
    Dim bTemp() As Byte
   
    sFile = "H:\1.jpg"
    iHandle = FreeFile
    Open sFile For Binary Access Read As iHandle
    If iHandle Then
        ReDim bTemp(LOF(iHandle)) As Byte
        Get #iHandle, , bTemp
        sTemp = StrConv(bTemp, vbUnicode)
        Close iHandle
    End If
   
    sBoundry = "AaBbQQbBaA"
   
    sHeaders = "Content-Type: multipart/form-data, boundry=" & sBoundry & _
               vbCrLf & "                                                                            "
   
    sPost = "-----------" & sBoundry & vbCrLf & _
            "-----------" & sBoundry & vbCrLf & _
            "Content-Disposition: form-data; name=""my_file""; filename=""" & _
            sFile & """" & vbCrLf & _
            "Content-Type: image/jpg" & vbCrLf & _
            "Content-Transfer-Encoding: binary" & vbCrLf & vbCrLf & sTemp & _
            vbCrLf & "-----------" & sBoundry & "--" & _
            vbCrLf & "-----------" & sBoundry & "--" & vbCrLf
   
    bTemp = StrConv(sPost, vbFromUnicode)
   
    WB.Navigate "http://server3/postingwork/Finish.pl", navNoReadFromCache, "", bTemp, sHeaders
       
         
End Sub
0
 
LVL 14

Expert Comment

by:mcrider
ID: 2638925
Thanks for the points! Glad I could help!


Cheers!®©
0

Featured Post

Highfive + Dolby Voice = No More Audio Complaints!

Poor audio quality is one of the top reasons people don’t use video conferencing. Get the crispest, clearest audio powered by Dolby Voice in every meeting. Highfive and Dolby Voice deliver the best video conferencing and audio experience for every meeting and every room.

Join & Write a Comment

Introduction In a recent article (http://www.experts-exchange.com/A_7811-A-Better-Concatenate-Function.html) for the Excel community, I showed an improved version of the Excel Concatenate() function.  While writing that article I realized that no o…
You can of course define an array to hold data that is of a particular type like an array of Strings to hold customer names or an array of Doubles to hold customer sales, but what do you do if you want to coordinate that data? This article describes…
Get people started with the utilization of class modules. Class modules can be a powerful tool in Microsoft Access. They allow you to create self-contained objects that encapsulate functionality. They can easily hide the complexity of a process from…
Show developers how to use a criteria form to limit the data that appears on an Access report. It is a common requirement that users can specify the criteria for a report at runtime. The easiest way to accomplish this is using a criteria form that a…

757 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question

Need Help in Real-Time?

Connect with top rated Experts

16 Experts available now in Live!

Get 1:1 Help Now