MultiPartFormData image upload not working on android?

I’m using the MultiPartForm code (How To - Upload an Image to a server (multipart/form-data) from:

http://developer.anscamobile.com/code/how-upload-image-server-multipartform-data#comment-105753

and I can’t get it to upload an image to my php server from the android. My listener gets called after the network.request POST, but the event.response is just “java.lang.Double”, apparently some type of error in Corona sending out the form.

The code works great in the Mac Simulator and in iPhone builds - my php server eats it up, saves out the files, sends 'em back looking great, etc. But android gives me the “java.lang.Double” response…

Anyone got this working in android builds? Any idea what up with java.lang.Double error? [import]uid: 79933 topic_id: 26120 reply_id: 326120[/import]

OK, so on the code exchange page, it looks like others are having the same multipart form problem on android… Our POST requests are getting “java.lang.Double” (a total SNAFU/java crash)in the event.response listener callback - and no data is sent to the server.

According to the original authors response on the code exchange page, he thinks that ansca is not including some necc. libraries for the android app to complete the mutlipart request properly.

The code-exchange thread is at: http://developer.anscamobile.com/code/how-upload-image-server-multipartform-data#comment-105753

(Original authors comments about the missing android lib(s) are in there too…) [import]uid: 79933 topic_id: 26120 reply_id: 106527[/import]

Hi Everyone,

I’m interested to know about this as well. Does the multipart form work with Android?

I’ve been able to successfully run it via the simulator, but the moment I pack it into an APK, I get a network error. I did notice that when the file gets encoded, it seems to only do a very small part according to the console. I’ve compared a bin64’d file with the one that is generated by Android in the console and it looks like it gets truncated.

If any of the pros can weigh in on this one it would be appreciated. [import]uid: 8045 topic_id: 26120 reply_id: 113568[/import]

Hello mpappas,

Did you ever have any success in uploading files from an android? Via multipart form, binary upload, ftp, or any other method?

Thank you! - David [import]uid: 68880 topic_id: 26120 reply_id: 134170[/import]

Hi David,

Yes, I got it working (multi-part form). I ran into several bumps along the way, probably the biggest one being related to cookies on android. Apparently, network request doesn’t (or didn’t, don’t know if it does now) persist cookies between calls (although iOS did/does). The multi-part code does also facilitate passing of cookies, so it all worked out.

So yes,.the multi-part code in the exchange does work, for both iOS and Android. Good stuff.

  • mpappas [import]uid: 79933 topic_id: 26120 reply_id: 134177[/import]

Hello mpappas,

Thank you for responding so quickly. I have an app where I am using the multi-part form from the exchange to upload a jpg file, and as related it works great on the simulator and iOS, but simply does not work on Android. I am encouraged that you found a way to make the exchange code to work for you on Android. (was concerned, from reading through forums that it might simply not work wit android) Do you have any advise on what mods I might have to make to the multi-part form exchange code to work on Android? Or any other tips to go from non-functional on Android to functional. I truly appreciate your insight!

All the best,

David [import]uid: 68880 topic_id: 26120 reply_id: 134183[/import]

Below is my code that calls the multi-part form… It’s pretty vanilla now. My old print statements are still in there commented out, used for debugging the android side…

function uploadFile(fileName, callBack) -- uploads a file, calls the callback when the upload is verified as complete  
  
-- if( isAndroid == true ) then  
-- uploadFile2(fileName, callBack) -- Non-async, android version  
-- return  
-- end   
  
-- iOS version  
  
local MultipartFormData = require("class\_MultipartFormData")  
local multipart = MultipartFormData.new()  
  
-- print(" -- uploading... iOS network.request() method - filename: ", fileName)  
  
 multipart:addFile("photo", system.pathForFile( fileName, system.TemporaryDirectory ), "image/jpeg", fileName)  
  
 uploadCallBack = callBack -- routine to call back to inform the upload is complete  
  
-- print(" -- multipart:tostring -- ", multipart:toString())  
  
 uploadParams = {}  
 uploadParams.body = multipart:getBody() -- Must call getBody() first!  
 uploadParams.headers = multipart:getHeaders() -- Headers not valid until getBody() is called.   
-- local tempString = string.sub(mojoData.cookieParams, 12, -1) -- Skip the starting &PHPSESSID= part....  
-- uploadParams.headers["Cookie"] = {}  
-- uploadParams.headers["Cookie"] = tempString  
  
-- printTable(uploadParams.headers, "Headers", 2)  
  
 local cryptoKey= "XXXXXX" -- Crypto stuff redacted  
 local cryptoLogin = "XXXXX"  
 local cryptoPass = "XXXXX  
  
-- print(" -- CRYPTO LOGIN: ", cryptoLogin )  
  
 local uploadURL = mojoData.mediaServerURL  
 -- New mediaServer params  
 uploadURL = uploadURL -- login params redacted...   
  
-- print(" -- Sending upload request -- ", uploadURL)  
 network.request( uploadURL, "POST", upLoadListener, uploadParams)  
  
-- print(" -- uploader Done.")   
 end   

For a while, when it wouldn’t work on android, I used the following to at least have android uploads functional while I got it going (http request worked on android for me, but not network.request for upload):

[code]
function uploadFile2(fileName, callBack) – uploads a file ANDROID ONLY, calls the callback when the upload is verified as complete
http = require(“socket.http”)

ltn12 = require(“ltn12”)
url = require(“socket.url”)

local post
local response = {}

– ANDROID ONLY upload…

local MultipartFormData = require(“class_MultipartFormData”)
local multipart = MultipartFormData.new()

print(" – uploading… ANDROID http request method – ")

multipart:addFile(“photo”, system.pathForFile( fileName, system.TemporaryDirectory ), “image/jpeg”, fileName)
uploadParams = {}
– print(" point a")
uploadParams.body = multipart:getBody() – Must call getBody() first!
– print(" point b")
uploadParams.headers = multipart:getHeaders() – Headers not valid until getBody() is called.

uploadCallBack = callBack – routine to call back to inform the upload is complete

local uploadURL = mojoData.mediaServerURL
– New mediaServer params
uploadURL = uploadURL ----- login info params redacted…

local r, c, h = http.request {
url = uploadURL,
method = “POST”,
headers =
uploadParams.headers,
source = ltn12.source.string(uploadParams.body),
sink = ltn12.sink.table(response)
}

– print(response[1])

local event = {}
event.response = response[1]

upLoadListener( event ) – This is synchronous, so call the listener back with response…

end
[/code] [import]uid: 79933 topic_id: 26120 reply_id: 134186[/import]

Thanks again mpappas. I’ll let you know if it does the trick! - David [import]uid: 68880 topic_id: 26120 reply_id: 134191[/import]

Hello mpappas,

Did you ever have any success in uploading files from an android? Via multipart form, binary upload, ftp, or any other method?

Thank you! - David [import]uid: 68880 topic_id: 26120 reply_id: 134170[/import]

Hi David,

Yes, I got it working (multi-part form). I ran into several bumps along the way, probably the biggest one being related to cookies on android. Apparently, network request doesn’t (or didn’t, don’t know if it does now) persist cookies between calls (although iOS did/does). The multi-part code does also facilitate passing of cookies, so it all worked out.

So yes,.the multi-part code in the exchange does work, for both iOS and Android. Good stuff.

  • mpappas [import]uid: 79933 topic_id: 26120 reply_id: 134177[/import]

Hello mpappas,

Thank you for responding so quickly. I have an app where I am using the multi-part form from the exchange to upload a jpg file, and as related it works great on the simulator and iOS, but simply does not work on Android. I am encouraged that you found a way to make the exchange code to work for you on Android. (was concerned, from reading through forums that it might simply not work wit android) Do you have any advise on what mods I might have to make to the multi-part form exchange code to work on Android? Or any other tips to go from non-functional on Android to functional. I truly appreciate your insight!

All the best,

David [import]uid: 68880 topic_id: 26120 reply_id: 134183[/import]

Below is my code that calls the multi-part form… It’s pretty vanilla now. My old print statements are still in there commented out, used for debugging the android side…

function uploadFile(fileName, callBack) -- uploads a file, calls the callback when the upload is verified as complete  
  
-- if( isAndroid == true ) then  
-- uploadFile2(fileName, callBack) -- Non-async, android version  
-- return  
-- end   
  
-- iOS version  
  
local MultipartFormData = require("class\_MultipartFormData")  
local multipart = MultipartFormData.new()  
  
-- print(" -- uploading... iOS network.request() method - filename: ", fileName)  
  
 multipart:addFile("photo", system.pathForFile( fileName, system.TemporaryDirectory ), "image/jpeg", fileName)  
  
 uploadCallBack = callBack -- routine to call back to inform the upload is complete  
  
-- print(" -- multipart:tostring -- ", multipart:toString())  
  
 uploadParams = {}  
 uploadParams.body = multipart:getBody() -- Must call getBody() first!  
 uploadParams.headers = multipart:getHeaders() -- Headers not valid until getBody() is called.   
-- local tempString = string.sub(mojoData.cookieParams, 12, -1) -- Skip the starting &PHPSESSID= part....  
-- uploadParams.headers["Cookie"] = {}  
-- uploadParams.headers["Cookie"] = tempString  
  
-- printTable(uploadParams.headers, "Headers", 2)  
  
 local cryptoKey= "XXXXXX" -- Crypto stuff redacted  
 local cryptoLogin = "XXXXX"  
 local cryptoPass = "XXXXX  
  
-- print(" -- CRYPTO LOGIN: ", cryptoLogin )  
  
 local uploadURL = mojoData.mediaServerURL  
 -- New mediaServer params  
 uploadURL = uploadURL -- login params redacted...   
  
-- print(" -- Sending upload request -- ", uploadURL)  
 network.request( uploadURL, "POST", upLoadListener, uploadParams)  
  
-- print(" -- uploader Done.")   
 end   

For a while, when it wouldn’t work on android, I used the following to at least have android uploads functional while I got it going (http request worked on android for me, but not network.request for upload):

[code]
function uploadFile2(fileName, callBack) – uploads a file ANDROID ONLY, calls the callback when the upload is verified as complete
http = require(“socket.http”)

ltn12 = require(“ltn12”)
url = require(“socket.url”)

local post
local response = {}

– ANDROID ONLY upload…

local MultipartFormData = require(“class_MultipartFormData”)
local multipart = MultipartFormData.new()

print(" – uploading… ANDROID http request method – ")

multipart:addFile(“photo”, system.pathForFile( fileName, system.TemporaryDirectory ), “image/jpeg”, fileName)
uploadParams = {}
– print(" point a")
uploadParams.body = multipart:getBody() – Must call getBody() first!
– print(" point b")
uploadParams.headers = multipart:getHeaders() – Headers not valid until getBody() is called.

uploadCallBack = callBack – routine to call back to inform the upload is complete

local uploadURL = mojoData.mediaServerURL
– New mediaServer params
uploadURL = uploadURL ----- login info params redacted…

local r, c, h = http.request {
url = uploadURL,
method = “POST”,
headers =
uploadParams.headers,
source = ltn12.source.string(uploadParams.body),
sink = ltn12.sink.table(response)
}

– print(response[1])

local event = {}
event.response = response[1]

upLoadListener( event ) – This is synchronous, so call the listener back with response…

end
[/code] [import]uid: 79933 topic_id: 26120 reply_id: 134186[/import]

Thanks again mpappas. I’ll let you know if it does the trick! - David [import]uid: 68880 topic_id: 26120 reply_id: 134191[/import]

All is well, but not what it seemed. I ran mpappas code, and found similar results to my own; no success uploading a test file on an Android device. But thanks to the input from mpappas and also Marble68, confirming that the code should in fact work, I had the clue needed to track down the problem. It turned out that for simplicity sake my test code utilized an image in the resource directory. Again this works flawlessly in the simulator and on iOS devices, but as it turns out, system.pathForFile() does not work on Android devices when accessing the Resource directory (it is correctly noted as such in the Corona API documentation, due to how Android handles application resources).

Many thanks to mpappas and Marble68 for the assist. - David [import]uid: 68880 topic_id: 26120 reply_id: 134613[/import]

All is well, but not what it seemed. I ran mpappas code, and found similar results to my own; no success uploading a test file on an Android device. But thanks to the input from mpappas and also Marble68, confirming that the code should in fact work, I had the clue needed to track down the problem. It turned out that for simplicity sake my test code utilized an image in the resource directory. Again this works flawlessly in the simulator and on iOS devices, but as it turns out, system.pathForFile() does not work on Android devices when accessing the Resource directory (it is correctly noted as such in the Corona API documentation, due to how Android handles application resources).

Many thanks to mpappas and Marble68 for the assist. - David [import]uid: 68880 topic_id: 26120 reply_id: 134613[/import]