I am developing a broker service which accepts a clients request to search for an image with certain tags. I have an existing web service in C# 2.0 which delivers the requested info and due to business rules, I cannot expose my 2.0 webservice to the new client and hence the need for my broker service which will invoke my 2.0 webservice and obtain the handle/location to the image and then try to stream it as the output of the WCF service call
The images could be between 1MB to 20MB in size. What is the best way to stream this data in WCF?
use MTOM attachments. See this article for a comparison and explanation: http://msdn.microsoft.com/en-us/library/ms733742.aspx
Change your response type and write your file
Response.ContentType = "image/jpeg";
Response.WriteFile(fileNameAndPath);
Response.End();
alternatively if you have the image loaded in memory
Response.ContentType = "image/jpeg";
Response.OutputStream.Write(imageBytes, 0, bytesLength);
Response.End();
Related
We are uploading a large size file using a SOAP request developed in C#.net and passing this to a web service API developed in VB.net.
In the existing logic we have implemented Base64 encoding algorithm and the respective code snippet is shown below.
Byte[] bytes = File.ReadAllBytes(FileName);
Base64String = Convert.ToBase64String(bytes);
But in this scenario, we are able to upload a file until 70 MB in IIS 7.0 server. We are encountered with an issue with the file size beyond that.
Now we would require solution to know about how to upload a large size (say for example, more than 500 GB) file by sending as SOAP attachments to a SOAP request API. We would also like to know the possible way to send it via mime-soap attachments.
Sample XML data:-
http://www.dummy.com' xmlns:xsd='http://www.dummy.com' xmlns:soap='http://dummy.com/soap/envelope/'>
Referred links1https://www.theserverside.com/news/1363957/Sending-Attachments-with-SOAP
Referred links2https://community.boomi.com/s/article/mime-soap-attachments
Maybe the title I have does not reflect my Question 100% but I will try to make it clearer. That is how our system is right now.
We have an Webserver that is public on the internet and the Webserver that has access to a Fileserver. We would like without having files on the Webserver the client to be able to download files from the Fileserver. Is there any technology available for these kind of requests?
We are using ASP. NET WebForms.
Thanks in advance.
I don't know of any Framework that would do this but I implemented something similar. In our case we have a list of the files that users should be able to download in a database but you could simply use System.IO.Directory to query for the available files in a certain folder yourself. It's also required that the application runs in an application pool that has an identity (User) that is allowed to access the fileshare.
The actual download is implemented as an ASP.Net WebHandler (.ashx-File). When the user hits that Handler I basically do something like this in the ProcessRequest method:
string fileName = "\\\\myServer\\folder\\file.pdf";
byte[] fileContent = System.IO.File.ReadAllBytes(fileName);
context.Response.Clear();
context.Response.ClearHeaders();
context.Response.ClearContent();
context.Response.ContentType = "application/pdf";
context.Response.AddHeader("Content-Disposition", "attachment;filename=" + System.IO.Path.GetFileName(fileName));
context.Response.AddHeader("Content-Length", fileContent.Length.ToString());
context.Response.BinaryWrite(fileContent);
Of course if you are dealing with bigger files you might want to not load the entire file into memory but rather read in chunks and make multiple calls to BinaryWrite. You also should set the ContentType to a MIME-Type that fits your file type so it gets handled correctly by the clients browser.
From an ASP.NET Web Api 2.x controller I'm am serving files using an instance of the StreamContent type. When a file is requested, its blob is located in the database, and a blob stream is opened. The blob stream is then used as input to a StreamContent instance.
Boiled down, my controller action looks similar to this:
[HttpGet]
[Route("{blobId}")]
public HttpResponseMessage DownloadBlob(int blobId)
{
// ... find the blob in DB and open the 'myBlobStream' based on the given id
var result = new HttpResponseMessage(HttpStatusCode.OK)
{
Content = new StreamContent(myBlobStream)
};
result.Content.Headers.ContentType = new MediaTypeHeaderValue("application/octet-stream");
result.Content.Headers.ContentLength = myBlobStream.Length;
result.Content.Headers.ContentDisposition = new ContentDispositionHeaderValue("attachment")
{
FileName = "foo.txt",
Size = myBlobStream.Length
};
return result;
}
When I hit the endpoint in Chrome (v. 35) it says that it is resolving the host (localhost) and when the file has downloaded it then appears in the download bar. However, I am wondering what is needed to enable Chrome (or any other browser) to show the download progress?
I thought this would be fixed by included the header information like content-type, content-length, and content-disposition, but from what I have tried, that does not make any difference.
Turned out that my implementation was correct. I closed fiddler and everything worked as expected. Don't know if fiddler somehow waits for the entire response to complete before it sends it through its proxy - at least, that would explain why the browser stays in the "resolving host" state until the entire file has been downloaded.
The Web API doesn't "push" information so, unless you have a background thread on your client polling the server for the download status every few seconds or so, this is a bad idea. For a number of reasons in fact:
Increased load on the server to serve multiple requests (imagine if many clients did that at the same time)
Increased data communication from your client (would be important if you were doing this on a mobile phone contract)
etc. (I'm sure I can think of more but it's late)
You might want to consider SignalR for this, although I'm no expert on it. According to the summary in the page I linked:
ASP.NET SignalR is a new library for ASP.NET developers that makes developing real-time web functionality easy. SignalR allows bi-directional communication between server and client. Servers can now push content to connected clients instantly as it becomes available. SignalR supports Web Sockets, and falls back to other compatible techniques for older browsers. SignalR includes APIs for connection management (for instance, connect and disconnect events), grouping connections, and authorization.
If your Web API can allow it, I suppose a potential alternative would be to first send a quick GET request to receive the size of the file you're about to download and store it in your client. In fact, you could utilise the Content-Length header here to avoid the extra GET. Then do your file download and, while it's happening, your client can report the download progress by comparing how much of the file it has received against the full size of the file it got from the server.
I have implemented a Restful web service in C# .Net and I want to enable users to upload images via this.
What I currently have is a service that only accepts text data. Ideally I need to get an image from the user and store it in my database.
[OperationContract]
[WebInvoke(UriTemplate = "/{key}", Method = "POST")]
ResponseStatus InsertSensor(string key, Image image);
My question what is the most efficient way to do this?
Many Thanks,
An image is not something you can transmit down a wire.
Instead, you need to encode the image into a stream or byte array (probably using PNG or JPEG).
The client would then send these bytes to the server, and the server would store it in the database.
Sample project from MSDN: ASP.NET Web API: File Upload and Multipart MIME
Here's another write-up that might be useful: http://blogs.msdn.com/b/henrikn/archive/2012/03/01/file-upload-and-asp-net-web-api.aspx
You could allow the users to post the image to a http handler as described in this question.
I want to push a file to the browser from a website using a webservice. I'm currently reading the file into a base64 byte array, and returning that from the webservice. This webservice is called from a website, and i'm stuck on how to push this as the original file to the browser. Ideally I would like to read the byte array into a memory stream, and then just write it to the Response stream if possible so the end user just downloads the file.
First, rather than send a base64 byte array, have your web service simply return a byte array for your file. Response.OutputStream.Write() will automatically base64 encode your bytes, so you might as well have them un-encoded in your memory stream.
Second, you'll need more than just the bytes. You'll need meta-data associated with the file. For the snippet below, I've placed all of that metadata into a separate class (local instance named "file"). Then, just use this snippet, once you have the data you need:
Response.Clear();
Response.ClearHeaders();
Response.ContentType = file.ContentType;
Response.AddHeader("Content-Disposition", "attachment; filename=\"" + file.FileName + "\"");
Response.AddHeader("Content-Length", file.FileSize.ToString());
Response.OutputStream.Write(file.Bytes, 0, file.Bytes.Length);
Response.Flush();
Response.End();
It's possible, you'll need to make sure you explicitly set the ContentType of the HttpResponse, for example:
Response.ContentType = "image/jpeg";
Response.OutputStream.Write(buffer, 0, buffer.Length);
If you want to control the file name, you'll have to add a Content-Disposition header. Google can help you find the right way to sort that out.
Its usually a bad idea to embed a file in a web service. You just add overhead and complexity with no real benefit.
Instead you should provide a IHttpHandler to handle the file upload. Most web servers also provide helper API's to simplify this, e.g. in ASP.NET you can access the uploaded file with:
HttpContext.Request.Files[0]
There are plenty of javascript file upload scripts that simplify this on the client:
http://www.phpletter.com/Demo/AjaxFileUpload-Demo/
It really depends on the interface to your webservice. Ie SOAP, REST, ASPX.
One thing you can try is to change the content-type in your Response to "Application/octet-stream". Or something similar to tell the receiver the MIME type.
If your using WCF rest you can use Stream as a return type on the web service.