I’m trying to upload a file to a web service using the new framework and am running into a few issues trying to port code from an HTTPSocket example to the new framework to use http 1.1.
I’ve got the following method which seems to do most of what I need (please excuse poor error checking etc, as it’s still a work in progress). Basically, I pass a socket, dictionary and string to it, and in the current state all content I pass through is correctly parsed and put into the mbData memory block.
The part that I’m struggling with is getting the data from the postContent binary stream into the postData xojo.core.memoryblock to send to the web service. I’ve read the documentation and some of the posts on the forum, but am unsure of how to convert the data into the required format. Any help appreciated.
SetFormData(sock as Xojo.net.HTTPSocket, FormData As Dictionary, Boundary As String)
If Boundary.Trim = "" Then
Boundary = "--" + Right(EncodeHex(MD5(Str(Microseconds))), 24) + "--bndry"
End If
Static CRLF As String = EndOfLine.Windows
Dim mbData As New MemoryBlock(0)
Dim postContent As New BinaryStream(mbData)
For Each key As String In FormData.Keys
postContent.Write("--" + Boundary + CRLF)
If VarType(FormData.Value(Key)) = Variant.TypeString Then
postContent.Write("Content-Disposition: form-data; name=""" + key + """" + CRLF + CRLF)
postContent.Write(FormData.Value(key) + CRLF)
ElseIf FormData.Value(Key) IsA FolderItem Then
Dim file As FolderItem = FormData.Value(key)
postContent.Write("Content-Disposition: form-data; name=""" + key + """; filename=""" + File.DisplayName + """" + CRLF)
postContent.Write("Content-Type: application/octet-stream" + CRLF + CRLF) ' replace with actual MIME Type
Dim bs As BinaryStream = BinaryStream.Open(File)
postContent.Write(bs.Read(bs.Length) + CRLF)
bs.Close
End If
Next
postContent.Write("--" + Boundary + "--" + CRLF)
Dim mbpostData as xojo.Core.MemoryBlock
Dim postData As New xojo.Core.MemoryBlock(mbpostData)
'Convert MB to X.C.MB?
postContent.Close
sock.SetRequestContent(postData, "application/x-www-form-urlencoded; boundary=" + Boundary.ToText)
'Change mime type as required
sock.Send("POST", "https://www.virustotal.com/vtapi/v2/file/scan")
Dim Clone As New Xojo.Core.MutableMemoryBlock(Source.Size)
Clone.LittleEndian = Source.LittleEndian
For I As Integer = 0 To Source.Size - 1
Clone.UInt8Value(I) = Source.UInt8Value(I)
Next
[quote=295033:@Kem Tekinay]This is probably faster:
dim nmb as new Xojo.Core.MemoryBlock( mb )
nmb = nmb.Left( mb.Size )
[/quote]
Kem, can you explain your code? It doesn’t make any sense to me, let alone within the question’s context.
I might have misunderstood. The question was how to copy data from a classic MemoryBlock to a Xojo.Core.MemoryBlock, yes?
A Constructor for Xojo.Core.MemoryBlock will take a Ptr, and the classic MemoryBlock auto-converts to Ptr. But a MemoryBlock created from a pointer has an undetermined size, so Left copies the data from that Pointer as a new Xojo.Core.MemoryBlock.
But if I did misunderstand, I’ve successfully answered a different question.
From your code above: do you really need to copy from the “classic” memory block to the “Xojo.Core” one? If not, you can create a “Xojo.Core” memory block pointing to the same memory of the “classic” one:
I didn’t realize (or remember) that version of the Constructor, but here’s the “gotcha” with doing it that way: the new MemoryBlock points to the memory held by the original, classic MemoryBlock. If that goes out of scope, the data is lost. For example, just to illustrate:
dim nmb as Xojo.Core.MemoryBlock
if true then // scope
dim mb as MemoryBlock = "some string"
nmb = new Xojo.Core.MemoryBlock( mb, mb.Size )
// nmb looks good at this point
end if
// nmb now "contains" garbage since mb went out of scope
Dim mb As MemoryBlock = "abcdef"
Dim nmb As New Xojo.Core.MemoryBlock(mb, mb.Size)
mb = Nil
// nmb is now garbage
I wasn’t aware of that. I thought memory blocks were like classes reference-counted.
Dim mb As MemoryBlock = "abcdef"
Dim nmb As New Xojo.Core.MemoryBlock(mb, mb.Size)
mb = Nil
// nmb is now garbage
I wasn’t aware of that. I thought memory blocks were like classes reference-counted.[/quote]
They are, but the constructor is for a pointer to the original. If the original goes away, the pointer is wrong.
In Kem’s first example, he creates a new memoryblock from the data returned by the pointer. That’s the nmb = nmb.Left line.