I have a ServiceStack service with a method to handle a GET request. This method returns binary data.
public object Get(DownloadFile request) {
return new HttpResult(new FileInfo("some file"), "application/octet-stream", asAttachment: true);
}
When the host is Windows it works fine but when I'm running it in Linux with Mono+FastCGI the data I download is not the same.
I analyzed the returned bytes for a few files and concluded that there is a pattern. The data is getting wrapped in this way:
original data size + \r\n + original data + \r\n\r\n0\r\n\r\n
Why is this happening and how to fix it?
Edit:
Turns out this is due to chunked transfers which are part of HTTP 1.1.
Knocte's answer pointed me in the right direction and I was able to work around the problem by forcing my request to use HTTP 1.0:
var req = (HttpWebRequest)WebRequest.Create(url);
req.ProtocolVersion = new Version("1.0");
I didn't need to try the patch suggested by knocte but it looks like it's the proper way to fix the problem instead of avoiding it like I did.
I think you're being affected by this bug.
If the patch that is attached to it works for you, then you could clean it up, and propose it as a pull request to mono in github.
Related
I need to invoke a remote REST interface handler and submit it a file in request body. Please note that I don't control the server. I cannot change the request to be multipart, the client has to work in accordance to external specification.
So far I managed to make it work like this (omitting headers etc. for brevity):
byte[] data = readFileCompletely ();
client.target (url).request ().post (Entity.entity (data, "file/mimetype"));
This works, but will fail with huge files that don't fit into memory. And since I have no restriction on filesize, this is a concern.
Question: is it somehow possible to use streams or something similar to avoid reading the whole file into memory?
If possible, I'd prefer to avoid implementation-specific extensions. If not, a solution that works with RESTEasy (on Wildfly) is also acceptable.
ReastEasy as well as Jersey support InputStream out of the box so simply use Entity.entity(inputStream, "application/octet-stream"); or whatever Content-Type header you want to set.
You can go low-level and construct the HTTP request using a library such as the plain java.net.URLConnection.
I have not tried it myself but there is example code which reads a local file and writes it to the request stream without loading it into a byte array.
Upload files from Java client to a HTTP server
Of course this solution requires more manual coding but it should work (unless java.net.URLConnection loads the whole file into memory)
I have a problem in delivering sensor data to the xively API via an Arduino Uno v3 and a Sparkfun WiFly shield. The problem is not in the hardware, or in the WiFly shield library since I can deliver the data to the Paraimpu server just fine.
The most fundamental problem is that the xively library will not work with the sparkfun WiFly library. The relevant declarations (suggested by xively in the documentation) are:
WiFlyClient client;
XivelyClient xivelyclient(client);
this will not work since the WiFlyClient declaration expects a server and port, hence I modified this to:
byte server[] = {173,203,98,29}; //api.xively.com IP address
WiFlyClient client(server,80);
XivelyClient xivelyclient(client);
This gives me an error on compilation of :
Xively_sketch2_aug20a:60: error: no matching function for call to 'XivelyClient::XivelyClient(WiFlyClient&)'
/Users/paultravers/Documents/Arduino/libraries/xively/XivelyClient.h:11: note: candidates are: XivelyClient::XivelyClient(Client&)
/Users/paultravers/Documents/Arduino/libraries/xively/XivelyClient.h:9: note: XivelyClient::XivelyClient(const XivelyClient&)
At this point I am stuck, and my attempts to modify the various libraries to try to reconcile this issue have come to no avail - mostly because it is above my skill level and I really don't know what I am doing.
To get round this, I have written the code to build the put request and send that to the API, using the template of the code that runs successfully to send data to Paraimpu.
I open a connection (either to api.xively.com or to 173.203.98.29; it makes no difference at this stage) and send the following :
PUT /v2/feeds/<feed ID redacted>.json
Host: api.xively.com
Content-Type: application/json
User-Agent : Xively-Arduino-Lib/1.0
X-ApiKey: < API key redacted >
Content-Length: 197
{"version":"1.0.0","datastreams" : [{"id":"TEMPERATURE_CHANNEL" , "current_value" : "29.00"},{"id":"LIGHT_SENSOR_CHANNEL","current_value":"541.00"},{"id":"ALARM_CHANNEL","current_value":"0.00"}]}
Terminating with a blank line.
Needless to say I have set up channels in xively with those names. But this does not work - I don't get the expected return, and the channels don't update. If I read the returning input on the connection it is just a long string of numbers. Can anyone see anything wrong in the format of this request?
i might take a look at WiFlyClient's documentation...maybe you need to set the port/etc in some other way...than extend WiFlyClient
class WiFlyClient2 : public WiFlyClient {
WiFlyClient2(int[] ip,int port) : WiFlyClient() {
//setup up your parent by calling it's functions here
}
}
then it should work like:
byte server[] = {173,203,98,29}; //api.xively.com IP address
WiFlyClient client(server,80);
XivelyClient xivelyclient(client);
note: i never use wifly/etc, i just use arduino...and i run into troubles like this too :)
I don't have a WiFly shield to test with. But as you said in your comment to Zoltan, I don't think that the WiFly client works in the same way that the Arduino Ethernet or Wifi do. This means that the Xively library likely does not work with the WiFly client.
This means that your approach of writing your own HTTP request is probably the way to go. I looked through your request and it looks exactly correct to me. Does anything show up in the Xively Workbench Request Log when you send the request?
One thing you could try is to use the CSV format instead. This can be better for testing since you avoid the possibility of a minor JSON error causing your entire request to not work. To do this change your .json to .csv and then simply make your body a comma separated list of datastream,value. Your body should look something like this:
TEMPERATURE_CHANNEL,29.00
LIGHT_SENSOR_CHANNEL,541.00
ALARM_CHANNEL,0.00
If this does not work it would be helpful if you could post what the return is, that would help us help you. Good luck!
One thing I noticed in your code is that you don't send the HTTP version in your request.
You should try sending:
PUT /v2/feeds/<feed ID redacted>.json HTTP/1.1
I was getting 405 errors when writing to Xively because I incorrectly had HTTP/1.0 as the version in my put requests.
There's also an example from SparkFun's WiFly library that shows writing to Thingspeak which is helpful to make sure you're using the WiFlyClient instance correctly.
I am working with ksoap2 for android and I am sending SOAP requests. I was googling for a whole day and couldn't find solution for my problem. The first problem was with i:type, my service was returning fault for requests with i:type, so I found that this can be fixed using
SoapSerializationEnvelope envelope = new SoapSerializationEnvelope(SoapEnvelope.VER10);
instead of
SoapSerializationEnvelope envelope = new SoapSerializationEnvelope(SoapEnvelope.VER11);
and that fixed the i:type problem. Now the generated request doesn't contain i:type and if I send it using SOAP UI it works fine, but now I get NullPointerException
in this line
httpTransport.call(DEFAULT_SOAP_ACTION, envelope);
Can anyone help me out with this? If u need my code I can post it. I also tried using different versions of ksoap .jar file and it didn't help.
Maybe someone will need this.
I solved this by setting types explicitly (for each PropertyInfo there is .setType function which receives type class String.class etc.) and use
SoapSerializationEnvelope envelope = new SoapSerializationEnvelope(SoapEnvelope.VER11);
and using that removes i:type from the soap request. Hope it will help someone.
I want to build a wcf web service so that the client and the server would be able to transfer files between each other. Do you know how I can achieve this? I think I should turn it into a byte array but I have no idea how to do that. The file is also quite big so I must turn on streamed response.
It sounds like you're on the right track. A quick search of the interwebz yielded this link: http://www.codeproject.com/Articles/166763/WCF-Streaming-Upload-Download-Files-Over-HTTP
Your question indicates that you want to send a file from a java client to a WCFd endpoint, but the contents of your question indicate that this should be a bidirectional capability. If this is the case, then you'll need to implement a service endpoint on your client as well. As far as that is concerned, I cannot be of much help, but there are resources out there like this SO question: In-process SOAP service server for Java
As far as practical implementation, I would think that using these two links you should be able to produce some code for your server and client.
As far as reading all bytes of a file, in C# you can use: File.ReadAllBytes It should work as in the following code:
//Read The contents of the file indicated
string fileName = "/path/to/some/file";
//store the binary in a byte array
byte[] buffer = File.ReadAllBytes(fileName);
//do something with those bytes!
Be sure to use the search function in the future:
I have a server making a head request to a database dump I've created. The remote server does this to make sure that it's not using excessive bandwidth when not necessary.
However, due to some other circumstances outside my control this causes the script to be hit twice: once for the head request, and then another time to download the data.
What I'd like is to have the script I've written detect the head request, send back a couple of headers (e.g. last modified is right now, filesize different than before), and exit. Is there a way to do this?
Since this is still unanswered, I'll give it a try, even though I don't do much ASP.NET.
I'm only familiar with ASP.NET MVC 3, so here's some example code I got to work for responding to HEAD requests:
Function Index() As ActionResult
ControllerContext.HttpContext.Response.AddHeader("NewHeader", "Value")
Return View()
End Function
<ActionName("Index")>
<AcceptVerbs(HttpVerbs.Head)>
Function IndexHead() As ActionResult
Return Index()
End Function
I'm not sure if this still sends content or not, but I didn't see any content in Firefox (with Live HTTP Headers) or with a WebRequest. It could just be that those two ignore content; I wasn't able to confirm with with my packet sniffer, though.
Also, if you want more control over headers, you'll need IIS 7.0, as mentioned in this MSDN Article.