Как отправить файл средствами VBscript

Sep 30, 2012 10:38

Пришлось поработать с VBscript, язык для меня новый и неприятный :) Долго разбирался как сделать вещь, простую для php. Перелопатил много интернетов и собрал таки нужные функции в одном месте.

Задача отправить файл в форму с помощью POST-запроса. Форма простейшая:
[HTML]

Для отправки используется XMLHTTPrequest. Передаём заголовки Content-Type и Content-Length. Затем грамотно формируем тело POST: заголовки и сам файл.
С текстовым файлом проще, можно его крепить простым текстом, но возможны проблемы с кодировками. Поэтому лучше передавать файл как binary. В этом случае в теле POST указываем Content-Type как application/upload или octet/stream. Сам файл предварительно тщательно готовится. Рецепт приготовления файла писал не сам, а взял тута.

В итоге получилось что-то такое:
[VBscript]
Function UploadFile(FileName,Url)
  srcFolder = left(WScript.ScriptFullName,(Len(WScript.ScriptFullName))-(len(WScript.ScriptName)))
  strURL = "http://Url/form.php"
  FileContents = FileGet(srcFolder+FileName)
  Boundary = "--boundaryasyoulike--"
  FieldName = "filedata"
  Tosend = BuildFormData(FileContents, Boundary, FileName, FieldName)
  Set HTTP = WScript.CreateObject("Microsoft.XMLHTTP")
  HTTP.open "POST", strURL, false
  HTTP.setRequestHeader "Content-Type", "multipart/form-data; boundary="+Boundary
  HTTP.setRequestHeader "Content-Length", LEN(Tosend)
  HTTP.send Tosend
  UploadFile = HTTP.responseText
  Set HTTP = Nothing
End Function

Function FileGet(FileN)
  Dim Stream: Set Stream = CreateObject("ADODB.Stream")
  Stream.Type = 1 'Binary
  Stream.Open
  Stream.LoadFromFile FileN
  FileGet = Stream.Read
  Stream.Close
End Function

Function BuildFormData(FileContents, Boundary, FileN, FieldName)
  Dim FormData, Pre, Po
  Const ContentType = "application/upload"

'The two parts around file contents In the multipart-form data.
  Pre = "--" + Boundary + vbCrLf + mpFields(FieldName, FileN, ContentType)
  Po = vbCrLf + "--" + Boundary + "--" + vbCrLf

'Build form data using recordset binary field
  Const adLongVarBinary = 205
  Dim RS: Set RS = CreateObject("ADODB.Recordset")
  RS.Fields.Append "b", adLongVarBinary, Len(Pre) + LenB(FileContents) + Len(Po)
  RS.Open
  RS.AddNew
    Dim LenData
    'Convert Pre string value To a binary data
    LenData = Len(Pre)
    RS("b").AppendChunk (StringToMB(Pre) & ChrB(0))
    Pre = RS("b").GetChunk(LenData)
    RS("b") = ""

'Convert Po string value To a binary data
    LenData = Len(Po)
    RS("b").AppendChunk (StringToMB(Po) & ChrB(0))
    Po = RS("b").GetChunk(LenData)
    RS("b") = ""

'Join Pre + FileContents + Po binary data
    RS("b").AppendChunk (Pre)
    RS("b").AppendChunk (FileContents)
    RS("b").AppendChunk (Po)
  RS.Update
  FormData = RS("b")
  RS.Close
  BuildFormData = FormData
End Function

Function mpFields(FieldName, FileN, ContentType)
  Dim MPTemplate 'template For multipart header
  MPTemplate = "Content-Disposition: form-data; name=""{field}"";" + _
   " filename=""{file}""" + vbCrLf + _
   "Content-Type: {ct}" + vbCrLf + vbCrLf
  Dim Out
  Out = Replace(MPTemplate, "{field}", FieldName)
  Out = Replace(Out, "{file}", FileN)
  mpFields = Replace(Out, "{ct}", ContentType)
End Function

Function StringToMB(S)
  Dim I, B
  For I = 1 To Len(S)
    B = B & ChrB(Asc(Mid(S, I, 1)))
  Next
  StringToMB = B
End Function


P.S. Если рассказал очевидные вещи, ногами не бейте, я новенький :)

полезно, programming

Previous post Next post
Up