receiving image from handlspecialurl

Hi Guys,

Anybody had created HandleSpecialUrl API/method that receiving an image file?

I tried to use string (base64) but It failed when image is too large.

Is this hard to implement in XOJO?

I learned that this can be done using a multi-part form. Does anybody done this before?

You should start with sending an image with a POST to your handleURL and see what the format is.

Thank michel,

There is no problem with sending. My concern is how to receive the file and save it to the folder within the server.

I hope you can give me some insights.

You need to know the format of what is sent to the app. For that, I would save request.entity to disk for further analysis.

Its an image file. capture from an android app

my problem is how to received the file

it receives automatically as part of the data in request.entity.

You just need to look inside for your file and write it to disk.

Thanks for clarification Chris,

I hope somebody may provide a simple sample on it works.

Hi Ronaldo, I hope the following can help you :

SENDING THE IMAGES

[code]//Save Files (Those are the two files I send to the API)
croppedDamage_Pic.Save(croppedDamage_Pic_File, Picture.SaveAsJPEG)
croppedDamage_Pic_TN.Save( croppedDamage_Pic_File_TN, Picture.SaveAsJPEG )

//Creation Socket
Var MyHTTPSocket As New HTTPSocket

//File to send
Var f1 As FolderItem = croppedDamage_Pic_File
Var f2 As FolderItem = croppedDamage_Pic_File_TN

// Storing the 2 files in a dictionary allows iterating and easily adddding multiple files
Var HTMLForm As New Dictionary

HTMLForm.Value( “UploadedFile1” ) = f1
HTMLForm.Value( “UploadedFile2” ) = f2

//The boundaries will allow separating generic picture info you want to send(such as a file name if necessary) and retrieving each pictures separately
Var picBoundary As String //At the beginning of the picture data
Var picDataBoundary As String // At the end of the picture data

picBoundary = “–” + Right( EncodeHex( MD5( Str( Microseconds ) ) ), 24 ) + “-picbOuNdArY”
picDataBoundary = “–” + Right( EncodeHex( MD5( Str( Microseconds ) ) ), 24 ) + “-picdatabOuNdArY”

//We create a memory block to hold the binary stream that will contain the picture and the info. Each picture is separated by the boundaries we created precedently
Static CRLF As String = EndOfLine.Windows
Var data As New MemoryBlock( 0 )
Var out As New BinaryStream( data )

//For each picture in the dictionary
For Each key As String In HTMLForm.Keys
If HTMLForm.Value(Key) IsA FolderItem Then
// Picture from dictionary
Var file As FolderItem = HTMLForm.Value( key )
out.Write( file.Name + picDataBoundary) //Picture name is added to the BinaryStream and then we add the first boundary
Var bs As BinaryStream = BinaryStream.Open( File ) //Reads picture data
out.Write( bs.Read( bs.Length ) ) //Writes picture data
out.Write( picBoundary ) // Adds the ending boundary
bs.Close
End If
Next

out.Close

//Add the memory block content to the POST
MyHTTPSocket.SetRequestContent(data, "multipart/form-data; " )

// URL Parameters (If your boundaries are not “static”, you need to share the boundaries you used with the API. )
Var parameters() As String
parameters.Append “assignmentnumber=” + EncodeURLComponent( inspection_damage.inspection_assignment_number )
parameters.Append “companycode=” + EncodeURLComponent( Globals.company_Code )
parameters.Append “picboundary=” + EncodeURLComponent( picBoundary )
parameters.Append “picdataboundary=” + EncodeURLComponent( picDataBoundary )

// Set the URL
Var url As String
url = “http://domain.com:8080/special/uploadpictures
url = url + “?” + Join(parameters,"&")

MyHTTPSocket.Post( url )[/code]

RECEIVING IMAGES

[code]Dim folderPhoto As FolderItem = GetFolderItem("").Parent.Parent.Child(“webapp”).Child(“Photos”)

//Retreives picture boundaries used from the URL
Dim picBoundary As String = Request.GetParameter( “picboundary” )
Dim picDataBoundary As String = Request.GetParameter( “picdataboundary” )

//Creates an array. Each element has picture infos (file name) and picture data (image)
Dim arrEntity() As String = Request.Entity.Split( picBoundary )
Dim reqDic As New Dictionary

For i As Integer = 0 To arrEntity.Ubound
Dim fileData() As String = arrEntity( i ).Split( picDataBoundary )
If arrEntity( i ) <> “” Then
reqDic.Value( fileData( 0 ) ) = fileData( 1 ) //The dictionary’s key is the file name and the value holds the image
End If
Next i

Dim keys(), k As Variant
//Dim i as Integer

keys = reqDic.keys
For Each k In keys
Dim f As FolderItem
Dim stream As BinaryStream

// Creates an image file from the binary stream
f = GetFolderItem( folderPhotoAssignment.NativePath + k.StringValue, FolderItem.PathTypeNative )

If f <> Nil Then
stream = BinaryStream.Create( f, True ) // Overwrite if exists
stream.Write( reqDic.Value( k ) )
stream.Close
End If
Next k[/code]

Don’t hesitate if you have questions!

Thank you Roger (I kept this on my code snippets).

This solution applies if we are also the one who we handle sending.

However, the sender was made in an android app which uses POST with the form-data format.

I hope that I found available code can handle form-data format.

POST form-data + json

Hi Lin,

I’m looking on how to receive a file from POST form-data. :slight_smile:

I hope other can share thier solution.

any help from the others?

Ronaldo, have you solved this problem already? I’ve been using this method for catching all the contents attached to a form’s body and storing them in a dictionary. I’m pretty sure I found this from an open source project though I couldn’t remember which… some changes were made for it to better fit my purpose. Hopefully this could help you.

[code]Public Function MultipartToDictionary(formData As String, boundary As String = “”) as Dictionary
If boundary.IsEmpty Then
Raise New UnsupportedFormatException
End If

Var elements() As String = formData.Split("–"+ boundary + EndOfLine.Windows)
Var lastElement As String = elements(elements.LastRowIndex)
elements(elements.LastRowIndex) = lastElement.Replace(EndOfLine.Windows + “–” + boundary + “–”, “”)

Var body As New Dictionary

For Each element As String In elements
Var line As String = element.TrimLeft.NthField(EndOfLine.Windows, 1)
Var name As String = line.NthField(";", 2).NthField("=", 2).ReplaceAll("""", “”)

If name.Trim = "" Then
  Continue
End If

Var nm As String = name

If line.CountFields(";") < 3 Then
  body.Value(nm) = element.NthField(EndOfLine.Windows + EndOfLine.Windows, 2)
Else
  Var keyName As String = line.NthField(";", 2).NthField("=", 2).ReplaceAll("""", "")
  Var fileName As String = line.NthField(";", 3).NthField("=", 2).ReplaceAll("""", "")
  
  If fileName.Trim = "" Then
    fileName = name
  End If
  
  Var file As FolderItem = CreateTempFile(fileName, element)
  
  body.Value(keyName) = file
End If

Next

Return body
End Function
[/code]

Oh great!

Actually I suspend the project because I felt helpless looking for this solution.

Thanks for your help. I will try this and revive my project.