Posting a file with HTTP.request

Hi, I need to upload a file using http.request, I had it working with network.request but realised that synchronous data was more suited to the task. I have done a lot of searching over the last 2 days but cannot seem to figure out what my problem is. I have checked the php settings on my server and everything is OK there. I am not recieving any error messages back from the server, but it appears that $_file is empty so I assume the error is in the lua file.

Thanks in advance.

Here is my code.

database.lua

function uploadPhoto ( filename )  
 print("Upload Photo Top")  
 local mime = require "mime"  
 local path = system.pathForFile( filename, system.DocumentsDirectory)  
 URL = "http://www.myserver.com/uploadImage.php"  
 local fileHandle = io.open( path)   
 local len = fileHandle:seek( "end", 0 )  
 io.close(fileHandle)  
 print("len=" .. len)  
 if fileHandle then   
 print("Image Found!")  
 response\_body = {}  
 local body, code, headers = http.request{  
 url = URL ,   
 method = "POST",  
 headers = {  
 ["Content-Type"] = "multipart/form-data",  
 ["Content-Length"] = len  
 },  
 source = ltn12.source.file("newimage.jpg"),  
 sink = ltn12.sink.table(response\_body)  
 }  
 print("Body = ", body)  
 print("code = ", code)  
 print("headers = ", headers[1])  
 print("response body = ", response\_body[1])  
 else  
 print("Image Not Found")  
 end  
end  

uploadImage.php

[code]

<?php
// In PHP versions earlier than 4.1.0, $HTTP\_POST\_FILES should be used instead // of $\_FILES. $uploaddir = '/files/'; $uploadfile = $uploaddir . basename($\_FILES['userfile']['name']); echo ' '; if (move\_uploaded\_file($\_FILES['userfile']['tmp\_name'], $uploadfile)) { echo "File is valid, and was successfully uploaded.\n"; } else { echo "Possible file upload attack!\n"; } echo "Temp filename = " . $\_FILES['userfile']['tmp\_name'] ; echo '\nHere is some more debugging info:'; print\_r($\_FILES); print " "; ?\> [/code] [import]uid: 184705 topic\_id: 34640 reply\_id: 334640[/import]

Actually it’s probably on your PHP side. Most likely a header is missing. See this page:

http://www.bradino.com/php/empty-post-array/

[import]uid: 199310 topic_id: 34640 reply_id: 137685[/import]

Thanks for the reply. The problem is indeed that no headers are being passed across. I just need to figure out why this is happening. I inserted this code into my php file
[php]
foreach (getallheaders() as $name => $value) {
echo “$name: $value\n”;
}
[/php]

And all I receive back is

[text]Connection: close, TE
Host: www.myserver.com
Te: trailers
User-Agent: LuaSocket 2.0.2[/text]

Where as if I use network.request through the same php file I get

[text]Content-Type: application/x-www-form-urlencoded
Accept: */*
Accept-Encoding: gzip, deflate
Accept-Language: en-us
Connection: keep-alive
Host: www.myserver.com
User-Agent: Corona%20Simulator/2013.998 CFNetwork/596.2.3 Darwin/12.2.1 (x86_64) (MacBookPro10%2C1)[/text] [import]uid: 184705 topic_id: 34640 reply_id: 137760[/import]

You should be able to change line 17 in your upload function to:

[“Content-Type”] = “application/x-www-form-urlencoded”

[import]uid: 199310 topic_id: 34640 reply_id: 137775[/import]

Thanks for your help Rob. I finally got it working, not the way I wanted — but it works…

I ended up using/adapting slightly bpappin’s tutorial on multipart forms by following this twitter tutorial . I was trying to avoid using this because I wanted to learn it for myself,I thought the code looked rather large and I had gotten it into my head that it was only for asynchronous data transfer (wood for trees).

Anyway here is the code I went with if anyone else has the same issue. The PHP code was a straight copy (with the alterations mentioned in the comments).

[lua]function rawPostRequestMultipart(image)
URL = “http://www.myserver.com/uploader.php
local multipart = MultipartFormData.new()
multipart:addFile(“myfile”, system.pathForFile( image, system.DocumentsDirectory ), “image/jpeg”, image)

local params = {}
params.body = multipart:getBody() – Must call getBody() first!
params.headers = multipart:getHeaders() – Headers not valid until getBody() is called.
response_body = {}
r,c,h = http.request
{
url = URL,
method = “POST”,
headers = params.headers,
source = ltn12.source.string(params.body),
sink = ltn12.sink.table(response_body)
}
print("Response Body = ", response_body[1])
return

end[/lua]
[import]uid: 184705 topic_id: 34640 reply_id: 137817[/import]

Actually it’s probably on your PHP side. Most likely a header is missing. See this page:

http://www.bradino.com/php/empty-post-array/

[import]uid: 199310 topic_id: 34640 reply_id: 137685[/import]

Thanks for the reply. The problem is indeed that no headers are being passed across. I just need to figure out why this is happening. I inserted this code into my php file
[php]
foreach (getallheaders() as $name => $value) {
echo “$name: $value\n”;
}
[/php]

And all I receive back is

[text]Connection: close, TE
Host: www.myserver.com
Te: trailers
User-Agent: LuaSocket 2.0.2[/text]

Where as if I use network.request through the same php file I get

[text]Content-Type: application/x-www-form-urlencoded
Accept: */*
Accept-Encoding: gzip, deflate
Accept-Language: en-us
Connection: keep-alive
Host: www.myserver.com
User-Agent: Corona%20Simulator/2013.998 CFNetwork/596.2.3 Darwin/12.2.1 (x86_64) (MacBookPro10%2C1)[/text] [import]uid: 184705 topic_id: 34640 reply_id: 137760[/import]

You should be able to change line 17 in your upload function to:

[“Content-Type”] = “application/x-www-form-urlencoded”

[import]uid: 199310 topic_id: 34640 reply_id: 137775[/import]

Thanks for your help Rob. I finally got it working, not the way I wanted — but it works…

I ended up using/adapting slightly bpappin’s tutorial on multipart forms by following this twitter tutorial . I was trying to avoid using this because I wanted to learn it for myself,I thought the code looked rather large and I had gotten it into my head that it was only for asynchronous data transfer (wood for trees).

Anyway here is the code I went with if anyone else has the same issue. The PHP code was a straight copy (with the alterations mentioned in the comments).

[lua]function rawPostRequestMultipart(image)
URL = “http://www.myserver.com/uploader.php
local multipart = MultipartFormData.new()
multipart:addFile(“myfile”, system.pathForFile( image, system.DocumentsDirectory ), “image/jpeg”, image)

local params = {}
params.body = multipart:getBody() – Must call getBody() first!
params.headers = multipart:getHeaders() – Headers not valid until getBody() is called.
response_body = {}
r,c,h = http.request
{
url = URL,
method = “POST”,
headers = params.headers,
source = ltn12.source.string(params.body),
sink = ltn12.sink.table(response_body)
}
print("Response Body = ", response_body[1])
return

end[/lua]
[import]uid: 184705 topic_id: 34640 reply_id: 137817[/import]

Hi Rob

I want invoke asp.net web services method from Lua and i have done it but this is long process.
I have to pass content type and header for invoke particular method.What is best way to call particular method ?.Please suggest me .This is my sample code.

local function networkListener( event )
if ( event.isError ) then
print( “Network error!”)
else
print ( "RESPONSE: " … event.response )
end
end
local headers = {}
headers[“Content-Type”] = “text/xml”
vartest = [[<?xml version="1.0" encoding="utf-8"?>






]]
–print(vartest)

local params = {}
params.body = vartest
params.headers = headers
network.request( “http://localhost:2907/Service1.asmx?op=GetBranch”, “POST”, networkListener, params)
end [import]uid: 209400 topic_id: 34640 reply_id: 138360[/import]

I’ve never tried up submit XML code before, but in theory your template looks right, though I’m a bit confused about one part.

Typically when you see a “?somekey=somevalue” on the end of a URL, that is a “GET” request. I’m not 100% sure what happens if you try to combine a POST request with a GET request like that. I would think you would do something more like:

local function networkListener( event )  
 if ( event.isError ) then  
 print( "Network error!")  
 else  
 print ( "RESPONSE: " .. event.response )  
 end  
end  
  
local headers = {}  
headers["Content-Type"] = "text/xml"  
vartest = [[<?xml version="1.0" encoding="utf-8"?>  
  
]]  
--print(vartest)  
  
local params = {}  
params.body = "opp=GetBranch&" .. vartest  
params.headers = headers  
network.request( "http://localhost:2907/Service1.asmx", "POST", networkListener, params)  
  
-- end -- dunno what this end is ending....  

[import]uid: 199310 topic_id: 34640 reply_id: 138386[/import]

Hi Rob

My code working fine and able to invoke method and get return value but i want invoke method by soap action .I don’t want write this code for soap body.

[[<?xml version="1.0" encoding="utf-8"?>






]] [import]uid: 209400 topic_id: 34640 reply_id: 138389[/import]

Maybe someone with some SOAP experience can chime in. But I don’t know if anyone who’s gotten SOAP to work.

[import]uid: 199310 topic_id: 34640 reply_id: 138411[/import]

Hi Rob

I want invoke asp.net web services method from Lua and i have done it but this is long process.
I have to pass content type and header for invoke particular method.What is best way to call particular method ?.Please suggest me .This is my sample code.

local function networkListener( event )
if ( event.isError ) then
print( “Network error!”)
else
print ( "RESPONSE: " … event.response )
end
end
local headers = {}
headers[“Content-Type”] = “text/xml”
vartest = [[<?xml version="1.0" encoding="utf-8"?>






]]
–print(vartest)

local params = {}
params.body = vartest
params.headers = headers
network.request( “http://localhost:2907/Service1.asmx?op=GetBranch”, “POST”, networkListener, params)
end [import]uid: 209400 topic_id: 34640 reply_id: 138360[/import]

I’ve never tried up submit XML code before, but in theory your template looks right, though I’m a bit confused about one part.

Typically when you see a “?somekey=somevalue” on the end of a URL, that is a “GET” request. I’m not 100% sure what happens if you try to combine a POST request with a GET request like that. I would think you would do something more like:

local function networkListener( event )  
 if ( event.isError ) then  
 print( "Network error!")  
 else  
 print ( "RESPONSE: " .. event.response )  
 end  
end  
  
local headers = {}  
headers["Content-Type"] = "text/xml"  
vartest = [[<?xml version="1.0" encoding="utf-8"?>  
  
]]  
--print(vartest)  
  
local params = {}  
params.body = "opp=GetBranch&" .. vartest  
params.headers = headers  
network.request( "http://localhost:2907/Service1.asmx", "POST", networkListener, params)  
  
-- end -- dunno what this end is ending....  

[import]uid: 199310 topic_id: 34640 reply_id: 138386[/import]

Hi Rob

My code working fine and able to invoke method and get return value but i want invoke method by soap action .I don’t want write this code for soap body.

[[<?xml version="1.0" encoding="utf-8"?>






]] [import]uid: 209400 topic_id: 34640 reply_id: 138389[/import]

Maybe someone with some SOAP experience can chime in. But I don’t know if anyone who’s gotten SOAP to work.

[import]uid: 199310 topic_id: 34640 reply_id: 138411[/import]

Soap works just fine, you just have to “post” your startpoint xml to the service then in the “response” do what you need to do etc.

I have it working right now and everything is simple i even use authentication etc. and all is well, the easiest way to do this is to get it working with something like soapUi:

http://www.soapui.org/About-SoapUI/what-is-soapui.html

Then once you have it working in there just grab the xml “post” and append that to your first request and the service wll response just fine.

[import]uid: 174725 topic_id: 34640 reply_id: 144877[/import]

Soap works just fine, you just have to “post” your startpoint xml to the service then in the “response” do what you need to do etc.

I have it working right now and everything is simple i even use authentication etc. and all is well, the easiest way to do this is to get it working with something like soapUi:

http://www.soapui.org/About-SoapUI/what-is-soapui.html

Then once you have it working in there just grab the xml “post” and append that to your first request and the service wll response just fine.

[import]uid: 174725 topic_id: 34640 reply_id: 144877[/import]

Soap works just fine, you just have to “post” your startpoint xml to the service then in the “response” do what you need to do etc.

I have it working right now and everything is simple i even use authentication etc. and all is well, the easiest way to do this is to get it working with something like soapUi:

http://www.soapui.org/About-SoapUI/what-is-soapui.html

Then once you have it working in there just grab the xml “post” and append that to your first request and the service wll response just fine.

[import]uid: 174725 topic_id: 34640 reply_id: 144877[/import]