Python client for image upload to WCF service from Raspberry Pi - c#

I have a WCF service running which takes an image file and stores it in the local file system. It is hosted by a console application and runs in the local computer. The code for which is as below.
Iservice.cs
[ServiceContract]
public interface IImageUpload
{
[OperationContract]
[WebInvoke(Method = "POST", UriTemplate = "FileUpload/{fileName}")]
void FileUpload(string fileName, Stream fileStream);
}
Service.cs
public class ImageUploadService : IImageUpload
{
public void FileUpload(string fileName, Stream fileStream)
{
FileStream fileToupload = new FileStream("C:\\ImageProcessing\\Images\\Destination\\" + fileName, FileMode.Create);
byte[] bytearray = new byte[5000000];
int bytesRead, totalBytesRead = 0;
do
{
bytesRead = fileStream.Read(bytearray, 0, bytearray.Length);
totalBytesRead += bytesRead;
} while (bytesRead > 0);
fileToupload.Write(bytearray, 0, bytearray.Length);
fileToupload.Close();
fileToupload.Dispose();
}
}
console program.cs to host
static void Main(string[] args)
{
string baseAddress = "http://192.168.1.4:8000/Service";
WebHttpBinding wb = new WebHttpBinding();
wb.MaxBufferSize = 4194304;
wb.MaxReceivedMessageSize = 4194304;
wb.MaxBufferPoolSize = 4194304;
ServiceHost host = new ServiceHost(typeof(ImageUploadService), new Uri(baseAddress));
host.AddServiceEndpoint(typeof(IImageUpload), wb, "").Behaviors.Add(new WebHttpBehavior());
//host.AddServiceEndpoint(typeof(IImageUpload), new WebHttpBinding(), "").Behaviors.Add(new WebHttpBehavior());
host.Open();
Console.WriteLine("Host opened");
Console.ReadKey(true);
}
Now I have a C# client which is just a simple windows form with a button to upload that talks with this service. It takes a file from its local system and sends it to the service. Code is as below.
private void button1_Click(object sender, EventArgs e)
{
byte[] bytearray = null;
string name = "PictureX.jpg";
Image im = Image.FromFile("C:\\ImageProcessing\\Images\\Source\\Picture1.jpg"); // big file
bytearray = imageToByteArray(im);
string baseAddress = "http://192.168.1.4:8000/Service/FileUpload/";
HttpWebRequest request = (HttpWebRequest)HttpWebRequest.Create(baseAddress + name);
request.Method = "POST";
request.ContentType = "text/plain";
request.ContentLength = bytearray.Length;
Stream serverStream = request.GetRequestStream();
serverStream.Write(bytearray, 0, bytearray.Length);
serverStream.Close();
using (HttpWebResponse response = request.GetResponse() as HttpWebResponse)
{
int statusCode = (int)response.StatusCode;
StreamReader reader = new StreamReader(response.GetResponseStream());
}
}
public byte[] imageToByteArray(Image imageIn)
{
MemoryStream ms = new MemoryStream();
imageIn.Save(ms, System.Drawing.Imaging.ImageFormat.Jpeg);
return ms.ToArray();
}
Both of them are working fine when I am running it on separate visual studio inside the same laptop. I do not have an app.config or web.config in my service. Everything is written in the code.
Entire code can be found in the below link.
https://github.com/logrcubed/ImageprocessingAlgorithm_WCF
Now I hook in a raspberry pi to the same WiFi (read local LAN) and want to write a python script to upload an image from a local folder in Pi to WCF service similar to my C# client. *How to achieve this? What is the python code for getting this done? I am new to python. So any help is appreciated.*
I tried the below approaches as a hit and trial most of which gave 404 errors. I do not understand whether these are right or not. Could anyone help me in converting the webrequest in C# to python?
Poster library
# test_client.py
from poster.encode import multipart_encode
from poster.streaminghttp import register_openers
import urllib2
# Register the streaming http handlers with urllib2
register_openers()
# Start the multipart/form-data encoding of the file "DSC0001.jpg"
# "image1" is the name of the parameter, which is normally set
# via the "name" parameter of the HTML <input> tag.
# headers contains the necessary Content-Type and Content-Length
# datagen is a generator object that yields the encoded parameters
datagen, headers = multipart_encode({"image1": open("/home/pi/test.jpg", "rb")})
# Create the Request object
request = urllib2.Request("http://192.168.1.6:8000/Service/", datagen, headers)
# Actually do the request, and get the response
print urllib2.urlopen(request).read()
urllib2
import urllib2
import MultipartPostHandler
params = {'file':open( "/home/pi/test.jpg" , 'rb')}
opener = urllib2.build_opener(MultipartPostHandler.MultipartPostHandler)
urllib2.install_opener(opener)
req = urllib2.Request( "http://192.168.1.6:8000/Service/FileUpload" , params)
text_response = urllib2.urlopen(req).read().strip()
requests
import requests
url = 'http://192.168.1.4:8000/Service'
headers = {'content-type': 'text/plain'}
files = {'file': open('/home/pi/test.jpg', 'rb')}
r = requests.post(url, files=files, headers=headers)

Related

Download a URL image to a client PC via C#

I'm trying to access a file on the server via an api that is behind Basic Auth. I then want to download that to a client's PC.
I've got the following code which does GET the url from behind the basic auth, however the image never downloads properly. I either get a failed network error message or I get a message saying I can't download it because my machine doesn't have an app installed to open it. It's a png so it definitely does!
It goes the whole way through the code and doesn't error so I'm confused as to why it's not downloading correctly to the clients machine (my pc while I'm testing!)
In the code I am specifying one file and I have specified it's length as bytes just to try and narrow down where I'm going wrong. Normally this could be any file that's being access of any length!
This is the code I have:
//Create a stream for the file
Stream stream = null;
var size = fileResp.ContentLength; //I used this to determine the file was 64196 in size
//This controls how many bytes to read at a time and send to the client
int bytesToRead = 64196;
// Buffer to read bytes in chunk size specified above
byte[] buffer = new Byte[bytesToRead];
string url= "https://myURL/images/image-2019-04-02-16-25-18-458.png";
WebRequest myReq = WebRequest.Create(url);
string credentials = "username:pwd";
CredentialCache mycache = new CredentialCache();
myReq.Headers["Authorization"] = "Basic " + Convert.ToBase64String(Encoding.ASCII.GetBytes(credentials));
myReq.Method = "GET";
// The number of bytes read
try
{
//Create a response for this request
HttpWebResponse fileResp = (HttpWebResponse)myReq.GetResponse();
if (myReq.ContentLength > 0)
fileResp.ContentLength = myReq.ContentLength;
//Get the Stream returned from the response
stream = fileResp.GetResponseStream();
// prepare the response to the client. resp is the client Response
var resp = HttpContext.Current.Response;
//Indicate the type of data being sent
string contentType = MimeMapping.GetMimeMapping("new.png");
resp.ContentType = contentType;
string fileName = "new.png";
//Name the file
resp.AddHeader("Content-Disposition", "attachment; filename=\"" + fileName + "\"");
resp.AddHeader("Content-Length", fileResp.ContentLength.ToString());
int length;
do
{
// Verify that the client is connected.
if (resp.IsClientConnected)
{
// Read data into the buffer.
length = stream.Read(buffer, 0, bytesToRead);
// and write it out to the response's output stream
resp.OutputStream.Write(buffer, 0, length);
// Flush the data
resp.Flush();
//Clear the buffer
buffer = new Byte[bytesToRead];
}
else
{
// cancel the download if client has disconnected
length = -1;
}
} while (length > 0); //Repeat until no data is read
}
finally
{
if (stream != null)
{
//Close the input stream
stream.Close();
}
}
The output from here: fileResp.GetResponseStream();
At first, please try to test if the following code works on your computer.
private bool DownloadImage(string imgurl, string filename)
{
HttpWebRequest request = (HttpWebRequest)WebRequest.Create(imgurl);
HttpWebResponse response = null;
try
{
response = (HttpWebResponse)request.GetResponse();
}
catch
{
response = null;
return false;
}
if (response != null && response.StatusCode == HttpStatusCode.OK)
{
Stream receiveStream = response.GetResponseStream();
Bitmap bitmap = new Bitmap(receiveStream);
if (bitmap != null)
{
bitmap.Save(filename);
}
receiveStream.Flush();
receiveStream.Close();
response.Close();
return true;
}
else
{
return false;
}
}
private void button1_Click(object sender, EventArgs e)
{
string imgurl = "https://upload.wikimedia.org/wikipedia/commons/4/42/Cute-Ball-Go-icon.png";
string filename = "D:\\download_test.png";
bool bIsDownloadSuccess = DownloadImage(imgurl, filename);
}
This code works on me well.
It doesn't have error, but returns false.
Please check where false is returned.
If it has some error, the problem will be on Windows System.
Please try and let me know.
Thanks.

Can't get over the "Cookies policy" page when trying to get a site's favicon

I am trying to get the website's favicon's by adding "/favicon.ico" to the domain
I make a request, get the stream, convert it to a memorystream, and then to an image.
For most sites, it works perfectly. For this one, I have a problem :"https://www.7sur7.be/"
Trying to get the favicon from https://www.7sur7.be/favicon.ico breaks when converting the memorystream to an image, because the stream is filled with the Cookies policy page.
Manually entering this address in a browser gets you to the cookies policy page, then to the icon
What I need is a request recognized as accepting cookies.
Here's the shortest code I could write to expose the problem.
public void Test()
{
var url = #"https://www.7sur7.be/favicon.ico";
//Try it with https://www.stackoverflow.com/favicon.ico and you'll end up with an Icon
var memStream = new MemoryStream();
Stream stream = GetStream(url);//defined below
byte[] buffer = new byte[1024];
int byteCount;
do
{
byteCount = stream.Read(buffer, 0, buffer.Length);
memStream.Write(buffer, 0, byteCount);
} while (byteCount > 0);
var img = Image.FromStream(memStream, true, true);
var bm = new Bitmap(img);
Icon ic = Icon.FromHandle(bm.GetHicon());
}
Here is the original GetStream() method:
private static Stream GetStream(string url)
{
WebRequest requestImg = WebRequest.Create(url);
WebResponse response = requestImg.GetResponse();
return response.GetResponseStream();
}
Inspired by this SO post, here is another GetStream()
implementation:
public Stream GetStream(string url)
{
CookieContainer cookieContainer = new CookieContainer();
HttpWebRequest httpWebRequest = (HttpWebRequest)WebRequest.Create(url);
httpWebRequest.CookieContainer = cookieContainer;
var response = (HttpWebResponse)httpWebRequest.GetResponse();
HttpWebRequest httpWebRequest2 = (HttpWebRequest)WebRequest.Create(url);
httpWebRequest2.CookieContainer = cookieContainer;
WebResponse response2 = httpWebRequest2.GetResponse();
return response.GetResponseStream();
}
Inspired by this SO post, here is another attempt:
(CookieAwareWebClient class in the link)
public void Test2()
{
var url = #"https://www.7sur7.be/favicon.ico";
//Try it with https://www.stackoverflow.com/favicon.ico and you'll end up with an Icon
var uri = new Uri(url);
var host = uri.Host;
CookieContainer cookieJar = new CookieContainer();
var cook = new Cookie("mycookie", "cookievalue", "/", host);
cookieJar.Add(cook);
CookieAwareWebClient client = new CookieAwareWebClient(cookieJar);
var bytes = client.DownloadData(url);
Icon icon;
using (MemoryStream ms = new MemoryStream(bytes))
{
icon = new Icon(ms);
}
}
I tried other solutions found here and there, and nothing seems to work. Could someone make the above code work? The final solution should be portable to other computers. Thanks!

Progress in uploading in ftp server c#

I ve got the following code which
foreach (string dir in dirs) { //dirs all files in directory
try{
// Get an instance of WebClient
WebClient client = new System.Net.WebClient();
// parse the ftp host and file into a uri path for the upload
Uri uri = new Uri(m_FtpHost + new FileInfo(dir).Name);
// set the username and password for the FTP server
client.Credentials = new System.Net.NetworkCredential(m_FtpUsername, m_FtpPassword);
// upload the file asynchronously, non-blocking.
client.UploadFileAsync(uri, "STOR",dir);
}
catch(Exception e){
print(e.Message);
}
}
Can I retrieve back the progress of the upload? I have in the dirs 4-5 files. I want exact the progress (not the files uploaded/(total files))
EDIT: Thus the right approach is the following:
public int percentage;
try{
// Get an instance of WebClient
WebClient client = new System.Net.WebClient();
// parse the ftp host and file into a uri path for the upload
Uri uri = new Uri(m_FtpHost + new FileInfo(dir).Name);
// set the username and password for the FTP server
client.Credentials = new System.Net.NetworkCredential(m_FtpUsername, m_FtpPassword);
// upload the file asynchronously, non-blocking.
client.UploadProgressChanged += WebClientUploadProgressChanged;
client.UploadFileCompleted += WebClientUploadCompleted;
client.UploadFileAsync(uri, "STOR",dir);
}
void WebClientUploadProgressChanged(object sender, UploadProgressChangedEventArgs e)
{
percentage = e.ProgressPercentage;
}
void WebClientUploadCompleted(object sender, UploadFileCompletedEventArgs e)
{
print( "Upload is finished. ");
}
I add this implementation to my code, however it seems that it doenst print anything in the console.
WebClient contains a dedicated event for this
public event UploadProgressChangedEventHandler UploadProgressChanged
https://msdn.microsoft.com/en-us/library/system.net.webclient.uploadprogresschanged(v=vs.110).aspx
EDIT : HttpWebRequest approach based on a google result :
HttpWebRequest request = (HttpWebRequest)WebRequest.Create(uri);
request.Method = "POST";
request.ContentType = "text/plain";
request.Timeout = -1; //Infinite wait for the response.
// Get the file information object.
FileInfo fileInfo = new FileInfo("C:\\Test\\uploadFile.dat");
// Set the file content length.
request.ContentLength = fileInfo.Length;
// Get the number of segments the file will be uploaded to the stream.
int segments = Convert.ToInt32(fileInfo.Length / (1024 * 4));
// Get the source file stream.
using (FileStream fileStream = fileInfo.OpenRead())
{
// Create 4KB buffer which is file page size.
byte[] tempBuffer = new byte[1024 * 4];
int bytesRead = 0;
// Write the source data to the network stream.
using (Stream requestStream = request.GetRequestStream())
{
// Loop till the file content is read completely.
while ((bytesRead = fileStream.Read(tempBuffer, 0, tempBuffer.Length)) > 0)
{
// Write the 4 KB data in the buffer to the network stream.
requestStream.Write(tempBuffer, 0, bytesRead);
// Update your progress bar here using segment count.
}
}
}
// Post the request and Get the response from the server.
using (WebResponse response = request.GetResponse())
{
// Request is successfully posted to the server.
}

Uploading binary data from C# to PHP

I want to upload files from a Windows C# application to a web server running PHP.
I am aware of the WebClient.UploadFile method but I would like to be able to upload a file in chunks so that I can monitor progress and be able to pause/resume.
Therefore I am reading part of the file and using the WebClient.UploadData method.
The problem I am having is that I don't know how to access data sent with UploadData from php. If I do print_r on the post data I can see that there is binary data but I don't know the key to access it. How can I access the binary data? Is there a better way I should be doing this altogether?
String file = "C:\\Users\\Public\\uploadtest\\4.wmv";
using (BinaryReader b = new BinaryReader(File.Open(file, FileMode.Open)))
{
int pos = 0;
int required = 102400;
b.BaseStream.Seek(pos, SeekOrigin.Begin);
byte[] by = b.ReadBytes(required);
using (WebClient wc = new WebClient()){
wc.Headers.Add("Content-Type", "application/x-www-form-urlencoded");
byte[] result = wc.UploadData("http://192.168.0.52/html/application.php", "POST", by);
String s = System.Text.Encoding.UTF8.GetString(result, 0, result.Length);
MessageBox.Show(s);
}
}
This is how I do my HTTP communications.
I guess when I reach using(), the HTTP connection is being set up, and inside the using() {...} body you can do pausing and stuff.
string valueString = "...";
string uriString = "http://someUrl/somePath";
HttpWebRequest httpWebRequest = (HttpWebRequest)WebRequest.Create(uriString);
httpWebRequest.Method = "POST";
string postData = "key=" + Uri.EscapeDataString(valueString);
byte[] byteArray = Encoding.UTF8.GetBytes(postData);
httpWebRequest.ContentType = "application/x-www-form-urlencoded";
httpWebRequest.ContentLength = byteArray.Length;
using (Stream dataStream = httpWebRequest.GetRequestStream())
{
// do pausing and stuff here by using a while loop and changing byteArray.Length into the desired length of your chunks
dataStream.Write(byteArray, 0, byteArray.Length);
}
HttpWebResponse httpWebResponse = (HttpWebResponse)httpWebRequest.GetResponse();
Stream receiveStream = httpWebResponse.GetResponseStream();
StreamReader readStream = new StreamReader(receiveStream);
string internalResponseString = readStream.ReadToEnd();
But when uploading a file, you should probably use multipart/form-data in stead of application/x-www-form-urlencoded. See also: http://www.php.net/manual/en/features.file-upload.post-method.php
In php you can use the superglobal variable $_FILES (eg print_r($_FILES); ) to access the uploaded file.
And also read this: https://stackoverflow.com/a/20000831/1209443 for more information how to deal with multipart/form-data
Use this. This will work for sure.
System.Net.WebClient Client = new System.Net.WebClient();
Client.Headers.Add("Content-Type", "binary/octet-stream");
byte[] result = Client.UploadFile("http://192.168.0.52/mipzy/html/application.php", "POST", file);
string s = System.Text.Encoding.UTF8.GetString(result, 0, result.Length);
MessageBox.Show(s);
Or the one with using
using (System.Net.WebClient Client = new System.Net.WebClient())
{
Client.Headers.Add("Content-Type", "binary/octet-stream");
byte[] result = Client.UploadFile("http://192.168.0.52/mipzy/html/application.php", "POST", file);
string s = System.Text.Encoding.UTF8.GetString(result, 0, result.Length);
MessageBox.Show(s);
}
Without binary reader. IF you want binary reader, you also must provide some multipart parameters to the form. This is automatically done by that UploadFile thing.

get image from web service and show on Winforms

i m developing a C# Window Application which uses web service as it's back end,
how to get image from specified URL:
the image on server is in JPEG Format
var client = new RestClient();
client.BaseUrl = "http://www.*****.com/images/12345.jpg";
var request = new RestRequest();
IRestResponse response = client.Execute(request);
Using RestSharp I did it this Way
var client = new RestClient();
client.BaseUrl = "http://www.abcd.com/image1.jpg";
var request = new RestRequest();
picturebox1.Image = new Bitmap(new MemoryStream(client.DownloadData(request)));
Showing Image at Picture Box
If the client has the image URL, why not just use HTTP to download it? Or are you saying that the images will always reside on the same server that the WebService is running on, and that the WebService method should accept a URL, translate it to a local path, and return the image as a byte array?
We have a method of our WSDL WebService that does about the same thing, we don't include the protocol and host portions of the URL (they'd be redundant.)
[WebMethod]
public byte[] GetPicture(string ImageURL)
{
if (ImageURL.StartsWith("http"))
return new byte[0];
string tmp = System.Web.Hosting.HostingEnvironment.MapPath("/" + ImageURL);
string FileName = Microsoft.JScript.GlobalObject.unescape(tmp);
if (System.IO.File.Exists(FileName))
{
FileStream fs = System.IO.File.OpenRead(FileName);
byte[] buf = new byte[fs.Length];
fs.Read(buf, 0, (int)fs.Length);
fs.Close();
return buf;
}
else
return new byte[0];
}
Does that answer your question?

Categories