0

I'm trying to upload a plain text file to a classic asp page and getting an error.

<p>Microsoft VBScript runtime </font> <font face="Arial" size=2>error '800a01a8'</font>
<p>
<font face="Arial" size=2>Object required: 'fields(...)'</font>

Html Code

<form action="upload.asp" method=post ENCTYPE="multipart/form-data">
      File :
<input type="file" class="form_field" name="File1" accept="image/jpeg">
<input type="submit" class="form_pb" Name="Action" value="Send File">
</form>

Vba Code to set the post variable and send the request.

    Const STR_BOUNDARY  As String = "a832972453175"
    Dim nFile           As Integer
    Dim baBuffer()      As Byte
    Dim sPostData       As String
....

'--- read file
nFile = FreeFile
Open sFileName For Binary Access Read As nFile
    If LOF(nFile) > 0 Then
        ReDim baBuffer(0 To LOF(nFile) - 1) As Byte
        Get nFile, , baBuffer
        sPostData = StrConv(baBuffer, vbUnicode)
    End If
Close nFile

sPostData = "--" & STR_BOUNDARY & vbCrLf & _
        "Content-Disposition: form-data; name=""File1""; filename=""" & Mid$(sFileName, InStrRev(sFileName, "\") + 1) & """" & vbCrLf & _
            "Content-Type: text/plain" & vbCrLf & vbCrLf & _
            sPostData & vbCrLf & vbCrLf & _
            STR_BOUNDARY & vbCrLf & _
            "Content-Disposition: form-data; name=""Action""" & vbCrLf & _
             vbCrLf & "Send File" & vbCrLf & _
            "--" & STR_BOUNDARY & "--"

With WinHttpReq

'UPLOAD REQUEST
.Open "POST", sUrl, False
.setRequestHeader "Content-Type", "multipart/form-data; boundary=" & STR_BOUNDARY
.setRequestHeader "User-Agent", "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0)"
.Send (sPostData)
end with

I have access to the source code of the page that is a classic asp page and the upload is executed with a vbscript running at the server.

The error is that the File1 argument = "" and then the upload doesnt start.

Despite the attribute accept in the html code is only for "image/jpeg" I can upload normally when navigating with a browser.

I think is something wrong with my sPostData variable in Vba code.

The file with the upload functions is here: https://www.royalholloway.ac.uk/resources/ASP/PStruh-CZ/1.3/upload.inc

Anyone can see what am I doing wrong?

luckasx
  • 359
  • 1
  • 6
  • 20
  • The error points to `Object required: 'fields(...)'` the provided code shows no mention of the `fields` collection so I would suggest you're looking in the wrong place. Did the error not contain a page name and line number? – user692942 Mar 18 '15 at 14:58
  • The error is caused because the result of the function GetUpload at the file upload.inc is empty. Like I posted there is a condition to start the upload (if Fields("File1").FileName = "" do nothing else start the upload) – luckasx Mar 18 '15 at 15:26
  • I don't think that will ever work like that, your trying to pass in effect what is binary multipart data as a string. The multipart form post handles all the boundary information you can't pass that before it's processed, you'll just end up with a malformed multipart. Try viewing the request using [Fiddler](http://www.telerik.com/fiddler) to see what the RAW request looks like. – user692942 Mar 18 '15 at 16:01
  • I viewed the request with Firebug. And I set the sPostData to be like the request in the browser. I will create a similar page with the same server-side code and then maybe find out something. Thanks. – luckasx Mar 18 '15 at 16:33

2 Answers2

1

I created a copy of the upload page and looked for something wrong. I found out that the boundary reconigzed by the page was "myboundary" + ;Charset=UTF-8.

The solution in this case is add the charset in the request header.

With WinHttpReq

'UPLOAD REQUEST
.Open "POST", sUrl, False
.setRequestHeader "Content-Type", "multipart/form-data; Charset=UTF-8;boundary=" & STR_BOUNDARY
.setRequestHeader "User-Agent", "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0)"
.Send (sPostData)
end with

.setRequestHeader "Content-Type", "multipart/form-data; Charset=UTF-8; boundary=" & STR_BOUNDARY

luckasx
  • 359
  • 1
  • 6
  • 20
0

Today I discovered I can upload files (either text or binary) from VBA Excel (could be Word, MSAccess or Outlook too) through standard POST (at least it works for small files). First, it opens a file in a byte array. Second, it converts the byte array to a Base64 String. Third, it uses an IE object to fill a form and submit it, with no direct user interaction.

Public Function UploadFileTo(sourceFile As String, uURL As String, nameFieldID As String, dataFieldID As String, formID As String) As Boolean
    UploadFileTo = False
    ''---------------------------
    Dim nome As String, dados64
    Dim bs() As Byte
    nome = Dir(sourceFile)
    If (nome = "") Then Exit Function
    ''
    bs = ReadFile2("" & sourceFile) ' loads the file into a byte array
    dados64 = Base64Encode(bs) ' encodes it to base64 and returns as String
    ''
    Dim ie As InternetExplorerMedium
    'Dim ie 'As Object
    Dim docweb As Object
    Set ie = New InternetExplorerMedium
    'Set ie = CreateObject("InternetExplorerMedium")
    'Set ie = GetObject("new:{D5E8041D-920F-45e9-B8FB-B1DEB82C6E5E}")
    ie.Navigate2 uURL
    ie.Visible = True
    While ie.Busy: DoEvents: Wend
    While ie.ReadyState <> 4: DoEvents: Wend
    ''
    Set docweb = ie.Document
    docweb.all(nameFieldID).Value = nome
    docweb.all(dataFieldID).Value = dados64
    docweb.all(formID).Submit
    While ie.Busy: DoEvents: Wend
    While ie.ReadyState <> READYSTATE_COMPLETE: DoEvents: Wend
    ''
    ie.Quit
    ''---------------------------
    UploadFileTo = True
End Function

For example: to call the following page:

if UploadFileTo("C:\myPath\myFile.txt", "http://www.website.com/page.html", "myFileNameField", "myFileData", "myDistantForm") then
    MsgBox "File Uploaded successfully"
else
    MsgBox "Failed."
end if

It calls the URL http://www.website.com/page.html

<html>
 <head>
  <title>Sending files within POST with base64 encoding</title>
 </head>
 <body>
  <form id="myDistantForm" action="teste.cgi" method="POST">
   Name: <input type="text" id="finame" name="arq_nome" value="">    <br>
   Data: <textarea name="myFileNameField" id="fidata" rows="30" cols="120"></textarea> <br>
   <input type="submit" name="myFileData" value="Send the File"> <br>
  </form>
 </body>
</html>

IMPORTANT: The server must be able to decode a Base64-encoded string and, then, save the decoded data into a file in the desired server directory, using the given name (or some auto-generated, unique name), no matter if the target server runs ASP, PHP, JSP, CGI/ISAPI or whatever.

To read any file to a Byte array: how can I read a binary file using VBA?

To encode that array into a Base64 String: How do I base64 encode a string efficiently using Excel VBA?

Community
  • 1
  • 1
  • Well... to adapt it to use in Classic ASP, you can follow my response adapting it by removing everything related to Excel. Or just go through its essence: first, load the file in a byte array, then convert this data in a Base64 string, then send this string to the destination page (as a common FORM request, not as in a upload form). The server must be able to decode the base64 String and save it in a file with the same name and extension. At least, it was tested with small files, including videos. Text files also work very well. – Fiszpan Porcel Jun 04 '15 at 18:22