Get Solvemedia image using RestSharp - c#

I'm developing an application which needs to make a query on a website to extract certain data, such as the user's name, points / remaining balance etc.
I present a problem in the login, the client needs to solve a captcha solvemedia to be able to enter the website, I would like to extract the image of this captcha and show it to the client but I am having problems to extract it, i'm trying to do it through http requests with RestSharp, the reason I do not do it with a webbrowser or selenium is that it spends a lot more resources.
i try this:
RestClient restClient = new RestClient(#"//api-secure.solvemedia.com/papi/media?c=2#gAB09NHSertXLv3TnpobmKDxvkjsaT4m#X4wLMdkN.u0ENU8bgrS3KH9APTC4lJjokJaIfZePPIgNLL84QkOaQlXcxzHvOVTTU98Of7mo8BoC0QQuiH1RMqMrGof6BbL-tReeY8AHhPA7-nwvQKLqUEXQwTL4HhLXfZVre9jccpqQxFGIRYZH1ZQoAKCV5k1TGCLXXP9vMVsJFntDNz6Ozik02MANT1siBJRYTNIpGcj6p6Gbq5j0HvQChz7jtgdzwlj7nee0BdZphpg27ikQlVB5IUelMvSjzNNvPZawB9YbC9v6zyJngNQaJIJku2SPJkhFXIK0uoA;w=300;h=150;fg=000000;bg=f8f8f8");
var fileBytes = restClient.DownloadData(new RestRequest("#", Method.GET));
File.WriteAllBytes(Path.Combine(directory, "poster-got.jpg"), fileBytes);
The problem with this is that I only get an image that says "Media Error", Is there any way to get the image that is sent when you request the login page? Can it be done with restsharp? , if not with what library could I do it?

For downloading image I use https://github.com/jgiacomini/Tiny.RestClient
But when I try to view your image in in my browser I have a media error. I think you use a wrong url.
In your case
using Tiny.RestClient;
var client = new TinyRestClient(new HttpClient(), "#"http//api-secure.solvemedia.com");
FileInfo fileInfo = await client.
GetRequest("papi/media").
AddQueryParameter("2#gAB09NHSertXLv3TnpobmKDxvkjsaT4m#X4wLMdkN.u0ENU8bgrS3KH9APTC4lJjokJaIfZePPIgNLL84QkOaQlXcxzHvOVTTU98Of7mo8BoC0QQuiH1RMqMrGof6BbL-tReeY8AHhPA7-nwvQKLqUEXQwTL4HhLXfZVre9jccpqQxFGIRYZH1ZQoAKCV5k1TGCLXXP9vMVsJFntDNz6Ozik02MANT1siBJRYTNIpGcj6p6Gbq5j0HvQChz7jtgdzwlj7nee0BdZphpg27ikQlVB5IUelMvSjzNNvPZawB9YbC9v6zyJngNQaJIJku2SPJkhFXIK0uoA;w=300;h=150;fg=000000;bg=f8f8f8").
DownloadFileAsync("c:\"poster-got.jpg");

Related

Inserting Image With Inline HTML

I am new to Web APIs, so sorry if I am missing information. I am trying to send an email from my web api with an image (not as an attachment), but I am having issues with the inline html.
Example (This is in the WebAPI Controller)
message Body = "<p>Here is an image</p>" + Model.Image;
Now this will not work, as it displays "System.Byte[]", so my alternative was to convert it with some inline html, such as...
message Body = "<p>Here is an image</p>" + "<img src=\"data:image/gif;base64,#System.Convert.ToBase64String{Model.Image)\" />;
This will return an empty element. What am I doing wrong? If I were to guess, I am not using quotations correctly, but I cannot find anyone trying to insert an image the way I am.
Site note - If I see what is being sent from the mobile app for the image, I am getting a huge string of text that is always the same, regardless of whether it is a different image. I thought I would use that like src="data:image/gif;base64,", but I just get a long string returned in the email.
You need to host your image somewhere else and use the full path. Example:
<img scr="https://static.makeuseof.com/wp-content/uploads/2017/12/test-html-online-670x335.jpg" />
Most email clients do not display base64 images. My solution was to attach the image to the email by using the following code.
MemoryStream ms = new MemoryStream(Model.Image);
message.Attachments.Add(new Attachment(ms, "Image.png", "image/png"));
I did not need to convert from byte to base64, as this was done on the mobile app before being sent to the API, so I just referenced the value that was stored in the model.

How to "create the video" after file uploaded to DailyMotion using c#

Im following the instructions from here to publish a new video on DailyMotion, using c# and a WebClient.
i successfully got the auth-token, then an upload url, then the actual file to upload. im stuck at step 4, called: "create the video"
it states to POST url=<the url i got from previous step> to https://api.dailymotion.com/me/videos (with the Authorization token in the header), but all my attempts result in "bad request" - without further explanation.
any ideas?
using (var client = new WebClient())
{
var createRequest = $"url={videoUpload.url}";
client.Headers.Add("Authorization", $"Bearer {authToken.access_token}");
client.Headers.Add("Content-Type", "application/x-www-form-urlencoded");
var createVideo = client.UploadString("https://api.dailymotion.com/me/videos", "POST", createRequest);
}
also tried:
var createRequest = $"url={HttpUtility.UrlEncode(videoUpload.url)}";
I tried your code and my video was created successfully. As explained in our documentation a 400 error is related to a missing/invalid parameter.
I assume you are trying to send the upload url (returned in step 2) instead of the url returned by step 3 (url of your uploaded file).
You can find an article (with examples of returned values) which use a simplified way to upload on Dailymotion here.

C# loading html of a webpage currently on

I am trying to make a small app that can log in automatically on a website, get certain texts on the website and return to user.
To show what I have, I did below to make it log in,
System.Windows.Forms.HtmlDocument doc = logger.Document as System.Windows.Forms.HtmlDocument;
try
{
doc.GetElementById("loginUsername").SetAttribute("value", "myusername");
doc.GetElementById("loginPassword").SetAttribute("value", "mypassword");
doc.GetElementById("loginSubmit").InvokeMember("click");
And below to load html of the page
WebClient myClient = new WebClient();
Stream response = myClient.OpenRead(webbrowser.Url);
StreamReader reader = new StreamReader(response);
string src = reader.ReadToEnd(); // finally reading html and saving in variable
Now, it successfully loaded html but html of the page where it's not logged in. Is there a way to refer to current html somehow? Or another way to achieve my goals. Thank you for reading!
Use the Webclient class so you can use sessions and cookies.
check this Q&A: Using WebClient or WebRequest to login to a website and access data
Why don't you make REST API calls and send the data like username and password from your code itself?
Is there any Web API for the URL ? If yes , you can simply call the service and pass on the required parameters. The API shall return in JSON/XML which you can parse and extract information

Exception in BackgroundUploader

I am trying to upload some avi file to server. It works fine with HttpRequest but i need to continue uploading even if i suspend app so thats why i am trying to use BackgroundUploader. I am following this guideline on msdn http://msdn.microsoft.com/en-us/library/windows/apps/jj152727.aspx. So my code looks something like this.
StorageFile storageFile = KnownFolders.VideosLibrary.GetFileAsync("fileName");
BackgroundUploader uploader = new BackgroundUploader();
uploader.Method = "POST";
uploader.SetRequestHeader("Content-Type", "multipart/form-data; boundary=" + boundary);
var fs = await storageFile.OpenAsync(Windows.Storage.FileAccessMode.ReadWrite);
IInputStream aaaa = fs.GetInputStreamAt(0);
UploadOperation upload = uploader.CreateUploadFromStreamAsync(new Uri("uploadUri"), aaaa);
await HandleUploadAsync(upload, true);
the rest is same as on MSDN. And i am getting exception Unsupported media type (415) in method HandleUploadAsync on line
await upload.StartAsync().AsTask(cts.Token, progressCallback);
What am i doing wrong? Or what can cause this kind of exception?
EDIT : I solved my problem as i commented down here and in my answer. I think at the end i am basically just sending some data to server that are recognized and interpreted as i want to. So if i use BackgroundUploader i am not only uploading some file i am also sending information about how am i doing that(as i mentioned in my answer). So by the same idea i can also upload folder to server and by that i am not sending any actual content only some description about how to do that. And if i compare request that i am making by HttpRequest and BackgroundUploader they are equal and thats what i wanted.
So the problem part was the header of request. I have some header in my request that is recognized by server and i was trying to put it to BackgroundUploader through SetRequestheader method but it did not work. As Kieqic suggested i used Fiddler and by that i compare request made by HttpRequest and BackgroundUploader. I found out they are completely different. So through SetRequestheader i add some parts like expected Content-Type and for the rest parts of header to make them equal i add it before content of my file as array of bytes. And this works so conclusion is in my case using Fiddler that helped my how to construct request header.

File download via Webapi controller - handling errors

I am working on an application that provides some links for users to download files.
The page itself is served up by an MVC controller but the links are pointing to a WebAPI controller running on a separate domain.
(I would have preferred same domain but for various reasons it has to be a separate project and it will run on a separate domain. I don't think CORS is part of the issue anyway as this is not using XHR, but I mention it just in case).
So in development, the main MVC project is http://localhost:56626/Reports/
And the links on the page might look like this:
Report 12345
where port 51288 is hosting the Web API.
The WebAPI controller uses ReportID to locate a file, and write its contents into the response stream, setting the disposition as an attachment:
//security.permission checks and scaffolding/database interaction
//left out for clarity
try
{
string filename = #"C:\ReportFiles\TestReport.csv";
var stream = new FileStream(path, FileMode.Open);
result.Content = new StreamContent(stream);
result.Content.Headers.ContentType = new MediaTypeHeaderValue("text/csv");
var disp = new ContentDispositionHeaderValue("attachment");
disp.FileName = "TestReport.csv";
result.Content.Headers.ContentDisposition = disp;
return result;
}
catch(Exception ex)
{
//how to return a response that won't redirect on error?
}
By doing this the user can then click on the link and without any redirection, the user gets prompted to save or open the file, which is what I want; they stay on the original page with the links and just get an Open/Save dialog from the browser.
The problem arises when something goes wrong in the Web API controller - either an exception or some internal logic condition that means the file cannot be downloaded.
In this case when clicking the link, the download doesn't happen (obviously) and they get taken to the target URL instead i.e http://localhost:51288/api/ReportDownload?ReportID=12345 which is not desirable for my requirements.
I would much rather be able to catch the error somehow on the client-side by returning for e.g. HTTP 500 in the response, and just display a message to the user that the download failed.
Now to be honest, I don't even understand how the browser can do the "in place" File/Save dialog in the first place:
I always thought if you click a link that has no explicit target attribute,the browser would just open the new request in your current tab i.e it's just another GET request to the target URL, but it seems this is not the case
The browser seems to be doing a hidden background fetch of the target URL in this case (same behaviour in FF,Chrome and IE) which I cannot even see in the F12 tools.
The F12 Network log shows no activity at all except in the specific case where the response has NOT been setup as Content-Disposition: attachment i.e an error -only in this case do I see the (failed) HTTP GET being logged in the Network request list.
I suppose I could just catch any exception in the controller and send back a dummy file called "Error.csv" with contents "Ha Ha Nope!" or something similar, but that would be a last resort...any ideas welcome!
If the user clicks on the link, the browser will follow it - then depending on the response headers and browser configuration, it'll either show the file dialog or render directly - you can't really change that behavior (apart from using preventDefault when the link is clicked, which kind of defeats the purpose).
I'd suggest taking a closer look at http://jqueryfiledownload.apphb.com/ which lets you do something like this:
$.fileDownload('some/file/url')
.done(function () { alert('File download a success!'); })
.fail(function () { alert('File download failed!'); });
Then you could bind the download action using jQuery.

Categories