Download file from URL with parameters and authentication required - c#

Sorry for disturbing you, but I tried during more than a week and did no find a simple and efficient way to reach this goal, so I'm here to ask your help. I have a recurrent task in my job that follow this steps:
Access my company website;
Sign-in;
Make a search;
Download a KMZ file from the search result page.
I do it every week and need to download more then 100 files per time, do you know?
I have a list with all result I need, so I created an application in c# to automate this process, but when the file is downloaded it is not the correct type (KMZ) and its content is the login page source code. It happens because I don't have the correct file name, it is loaded by some parameters in URL like https://mycompanywebsite.org/files/fileViewServlet?Parameter1=abx&Parameter2=xyz&Parameter3=123
That's what I did.
//Download the file for the returned list
foreach (DataGridViewRow row in dataGridView1.Rows)
{
using (WebClient client = new WebClient())
{
//client.Credentials = new NetworkCredential("username", "password");
String credentials = Convert.ToBase64String(Encoding.ASCII.GetBytes("myusernae" + ":" + "mypassword"));
client.Headers[HttpRequestHeader.Authorization] = $"Basic {credentials}";
try
{
//Download the KMZ
client.Proxy = null;
client.QueryString.Add("parameter1", "value");
client.QueryString.Add("parameter2", "value");
client.QueryString.Add("parameter3", "value");
outputFileName = "File_Name_" + row.Cells["FieldTitle"].Value.ToString() + ".kmz";
client.DownloadFile("https://mycompanywebsite.org/files/fileViewServlet?", strTargetFolder + nomeArquivoEstaca);
}
catch (WebException ex)
{
MessageBox.Show(ex.ToString());
}
}
}
If you have any sample to help me reach this goal, I'll really appreciate it.
Thanks very much.

Nobody has a way that I can reach this goal? The major problem here is the fact that I have no access to the file name on the URL. As I can see, the file is downloaded from a server action when the URL with that parameters is called. Is some function that I can use to find the name of the file and use it do download it in c# windows or web application?

Related

Download file from URI vs. Return file from Web API

While owning/hosting a Web API 2 application, I am writing a desktop application where I need to download a .zip file based on certain criteria. I have come across two approaches and am not sure which is more secure and proper:
1) In the initial approach, I made a function call to my web api with the provided criteria. The API would create the zip file and return a specific path string. Then, I used the WebClient.DownloadFileAsync to download the related file from the path:
private async Task<bool> DownloadFile(SOME PARAMETER)
{
var result = false;
var _stopwatch = new Stopwatch();
try
{
using (var _client = new WebClient())
{
// Returns the Uri of the file
var downloadAddress = await GetDownloadFileAddress(SOME PARAMETER);
if (!string.IsNullOrEmpty(downloadAddress))
{
// Some local path
var downloadFilePath = "C:\MyLocalPath"
_stopwatch.Start();
_client.DownloadFileCompleted += wc_DownloadFileCompleted;
_client.DownloadProgressChanged += wc_DownloadProgressChanged;
_client.DownloadFileAsync(new Uri(downloadAddress), downloadFilePath);
result = true;
}
}
}
catch (Exception ex)
{
ModErrorHandler.HandleError(ex, MethodBase.GetCurrentMethod().Name, Application.ProductName);
}
return result;
}
I like the above because the files could be near a 1 gig and so I can display progress bar to show the download progress and also copy the file into a specific local path. However, I am concerned that it is not a secure way to pass the Uri openly(?!)
2) Then, I thought I could return the related file from the API directly. A sample code could be found here:
How to return a file (FileContentResult) in ASP.NET WebAPI
The api authentication will now take care of security and invalid download requests. However, I am not sure if this is a wise approach for files that over 1gb. More importantly, I am not sure how to show the download progress in my progress bar and how to copy the file into a specific local path, both of which would be taken care of in the first approach.
Can someone advise which method is truly the correct way? And if 2, suggest a few hints for the questions that I have raised after?

Get data in file without indicating a particular filepath

I am tasked to create a web service API where for an example, when an URL http://localhost:12345/api/filereader/data.txt is entered in the web browser, the data which is in data.txt file has to be displayed in the web page. I am able to do it if I know the filepath of data.txt.
However another requirement is that I am not supposed to indicate the filepath (in my code) as the scenario is, user is supposed to be able to use the URL API and input the .txt file name as a parameter (from whichever computer/server they are using) to get the data of what is in the .txt file that they have indicated. Therefore there should not be any physical path in my code. Is it possible to achieve that?
Here is the code that I have tried (with filepath):
ReaderController.cs
[ResponseType(typeof(string))]
public IHttpActionResult Get(String FileName)
{
try
{
string fileName = FileName;
string path = "C:\\Users\\attsuap1\\Desktop\\" + fileName;
string result = File.ReadAllText(path);
var resultDTO = JsonConvert.DeserializeObject(result);
return Ok(resultDTO);
}
catch
{
var result = "File does not exist";
return Ok(new { ErrorMessage = result });
}
}
How do I edit this code to get what I want?
You are asking to load a file from a user device from your server. That is just not possible for security purposes (imagine what would happen if you could).
The only way to get access to a file from the user, is by letting the user send it using some sort of upload form or control. The posted data can be used by your server then.

How to download a public shared file from google drive with C#

I'm trying to download a public shared file from Google Drive using C#.
Here's the code I'm currently using
DriveService.Files.Get(fileId);
Where the fileID is taken from the URL
https://drive.google.com/file/d/{ fileID }/view?usp=sharing
Now this all seems like it should work no problem, but I'm getting a file not found error every time.
I've done this previously with getting a list of files from a public folder that is shared and I managed to get that one working by using this query
ListRequest request = service.Files.List();
request.Q = $"'{ folderID }' in parents";
request.Fields = "files(mimeType,id,modifiedTime,name,version,originalFilename)";
The in parents section is what made this one work, but I can't think of a similar way to make the Get query work, it seems like it should just work if given the right ID and I have the permissions.
I'm definitely logged in correctly, as I'm able to download other files, so I know that's not the problem either.
Any help would be greatly appreciated.
The File Resource returned by request.Execute(); contains a WebContentLink property. It is a link for downloading the content using cookie based authentication. In cases where the content is shared publicly, the content can be downloaded without any credentials.
Or you could just do (in API v2):
var request = MyService.Files.Get(FileID);
var stream = new System.IO.MemoryStream();
try
{
request.Download(stream);
System.IO.FileStream file = new System.IO.FileStream(PathToSave, System.IO.FileMode.Create, System.IO.FileAccess.Write);
Stream.WriteTo(file);
file.Close();
}
catch (Exception ex)
{
MessageBox.Show(ex.Message, "Error Occured:", MessageBoxButtons.OK, MessageBoxIcon.Error);
}
You won't have a downloadlink if the file you are trying to download is a native Google Docs format. If that's the case you must look for the ExportLinks.
You will have several export links, so you will have to choose which format suits you best.
The issue ended up being related to permission scopes when authenticating through GoogleWebAuthorizationBroker.AuthorizeAsync().
I'd played with these previously, and I thought it just didn't work, but it turns out you have to delete any previous credentials for these changes to actually work. See the comments in google's sample.
To read public files I had to add the following permission to my scope
DriveService.Scope.DriveReadonly
Hopefully nobody else will stare at their screen for hours now.

Dowload a pdf from a link with c#

I have a windows service application that needs to download pdf files from different public web sites and save them locally to a folder on the server
I tried to use System.Net.WebClient to perform the download like this
client = new WebClient();
client.DownloadFile(new Uri(fileLink, UriKind.Absolute), destination);
destination is the full path and name to the folder where I need to save the file to. example: \server-name\downloads\file123.pdf
fileLink is the url to the pdf file
One of the links I am trying to save is: https://www.wvmmis.com/WV%20Medicaid%20Provider%20SanctionedExclusion/WV%20Medicaid%20Exclusions%20-%20June%202016.pdf
The code works but the file that is saved is corrupted and cannot be opened by Acrobat reader or any pdf reader.
If you click the link above and do save as and save the page locally to a pdf, then you can open it fine. So the problem is not that the pdf is really corrupted, but WebClient is not saving it right.
Is there any configuration I can do to the WebClient that causes it to save the file correctly, or is there another way to do it that does save it right ?
Thank you
I wrote something similar long time ago
try
{
WebRequest request = WebRequest.Create(url);
WebResponse response = request.GetResponse();
string originalFileName = response.ResponseUri.AbsolutePath.Substring(response.ResponseUri.AbsolutePath.LastIndexOf("/") + 1);
Stream streamWithFileBody = response.GetResponseStream();
using (Stream output = File.OpenWrite(#"C:\MyPath\" + originalFileName))
{
streamWithFileBody.CopyTo(output);
}
Console.WriteLine("Downloded : " + originalFileName);
}
catch (Exception ex)
{
Console.WriteLine("Unable to Download : " + ex.ToString());
}
After trying all the examples that I found online without luck, I finally figured out a way to do this. I am posting my answer here in case someone else runs into the same problem.
I used selenium FireFoxDriver to navigate to the page that contains the link, then I find the link and click it. I created a profile in firefox to download the file type pdf directly instead of opening it.
FirefoxDriver driver = new FirefoxDriver(myProfile);
driver.Navigate().GoToUrl(pageUrl);
driver.FindElement(By.LinkText(linkText)).Click();
You can also find the link by href or id too, but in my case I needed to find it by text.

Web client upload will happen, Where?

I've written a simple code. I don't understand, what happens here. Please explain to me, where will I find a given upload file
WebClient client = new WebClient();
string uri = "http://localhost:8080/sample.txt";
client.Credentials = CredentialCache.DefaultCredentials;
string Filename = "F:\sample_test.txt/docx;
byte[] arrReturn = client.UploadFile(uri, "POST", Filename);
Well, to start with this clearly isn't your real code, as this line won't compile:
string Filename = "F:\sample_test.txt/docx/";
\s isn't a valid escape sequence However, assuming you had working code, what will happen is that your application would make an HTTP POST request with the contents of the file, to the given URI - in this case http://localhost:8080/sample.txt. It's entirely up to the server what it does with the request.
It could save the file on disk somewhere
It could save it to a database
It could post it to another web service
It could completely ignore the contents, and not save it anywhere
Nothing is guaranteed by the act of uploading the file - you're just making a request with some data.
Now if your URI really involves localhost, then it's uploading the file to the computer you're on - so you should be in control of what the web server listening on port 8080 is going to do with upload requests. Again, we can't tell you what it will do - it's up to the server.
It might be your filename:
string Filename = "F:\sample_test.txt/docx/";
Change the forward slashes to blackslashes, and give an actual filename as well, not just the path:
string Filename = #"F:\sample_test.txt\docx\";
Or
string Filename = "F:\\sample_test.txt\\docx\\";
Actually, the filename as is doesn't make much sense - I'm not sure how UploadFile would process it, even with the slashes going the correct way, as you appear to have a filename followed by a directory...? Shouldn't it actually be:
string Filename = #"F:\docx\sample_test.txt"?
It could be the URI - you're specifying the filename as well as the URI.
Did you look at the location specified in the URI? http://localhost:8080/?
If it's not there, then try wrapping your code in a try-catch block to see if any exceptions are thrown:
try
{
byte[] arrReturn = client.UploadFile(uri, "POST", Filename);
}
catch (Exception ex)
{
// do something here - in the debugger, you can inspect ex.Message to see the exception
}

Categories

Resources