Dowload a pdf from a link with c# - 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.

Related

Selenium File upload from URL instead of local file

Trying to upload a file with a HTML input element via Selenium/ChromeDriver.
If the file is a local file everything is OK.
But I need to upload from a URL. In that case the driver throws an error.
If I upload the URL with chrome manually (click on "Select file" and paste the URL as filename and click OK) the upload works as expected.
HTML:
<input type="file" name="file1">
C# code:
var driver = new ChromeDriver();
driver.Navigate().GoToUrl("<URL HERE>");
var input = driver.FindElement(By.Name(name));
ele.SendKeys("C:\\pic.png"); //works because local file exists
ele.SendKeys("https://wikipedia.org/static/favicon/wikipedia.ico"); //fails
Exception:
OpenQA.Selenium.WebDriverException: "invalid argument: File not found : https://wikipedia.org/static/favicon/wikipedia.ico
(Session info: chrome=92.0.4515.131)"
I found out that the exception is thrown because the drivers DefaultFileDetector cant resolve it to a file.
So I tried to implement my own FileDetector and assign it to the driver:
var allowsDetection = driver as IAllowsFileDetection;
if (allowsDetection != null)
{
allowsDetection.FileDetector = new DummyFileDetector();
}
DummyFileDetector:
class DummyFileDetector : IFileDetector
{
public bool IsFile(string keySequence)
{
return true;
}
}
But DummyFileDetector.IsFile is never called (it seems that allowsDetection.FileDetector = new DummyFileDetector() does not change the FileDetector of the driver).
I don't want to download the file and then upload it (if that is possible). As said manually set the URL in the file selection dialog does the trick, but not with Selenium.
Any ideas?
I searched many questions here and on other internet resources, and found that the only way to upload a file from external URL with driver.SendKeys() method is first to download it to your local disk and then upload with driver.SendKeys()
Proof
I've never used C# before, but I think a really simple way to go around this is downloading the file, reuploading it, then deleting it. I'm sure you can do it in C#. I understand in selenium python it is pretty simple to do that, I don't think python code would be helpful here though (lol)

Download text file from website using WebCLient

We recently switched our ftp site at work from ftp://address to https://ftp.address and now my application that retrieves files is unable to download files with expected content.
I previously used FtpWebRequest and it has been working for many years.
I am now trying to use WebClient and it downloads a file but it is not the text file I need. Instead, the contents of the file turns out to be some HTML.
Previous that worked:
FtpWebRequest request = (FtpWebRequest)WebRequest.Create(getAppSetting("URI") + getAppSetting("FilePath") + args[0].ToString());
request.Method = WebRequestMethods.Ftp.DownloadFile;
setCredentials(request);
FtpWebResponse response = (FtpWebResponse)request.GetResponse();
Changed code to handle https:
System.Net.ServicePointManager.SecurityProtocol = SecurityProtocolType.Tls | SecurityProtocolType.Tls11 | SecurityProtocolType.Tls12;
WebClient request = new WebClient();
setCredentials(request);
string file = request.DownloadString(getAppSetting("URI") + getAppSetting("FilePath") + args[0].ToString());
The result is a file that is downloaded but it contains HTML. I expect to have the contents of the file on the website I am pulling from.
After a couple of weeks of research, I finally found out what I needed to do and the answer was quite simple. I found out that our new website uses SSH so I installed SSH.Net via my nugent package to Visual Studio, and added "using Renci.SshNet;". I used the following code to download the file to my local drive:
using (SftpClient sftp = new SftpClient("ftp.website.com", 22,"username", "password")
{
sftp.Connect();
if (sftp.IsConnected)
{
using (Filestream fs = new FileStream("Output.txt", FileMode.Create))
{
sftp.DownloadFile("/file/Client/Input.txt", fs);
}
}
sftp.Disconnect();
}
This works perfectly. My file no longer downloads as an HTML file and I get my desired output. I hope this saves someone else a lot of time.

Download file from URL with parameters and authentication required

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?

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.

Open a .txt file on Android

I am currently working in Unity3D and wish to simply open a .txt file upon clicking on a button.
EDIT : When I say open a .txt file, I mean open it in some editor on the device, not open it asnd save it's content to some string in my app. Kind of like opening a browser to access a website from the app.
Here's the code I currently have (C#) :
private void ShowTextFile(string fileName)
{
Application.OpenURL(Application.streamingAssetsPath + "/PATH/" + fileName);
}
But it's not working ! What am I missing ?
EDIT : I'm expecting for the .txt file to open in another window (like opening a web browser, for example), but it simply isn't doing anything. Not even getting an error.
EDIT2 : I tried using Application.persistentDataPath instead, and in both cases, it says my .txt file doesn't exist. However, when using Application.persistentDataPath, it opens up a message box asking me what I want to open the file with. Whatever I choose, it will give me an error, telling me error loading file or something like that. I've also noticed that it opens "file:///". Is it normal that there is a file:/// before the path ?
EDIT3 (I'm on fire !) : I think the problem might be related to the fact that there is a "." in my path (the com.me.myapp in the data path). Is there any way to avoid this ? Am I even looking at the right path ?
I've tried opening a txt file on Android before, using this:
TextAsset txt = (TextAsset)Resources.Load("file", typeof(TextAsset));
string content = txt.text;
Where file is the name of the txt file (don't need to write file.txt).
The variable string will contain the contents of the text file, you just need to loop through them afterwards.
This method requires:
using System.Text;
using System.IO;
Put file.txt inside a directory named "Resources" (inside Assets dir), if it isn't there then create a new one.
This is my code for Android:
var rpath = Path.Combine(Application.streamingAssetsPath, "file_name");
WWW www = new WWW(rpath);
yield return www;
StringReader streamReader = new StringReader(www.text);
text = streamReader.ReadToEnd();
For iOS:
var rpath = Path.Combine(Application.streamingAssetsPath, "file_name");
StreamReader streamReader = new StreamReader(rpath);
text = streamReader.ReadToEnd();
Note: file_name in StreamingAssets folder
Found a solution that works ! Here's the thing, the streaming assets path, on Android, returns a path that can only be read by a WWW object. So I simply read it with a WWW object then recreated the file in my persistent data path. Added a check to make sure the file doesn't already exist before creating it. Also, make sure you create the directory in case it doesn't exist, else you'll get an error. Note that this solution is probably not optimal if you have large files that are regularly accessed.
string realPath = Application.persistentDataPath + "/PATH/" + fileName;
if (!System.IO.File.Exists(realPath))
{
if (!System.IO.Directory.Exists(Application.persistentDataPath + "/PATH/"))
{
System.IO.Directory.CreateDirectory(Application.persistentDataPath + "/PATH/");
}
WWW reader = new WWW(Application.streamingAssetsPath + "/PATH/" + realPath);
while ( ! reader.isDone) {}
System.IO.File.WriteAllBytes(realPath, reader.bytes);
}
Application.OpenURL(realPath);
If anyone has anything to add to this answer, feel free !

Categories

Resources