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.
Related
I am making an ASP.NET Core 3.1 MVC with Entity Framework website on a Microsoft server running IIS 10 with basic user file upload and download functions. I can upload files to the _webHostEnvironment.WebRootPath from the web but when I try to download them it cannot find them. However, if I recycle the app pool I can download the file (I can also download it from the web after accessing the website on localhost on the server).
Here is the code for when I upload the file:
string uniqueFileName = null;
if (model.Data != null)
{
string uploadsFolder = Path.Combine(_webHostEnvironment.WebRootPath, "images");
uniqueFileName = Guid.NewGuid().ToString() + "_" + model.Data.FileName;
string filePath = Path.Combine(uploadsFolder, uniqueFileName);
model.Data.CopyTo(new FileStream(filePath, FileMode.Create));
}
Here is the code for when I download it:
public FileResult DownloadData(string fileName, string tempAddCode, string patientName)
{
byte[] fileBytes = System.IO.File.ReadAllBytes(Path.Combine(_webHostEnvironment.WebRootPath, "images") + "\\" + fileName);
var dataStream = new MemoryStream(fileBytes);
return new FileStreamResult(dataStream, new MediaTypeHeaderValue("application/pdf"))
{
FileDownloadName = patientName.ToLower().Replace(" ", "_") + ".pdf"
};
}
What is going on? Why would recycling the app pool fix this? Am I saving these user-uploaded files to the wrong location and ASP.NET is doing some sort of caching thing? I'd love any help finding a solution! Thanks.
With this line you open file stream and never close it.
model.Data.CopyTo(new FileStream(filePath, FileMode.Create));
Make sure you always dispose your streams, so files don't stay locked. Use code below to properly copy stream to file
using (var fs = new FileStream(filePath, FileMode.Create))
{
model.Data.CopyTo(fs);
}
What happens if you put a breakpoint in the DownloadData function, and step through? Does it successfully read the file into fileBytes, or do you get an exception - what exception do you get? Also check IIS logs to get the error code and post it, please.
Also, make sure the user that you're running under, has Write access to the folder. By Default, it will not.
To add, right-click on the folder, security, and add (from computer)
IIS AppPool\ [whatever the appPool name is].
IIS AppPool\MyAppPool
I would like to download a file from a FTP and directly POST to a REST URL without having to save in a temp folder, which I am currently doing. Works great, but not what I want to do. When I take a file directly from the FTP, the File.OpenRead takes not only the FTP path
ftp://xxxx.xxxxxx.xxx/
but it adds the project path
C://myProject/ProjectName
in front of it, thus causing a
The filename, directory name, or volume label syntax is incorrect.
Where am I going wrong?
using(var client = new WebClient())
{
client.Headers.Add("Content-Type", "application/octet-stream");
using(var filestream = File.OpenRead(FTP_Path + FTP_filename))
using(var requestStream = client.OpenWrite(new Uri(fileUploadUrl), "POST"))
{
filestream.CopyTo(requestStream);
}
}
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.
I am trying to create an SSIS package that gets a folder tree structure from a remote SQL DB and recreates that structure in a document library in Sharepoint.
I tried to (hard) code a Script Task to create just one folder but I'm getting this error:
http://img856.imageshack.us/img856/1386/helpel.png
After running only a part of this script:
Microsoft.Sharepoint.Client.dll
Microsoft.Sharepoint.Client.Runtime.dll
public void Main()
{
ClientContext clientContext = new ClientContext("http://spdemo.example.com/");
clientContext.Credentials = new System.Net.NetworkCredential("admin", "password", "SPDEMO");
Web rootWeb = clientContext.Web;
Dts.TaskResult = (int)ScriptResults.Success;
}
I've scoured the internet for solutions, but haven't found something that works for me.
So basically i need to find out how to:
create a folder
populate it with sub-folders
Copy files in bitestreams from SQL to Sharepoint, all in SSIS
Thanks in advance!
Regards,
Vlad Ardelean
After some research I found out that in order to reference a DLL in a SSIS Script Task it first has to be strong named
Instead, I have found an easier way to create folders and upload files:
public void CreateFolder(string url)
{
HttpWebRequest request = (System.Net.HttpWebRequest)HttpWebRequest.Create(url);
request.Credentials = new NetworkCredential(user, pass);
request.Method = "MKCOL";
HttpWebResponse response = (System.Net.HttpWebResponse)request.GetResponse();
response.Close();
}
public void UploadDocument(byte[] file, string destinationName)
{
byte[] buffer = file;
WebRequest request = WebRequest.Create(destinationName);
request.Credentials = new System.Net.NetworkCredential(user, pass);
request.Method = "PUT";
request.ContentLength = buffer.Length;
BinaryWriter writer = new BinaryWriter(request.GetRequestStream());
writer.Write(buffer, 0, buffer.Length);
writer.Close();
HttpWebResponse response = (HttpWebResponse)request.GetResponse();
response.Close();
}
url : represents the url path of the folder you want to create
http://spsite.host.com/DocLib/FolderToCreate
destinationName: path + document name
http://spsite.host.com/DocLib/FolderToCreate/DocToCreate.docx
Did you try running your code from a stand-alone windows application written in C# in Visual Studio?
If I get errors in SSIS, my preference is to test that code thoroughly in Visual Studio and then port it to a script task in SSIS.
If you haven't done folder creation and file copy to SharePoint, the below links might help.
Create a folder - http://thingsthatshouldbeeasy.blogspot.in/2009/09/how-to-add-folder-to-sharepoint-list.html
You can do the create folder step recursively untill you have created the destination tree structure.
Copy Files - http://msdn.microsoft.com/en-us/library/ms454491.aspx, http://msdn.microsoft.com/en-us/library/ms470176.aspx
I dont understand what you mean by copy file in bitestreams from SQL. If you want to read binary data from SQLServer via ADO.Net use System.Data.SqlDbType.VarBinary
Read the data from SQL server to a stream and write to a temp file, copy that temp file from local to SP. Or you may even write the data in a stream to SP directly without a temp file.
I am trying this code to download a file from a Windows machine using C# against a Solaris machine and I receive error 550 - File unavailable.
string fileName = FileName();
string remoteUri = "xxxx";
var webClient = new WebClient();
webClient.Proxy = null;
webClient.Credentials = new NetworkCredential(Settings.Default.FtpUser, Settings.Default.FtpPassword);
webClient.BaseAddress = "ftp://"+Settings.Default.FtpHost;
webClient.DownloadFile(remoteUri, fileName);
I have validated that the URI works when using it in the address line of an Internet Explorer.
The URI looks like this
ftp://10.99.137.99/opt/scripts/overnight/test.txt
The actual location after the login on the Unix side is
/opt/scripts/overnight/test.txt
on the Unix side.
I am able to view the file after entering my user and password. What am I doing wrong? What other steps can I take? Is there an easy way to use more manual ftp?
Here's another interesting article with a different answer:
FtpWebRequest Download File
string remoteUri = "xxxx";
Have you posted the actual code? This is the name of the remote file. It needs to be ftp://10.99.137.99/opt/scripts/overnight/test.txt not xxxx
If it isn't the actual code, can you post the code you are really using?