powered by simpleCommunicator - 2.0.51     © 2025 Programmizd 02
Форумы / Visual Basic [игнор отключен] [закрыт для гостей] / Отправка данных на сервер
7 сообщений из 7, страница 1 из 1
Отправка данных на сервер
    #39280440
hclubmk
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Доброго времени суток. Столкнулся с первого взгляда - достаточно простой задачей, но "гусей" собрать не получается.
Есть необходимость выложить некоторые данные (текст, двоичные данные) на сервер посредством MSXML2.ServerXMLHTTP и PHP скрипта на серверной стороне.
Код: vbnet
1.
2.
3.
4.
5.
6.
7.
    Dim myMSXML As New MSXML2.ServerXMLHTTP60
    Dim context As String
    Dim state As Variant
    
    myMSXML.open "POST", "http://localhost/upload.php", False
    myMSXML.setRequestHeader "Content-Type", "application/x-www-form-urlencoded"
    myMSXML.send "data=" & "Это текст"



Код: php
1.
2.
3.
4.
5.
6.
7.
<?php
 $postdata = $_POST["data"];

 $fa = fopen("myfile.bin", "w");
 fwrite($fa,$postdata);
 fclose($fa);
?>



и всё вроде-как работает, но myfile.bin имеет кодировку UTF-8, и никакие
Код: plaintext
myMSXML.setRequestHeader "Charset", "Windows-1251"
погоды не делают (iconv и mb_convert_encoding в php-скрипте тоже не помогли). Вопрос: что я делаю не так, и каким образом скрипт PHP может получить/записать во внешний файл текст в "Windows-1251" кодировке, ну и второй вопрос - передача бинарных данных (а именно file-upload). Если у кого есть опыт - поделитесь решением.
...
Рейтинг: 0 / 0
Отправка данных на сервер
    #39280688
Фотография VSVLAD
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
hclubmk,

Посмотрите эту тему, особенно где обсуждается "WebFormClass". Я его использовал как-то (только с переделкой под .NET) для отправки данных на zalil.ru (даже работало, пока сайт не подох)

http://www.sql.ru/forum/1024121/vbs-upload-files-on-http-server
...
Рейтинг: 0 / 0
Отправка данных на сервер
    #39281207
hclubmk
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
VSVLAD,

Спасибо, но для начала хотелось бы разобраться с примитивом.
Элементарная отправка данных на MSXML2.ServerXMLHTTP60 , причем, независимо, POST или GET , влечет не только перекодировку в UTF-8 (да и плевать на нее в конечном итоге), но распознает символ " + " как разделитель (пробел), так, что даже base64 серверу доставляктся уже искаженный, и, ни о каком извлечении данных речи уже идти не может.
Для примера:
Код: vbnet
1.
myMSXML.send "data=" & "1+2=3"

на стороне PHP скрипта будет как
Код: php
1.
1 2=3
...
Рейтинг: 0 / 0
Отправка данных на сервер
    #39281355
hclubmk
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
в принципе, rawurldecode($_GET("data")) на стороне PHP решает вопрос со всеми '+', '&' и т.п., для нормальной передачи параметров, этот самый '+' должен выглядеть как %2B, и тогда
Код: vbnet
1.
myMSXML.send "data=" & "1%2B2=3"

будет иметь соответствующий вид
Код: php
1.
1+2=3
...
Рейтинг: 0 / 0
Отправка данных на сервер
    #39281555
hclubmk
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
По итогу, выгрузка файла оказалась достаточно простой, возможно есть и более изящное решение, но, чтобы закрыть тему, оставлю то, что получилось:
Модуль 1
Код: vbnet
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
27.
28.
29.
30.
31.
32.
33.
34.
35.
36.
37.
38.
39.
40.
41.
42.
43.
44.
45.
46.
47.
48.
49.
50.
51.
52.
53.
54.
55.
56.
57.
58.
59.
60.
61.
62.
63.
64.
65.
66.
67.
68.
69.
70.
71.
72.
73.
74.
75.
76.
77.
78.
79.
80.
81.
82.
83.
84.
85.
86.
87.
88.
89.
90.
91.
92.
93.
94.
95.
96.
97.
98.
99.
100.
101.
102.
103.
104.
105.
106.
107.
108.
109.
110.
111.
112.
113.
114.
115.
116.
117.
118.
119.
120.
121.
122.
123.
124.
125.
126.
127.
128.
129.
130.
131.
132.
133.
134.
135.
136.
137.
138.
Option Explicit

Private Const clOneMask = 16515072          '000000 111111 111111 111111
Private Const clTwoMask = 258048            '111111 000000 111111 111111
Private Const clThreeMask = 4032            '111111 111111 000000 111111
Private Const clFourMask = 63               '111111 111111 111111 000000

Private Const clHighMask = 16711680         '11111111 00000000 00000000
Private Const clMidMask = 65280             '00000000 11111111 00000000
Private Const clLowMask = 255               '00000000 00000000 11111111

Private Const cl2Exp18 = 262144             '2 to the 18th power
Private Const cl2Exp12 = 4096               '2 to the 12th
Private Const cl2Exp6 = 64                  '2 to the 6th
Private Const cl2Exp8 = 256                 '2 to the 8th
Private Const cl2Exp16 = 65536              '2 to the 16th

Public Function Encode64(sString As String) As String
    Dim bTrans(63) As Byte, lPowers8(255) As Long, lPowers16(255) As Long, bOut() As Byte, bIn() As Byte
    Dim lChar As Long, lTrip As Long, iPad As Integer, lLen As Long, lTemp As Long, lPos As Long, lOutSize As Long
    
    For lTemp = 0 To 63                                 'Fill the translation table.
        Select Case lTemp
            Case 0 To 25
                bTrans(lTemp) = 65 + lTemp              'A - Z
            Case 26 To 51
                bTrans(lTemp) = 71 + lTemp              'a - z
            Case 52 To 61
                bTrans(lTemp) = lTemp - 4               '1 - 0
            Case 62
                bTrans(lTemp) = 43                      'Chr(43) = "+"
            Case 63
                bTrans(lTemp) = 47                      'Chr(47) = "/"
        End Select
    Next lTemp

    For lTemp = 0 To 255                                'Fill the 2^8 and 2^16 lookup tables.
        lPowers8(lTemp) = lTemp * cl2Exp8
        lPowers16(lTemp) = lTemp * cl2Exp16
    Next lTemp

    iPad = Len(sString) Mod 3                           'See if the length is divisible by 3
    If iPad Then                                        'If not, figure out the end pad and resize the input.
        iPad = 3 - iPad
        sString = sString & String(iPad, Chr(0))
    End If

    bIn = StrConv(sString, vbFromUnicode)               'Load the input string.
    lLen = ((UBound(bIn) + 1) \ 3) * 4                  'Length of resulting string.
    lTemp = lLen \ 72                                   'Added space for vbCrLfs.
    lOutSize = ((lTemp * 2) + lLen) - 1                 'Calculate the size of the output buffer.
    ReDim bOut(lOutSize)                                'Make the output buffer.
    
    lLen = 0                                            'Reusing this one, so reset it.
    
    For lChar = LBound(bIn) To UBound(bIn) Step 3
        lTrip = lPowers16(bIn(lChar)) + lPowers8(bIn(lChar + 1)) + bIn(lChar + 2)    'Combine the 3 bytes
        lTemp = lTrip And clOneMask                     'Mask for the first 6 bits
        bOut(lPos) = bTrans(lTemp \ cl2Exp18)           'Shift it down to the low 6 bits and get the value
        lTemp = lTrip And clTwoMask                     'Mask for the second set.
        bOut(lPos + 1) = bTrans(lTemp \ cl2Exp12)       'Shift it down and translate.
        lTemp = lTrip And clThreeMask                   'Mask for the third set.
        bOut(lPos + 2) = bTrans(lTemp \ cl2Exp6)        'Shift it down and translate.
        bOut(lPos + 3) = bTrans(lTrip And clFourMask)   'Mask for the low set.
        If lLen = 68 Then                               'Ready for a newline
            bOut(lPos + 4) = 13                         'Chr(13) = vbCr
            bOut(lPos + 5) = 10                         'Chr(10) = vbLf
            lLen = 0                                    'Reset the counter
            lPos = lPos + 6
        Else
            lLen = lLen + 4
            lPos = lPos + 4
        End If
    Next lChar
    If bOut(lOutSize) = 10 Then lOutSize = lOutSize - 2 'Shift the padding chars down if it ends with CrLf.
    If iPad = 1 Then                                    'Add the padding chars if any.
        bOut(lOutSize) = 61                             'Chr(61) = "="
    ElseIf iPad = 2 Then
        bOut(lOutSize) = 61
        bOut(lOutSize - 1) = 61
    End If
    Encode64 = StrConv(bOut, vbUnicode)                 'Convert back to a string and return it.
End Function

Public Function Decode64(sString As String) As String
    Dim bOut() As Byte, bIn() As Byte, bTrans(255) As Byte, lPowers6(63) As Long, lPowers12(63) As Long
    Dim lPowers18(63) As Long, lQuad As Long, iPad As Integer, lChar As Long, lPos As Long, sOut As String
    Dim lTemp As Long
    
    sString = Replace(sString, vbCr, vbNullString)      'Get rid of the vbCrLfs.  These could be in...
    sString = Replace(sString, vbLf, vbNullString)      'either order.
    lTemp = Len(sString) Mod 4                          'Test for valid input.
    If lTemp Then
        Call Err.Raise(vbObjectError, "MyDecode", "Input string is not valid Base64.")
    End If
    If InStrRev(sString, "==") Then                     'InStrRev is faster when you know it's at the end.
        iPad = 2                                        'Note:  These translate to 0, so you can leave them...
    ElseIf InStrRev(sString, "=") Then                  'in the string and just resize the output.
        iPad = 1
    End If
    For lTemp = 0 To 255                                'Fill the translation table.
        Select Case lTemp
            Case 65 To 90
                bTrans(lTemp) = lTemp - 65              'A - Z
            Case 97 To 122
                bTrans(lTemp) = lTemp - 71              'a - z
            Case 48 To 57
                bTrans(lTemp) = lTemp + 4               '1 - 0
            Case 43
                bTrans(lTemp) = 62                      'Chr(43) = "+"
            Case 47
                bTrans(lTemp) = 63                      'Chr(47) = "/"
        End Select
    Next lTemp
    For lTemp = 0 To 63                                 'Fill the 2^6, 2^12, and 2^18 lookup tables.
        lPowers6(lTemp) = lTemp * cl2Exp6
        lPowers12(lTemp) = lTemp * cl2Exp12
        lPowers18(lTemp) = lTemp * cl2Exp18
    Next lTemp
    
    bIn = StrConv(sString, vbFromUnicode)               'Load the input byte array.
    ReDim bOut((((UBound(bIn) + 1) \ 4) * 3) - 1)       'Prepare the output buffer.
    
    For lChar = 0 To UBound(bIn) Step 4
        lQuad = lPowers18(bTrans(bIn(lChar))) + lPowers12(bTrans(bIn(lChar + 1))) + _
                lPowers6(bTrans(bIn(lChar + 2))) + bTrans(bIn(lChar + 3))           'Rebuild the bits.
        lTemp = lQuad And clHighMask                    'Mask for the first byte
        bOut(lPos) = lTemp \ cl2Exp16                   'Shift it down
        lTemp = lQuad And clMidMask                     'Mask for the second byte
        bOut(lPos + 1) = lTemp \ cl2Exp8                'Shift it down
        bOut(lPos + 2) = lQuad And clLowMask            'Mask for the third byte
        lPos = lPos + 3
    Next lChar

    sOut = StrConv(bOut, vbUnicode)                     'Convert back to a string.
    If iPad Then sOut = Left$(sOut, Len(sOut) - iPad)   'Chop off any extra bytes.
    Decode64 = sOut
End Function

Модуль 2
Код: vbnet
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
27.
28.
29.
30.
31.
32.
33.
34.
35.
36.
37.
38.
39.
40.
41.
42.
43.
44.
45.
46.
47.
48.
49.
50.
51.
52.
53.
54.
55.
56.
57.
58.
59.
60.
61.
62.
63.
64.
65.
66.
67.
68.
69.
70.
71.
72.
73.
74.
75.
76.
77.
78.
' A Base64 Encoder/Decoder.
'
' This module is used to encode and decode data in Base64 format as described in RFC 1521.
'
' Home page: www.source-code.biz.
' License: GNU/LGPL (www.gnu.org/licenses/lgpl.html).
' Copyright 2007: Christian d'Heureuse, Inventec Informatik AG, Switzerland.
' This module is provided "as is" without warranty of any kind.

Option Explicit

Private Const CP_UTF8 As Long = 65001 ' UTF-8 Code Page
Private Declare Function MultiByteToWideChar Lib "KERNEL32" ( _
    ByVal CodePage As Long, _
    ByVal dwFlags As Long, _
    ByVal lpMultiByteStr As Long, _
    ByVal cchMultiByte As Long, _
    ByVal lpWideCharStr As Long, _
    ByVal cchWideChar As Long) As Long
    
'------------------------------------------------------------------
' NAME:         FromUTF8 (Private)
' DESCRIPTION:  Use the system call MultiByteToWideChar to
'               get chars using more than one byte and return
'               return the whole string
' CALLED BY:    DecodeURI
' PARAMETERS:
'  UTF8 (I,REQ)   - the ID of the element to return
'  Length (I,REQ) - length of the string
' RETURNS:      the full raw data of this field
'------------------------------------------------------------------
Private Function FromUTF8(ByRef UTF8() As Byte, ByVal Length As Long) As String
    Dim lDataLength As Long

    lDataLength = MultiByteToWideChar(CP_UTF8, 0, VarPtr(UTF8(0)), Length, 0, 0)  ' Get the length of the data.
    FromUTF8 = String$(lDataLength, 0)                                         ' Create array big enough
    MultiByteToWideChar CP_UTF8, 0, VarPtr(UTF8(0)), _
                        Length, StrPtr(FromUTF8), lDataLength                  '
End Function

Function ToLong(intVal)
    If intVal < 0 Then
        ToLong = CLng(intVal) + &H10000
    Else
        ToLong = CLng(intVal)
    End If
End Function

Function Text2UTF8(text As String) As String
    Dim i, c, utfc, b1, b2, b3, l
    
    For i = 1 To Len(text)
        c = ToLong(AscW(Mid(text, i, 1)))
 
        If c < 128 Then
            l = Hex(c)
            If Len(l) = 1 Then
                utfc = "%0" & l
            Else
                utfc = "%" & l
            End If
        ElseIf c < 2048 Then
            b1 = c Mod &H40
            b2 = (c - b1) / &H40
            utfc = "%" & Hex(&HC0 + b2) & "%" & Hex(&H80 + b1)
        ElseIf c < 65536 And (c < 55296 Or c > 57343) Then
            b1 = c Mod &H40
            b2 = ((c - b1) / &H40) Mod &H40
            b3 = (c - b1 - (&H40 * b2)) / &H1000
            utfc = "%" & Chr(&HE0 + b3) & "%" & Chr(&H80 + b2) & "%" & Chr(&H80 + b1)
        Else
            ' UTF-16
            utfc = "%" & Chr(&HEF) & "%" & Chr(&HBF) & "%" & Chr(&HBD)
        End If

        Text2UTF8 = Text2UTF8 + utfc
    Next
End Function

Сама выгрузка
Код: vbnet
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
Private Function TransferFile(theHost As String, filename As String)
    Dim myMSXML As New MSXML2.XMLHTTP60
    Dim context As String
    Dim fileNum As Integer
    Dim strImage As String
    
    fileNum = FreeFile
    Open filename For Binary As fileNum
    strImage = String(LOF(fileNum), Chr$(32))
    Get fileNum, , strImage
    strImage = Text2UTF8(Encode64(strImage))
    Close fileNum
    
    myMSXML.open "POST", theHost, False
    myMSXML.setRequestHeader "Content-Type", "application/x-www-form-urlencoded"
    myMSXML.send "data=" & strImage
End Function
.............
TransferFile "http://127.0.0.1/upload.php", App.Path & "\apache.gif"

И скрипт upload.php на стороне сервера
Код: php
1.
2.
3.
4.
5.
6.
7.
8.
<?php
if(!empty($_POST["data"]))
{
 	$fa = fopen("uploaded.gif", "w");
	fwrite($fa,base64_decode($_POST["data"]));
	fclose($fa);
}
?>
...
Рейтинг: 0 / 0
Отправка данных на сервер
    #39282029
Фотография VSVLAD
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
hclubmk,

Не считая 30% увеличение трафика, так то да... работать будет
...
Рейтинг: 0 / 0
Отправка данных на сервер
    #39282226
hclubmk
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
VSVLAD,
Хорошо, для файлов просто:
Код: vbnet
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
27.
28.
29.
30.
31.
32.
33.
34.
35.
36.
37.
Private Function PostFile(Url As String, FileName As String, Optional ByVal Async As Boolean) As String
    Const STR_BOUNDARY  As String = "MYBOUNDARY"
    Dim nFile           As Integer
    Dim Buffer()        As Byte
    Dim PostData        As String
    Dim XMLHTTP         As New XMLHTTP
    
    nFile = FreeFile
    Open FileName For Binary Access Read As nFile
    If LOF(nFile) > 0 Then
        ReDim baBuffer(0 To LOF(nFile) - 1) As Byte
        Get nFile, , Buffer
        PostData = StrConv(Buffer, vbUnicode)
    End If
    Close nFile
    
    PostData = "--" & STR_BOUNDARY & vbCrLf & _
        "Content-Disposition: form-data; name=""uploadfile""; filename=""" & Mid$(FileName, InStrRev(FileName, "\") + 1) & """" & vbCrLf & _
        "Content-Type: application/octet-stream" & vbCrLf & vbCrLf & _
        PostData & vbCrLf & _
        "--" & STR_BOUNDARY & "--"
    
    With XMLHTTP
        .Open "POST", Url, Async
        .SetRequestHeader "Content-Type", "multipart/form-data; boundary=" & STR_BOUNDARY
        .Send ToByteArray(PostData)
        If Not Async Then
            PostFile = .ResponseText
        End If
    End With
End Function
 
Private Function ToByteArray(sText As String) As Byte()
    ToByteArray = StrConv(sText, vbFromUnicode)
End Function
..........
PostFile "http://127.0.0.1/upload2.php?DIR=.", App.Path & "\apache.gif"


Код: php
1.
2.
3.
4.
5.
6.
<?php
$base_dir = $_GET["DIR"];
if(!is_dir($base_dir))
    mkdir($base_dir);
move_uploaded_file($_FILES["uploadfile"]["tmp_name"], $base_dir . '/' . $_FILES["uploadfile"]["name"]);
?>

Но как на стороне PHP мне получить bytearray() не записывая его в файл (речь может идти не только о передаче файлов, но и произвольных RAW), причем, как ты заметил, с экономией трафика?
...
Рейтинг: 0 / 0
7 сообщений из 7, страница 1 из 1
Форумы / Visual Basic [игнор отключен] [закрыт для гостей] / Отправка данных на сервер
Целевая тема:
Создать новую тему:
Автор:
Закрыть
Цитировать
Найденые пользователи ...
Разблокировать пользователей ...
Читали форум (0):
Пользователи онлайн (0):
x
x
Закрыть


Просмотр
0 / 0
Close
Debug Console [Select Text]