Download files and create the same folder structure as the Host - c#

I have a config file which consists of list of URIs I want to download. For example,
http://xyz.abc.com/Dir1/Dir3/sds.txt
http://xyz.abc.com/Dir2/Dir4/jhjs.txt
http://xyz.abc.com/Dir1/itr.txt
I want to read the config file and and copy each URL but at the same time create the same directory structure as on the host. For example, for the first line in the config file, I want to create the directory structure Dir1/Dir3 on my local machine (if it doesn't exist) and then copy sds.exe to .../Dir1/Dir3/
How do I do this in C#?
What I have till now is:
string myStringWebResource; //Read this from the config file
System.IO.StreamReader file =
new System.IO.StreamReader("config.txt");
// Read the config file line by line
while ((myStringWebResource = file.ReadLine()) != null)
{
// Create a new WebClient instance.
using (WebClient myWebClient = new WebClient())
{
//How do I keep the original filename, e.g. sds.txt
string outputFilename = #"" + ???";
Console.WriteLine("Downloading ...");
// Download the Web resource and save it into
// the current filesystem folder.
try
{
myWebClient.DownloadFile(myStringWebResource, outputFilename);
Console.WriteLine("Successful");
}
catch (WebException e)
{
Console.WriteLine("Fail" + e.Message);
}
}
}
While this lets me download all the files in the config file,
I have this problem of having to name them after download, how can I retain their original name?
All the files get downloaded in the same folder. How could I replicate the folder structure from the Host?

My suggestion would we to filter the host out. Then split each remaining string on the /. Then build a method that takes a string[] as argument to create the directory structure. Move the file with filename (last item in the array) in that directory, using the original path (without host).
If the host is variable, remove everything before the third /.

Related

C# WebClient download file to absolute path

I'm working with ASP.NET Core and try to download a file to an absolute path.
But the problem I have is that the file always gets downloaded to the project directory and the filename itself gets the name of the whole path.
My Code:
string path = #"C:\Users\User\file.txt";
string url = "https://example.com/file.txt";
using (var client = new WebClient())
{
client.DownloadFile(url, path);
}
With this code the file gets then saved in the project folder with the file name C:\Users\User\file.txt, instead of being saved in the directory C:\Users\User with the file name file.txt.
The backslashes and the colon get replaced with some special characters, because they are not allowed in the filename.
Update
This worked for me:
using (WebClient client = new WebClient()) {
client.DownloadFile("https://localhost:5001/", #"D:\file.html");
}
According to this and other answers, your absolute path should work. Are you certain your path is formatted correctly and the destination folder exists?
Original Answer
Use this if all else fails, since saving to a valid folder should work.
WebClient.DownloadFile will download to the location of the current application (specified by Application.Startup) for a relative path. From the docs:
Parameters
address Uri
The URI specified as a String, from which to download data.
fileName String
The name of the local file that is to receive the data.
If you are going to use WebClient, you will need to move the file after you have downloaded it, e.g.
// Download to a local file.
using (var client = new WebClient())
{
client.DownloadFile(url, fileName);
}
// Get the full path of the download and the destination folder.
string fromPath = Path.Combine(Application.StartupPath, fileName);
string toPath = Path.Combine(destinationFolder, fileName);
// Move the file.
File.Move(fromPath, toPath);

Windows Forms app on shared location, save file locally

My problem is that I have a windows forms application which is located on a shared location, which is doing some logic and at the end i need to export the data into an excel file.
But the excel file should be exported to the machine that the users is logged in, not on the shared server where the application is hosted ...
Any Ideas?
Example of the situation:
The location of the application is at 192.168.1.150\AppName\App.exe
I have access to this shared location and I'm starting the exe file from there.
I need the application to export an excel file to my computer on my desktop .... how?
If you think the folder "My Documents" is a good place to save the Excel file, then this code will help to get you the path:
var folderPath = Environment.GetFolderPath(Environment.SpecialFolder.MyDocuments)
or if you want to put the file on the Desktop:
var folderPath = Environment.GetFolderPath(Environment.SpecialFolder.DesktopDirectory)
The code works regardless of where the folder "My Documents" (or "Desktop") is located for the user (C:, D:, Network share, etc), or which language version his windows installation is using.
To combine with a time based file name:
var fileName = $"your_file_{DateTime.Now:yyMMddHHmmss}.xlsx";
var fullPath = Path.Combine(folderPath, fileName);
I often use time based file names to not overwrite if there is a previous file. (It would of course overwrite if created the same second)
If you want a file name that is guaranteed to be unique you can use a Guid instead of DateTime:
var fileName = $"your_file_{Guid.NewGuid():N}.xlsx";
If the file is just used "within the program" you can also store it in the temporary files folder. To get the path to the temporary files folder you write var folderPath = Path.GetTempPath()
Hope this helps!
Why don't you just use Save File Dialog and save the excel file where you want? Something like this:
private void SaveFile_FileOk(object sender, CancelEventArgs e)
{
string name = SaveFile.FileName;
string[] savearray = new string[] { "some test:" }
File.WriteAllLines(name, savearray);
//this is just an example, your excel file goes here.
}
And on your button to save:
SaveFile.ShowDialog();
You can choose the path for where you want to save...

How to download files from OneDrive

I am looking to download my files in public folder from One Drive, but it doesn't download the files.
Here is the scenario:
In public folder I have another folder with multiple files in it and is accessible widely.
for test purpose I have shared all the files in public folder (I don't if it's proper way of sharing it).
The following links are provided for me to download the file:
From shared folder link https://onedrive.live.com/redir?resid=DBBC281099F4FE69!646&authkey=!AGRCGuw8Y2_p9mA&ithint=folder%2c.mp3
From public folder link https://onedrive.live.com/redir?resid=DBBC281099F4FE69%21646
Direct link http://1drv.ms/1z9XlW6 -
I am using BackgroundTransferRequest to download the file using below code:
string filePathToDownload = string.Empty, fileName = "111.mp3";
filePathToDownload = "http://1drv.ms/1z9XlW6";
Uri transferUri = new Uri(Uri.EscapeUriString(filePathToDownload), UriKind.RelativeOrAbsolute);
BackgroundTransferRequest transferRequest = new BackgroundTransferRequest(transferUri);
transferRequest.Method = "GET";
transferRequest.TransferPreferences = TransferPreferences.AllowCellularAndBattery;
Uri downloadUri = new Uri(DataSource.TEMPDOWNLOADLOCATION + fileName, UriKind.RelativeOrAbsolute);
transferRequest.DownloadLocation = downloadUri;
transferRequest.Tag = fileName;
The file is 300Kb, but this only downloads 6 Kb.
How can I directly download the file from the links above (any of them)?
thanks!
If you replace the word redir with download in the url you get the raw file instead of the webpage i.e.
https://onedrive.live.com/download?resid=DBBC281099F4FE69%21646
Basically, you can't. Those links are links to the web content that shows the files you have shared. If your scenario doesn't mind asking the user to log in to OneDrive, then you can use the Live SDK to access these files.
To access your public folder from Live SDK, you need to either use Live SDK to get the folder-id for your public folder, or convert the IDs in the URL you copied into the format the Live SDK uses:
folder.<user-id>.<folder-resid>
Where is the part of before the !. In general you shouldn't construct an ID, since it's possible the IDs will change in the future, and instead you should retrieve the ID from the service. However, with the URL you pasted the ID would be:
folder.DBBC281099F4FE69.DBBC281099F4FE69!646
Which will allow you to call
https://apis.live.net:443/v5.0/folder.DBBC281099F4FE69.DBBC281099F4FE69!646/files?access_token=<valid_token>
and retrieve the IDs for the individual files, which you can then download via Live SDK following these details: http://msdn.microsoft.com/en-US/library/dn659726.aspx#download_a_file
For those who are still looking for a response to that question.
The easiest way to find the file path is to go to One Drive on the web and right-click on the file that we want and select Embed. Τhen on the right we see the info window to integrate our file into a page. Inside the iframe is the source of the file. Then we have to replace the word embed with the word download and that's it.
Try something like this
//we first need the file id
string id = string.Empty;
//we need to get all of the filenames stored in the root of the skydrive account
LiveOperationResult result = await this.client.GetAsync("me/skydrive/files");
//lets make a list of all these filenames
List<object> items = result.Result["data"] as List<object>;
//for every filename, check if it is what we want, in this case "sample.txt"
//if it is what we want, get the id and save it to out already defined id value
foreach (object item in items)
{
IDictionary<string, object> file = item as IDictionary<string, object>;
if (file["name"].ToString() == "sample.txt")
{
id = file["id"].ToString();
}
}
//to download the file we need to use the id + "/content"
LiveDownloadOperationResult result2 = await client.DownloadAsync(string.Format("{0}/content", id));
//once the file had downloaded, lets copy it to IsolatedStorage
Stream stream = result2.Stream;
using (IsolatedStorageFile storage = IsolatedStorageFile.GetUserStoreForApplication())
{
using (IsolatedStorageFileStream fileToSave = storage.OpenFile("sample.txt", FileMode.Create, FileAccess.ReadWrite))
{
stream.CopyTo(fileToSave);
stream.Flush();
stream.Close();
}
}
here client is the object of LiveConnectClient class.
Import
using Microsoft.Live;
using Microsoft.Live.Controls;
Here is use txt file as an example. Go through this example:http://www.baileystein.com/2013/10/20/skydrive-how-to-upload-and-download-a-text-file-on-wp8/

Cannot create a file when it already exists using File.Move

I was trying to move a file from my Resx to my PC, but I'm keep having problems.
So I import a folder named "bad" in the Resources and I use the File.Move method to move the folder "bad" into my PC.
But the program keeps crashing because it says: Cannot create a file when its already exists.
Here the code I use:
//txtpath is the root folder. I let the user choose the root folder and save it in txtpath.text
private void btnbadname_Click(object sender, EventArgs e)
{
string source = "Resources\bad";
string destination = txtpath.Text + #"\RADS\projects\lol_air_client\releases\0.0.1.74\deploy\assets\locale\App";
File.Move(source, destination);
MessageBox.Show("脏话ID已开启, 教程请点击下面的链接");
}
The destination Directory cannot exist. In your code you are creating the Directory if it doesn't exist and then trying to move your directory, the Move Method will create the directory for you. If the Directory already exists you will need to Delete it or Move it.
See:
Cannot create a file when that file already exists when using Directory.Move
Destination supposed to have the filename as well
string destination = txtpath.Text + #"\RADS\projects\lol_air_client\releases\0.0.1.74\deploy\assets\locale\App\yourfilename.ext";
You are using File.Move to move directory, why not using Directory.Move.
The MSDN documentation will only move files from a source to a destination, while Directory.Move will move the directory itself.
If I misunderstood you, and you want to move a file;
You can check if the file exists before or not using something like:
if(File.Exists(fileName))
File.Delete(fileName);
Edit:
If you want to iterate through the directory and make sure that the file doesn't exist before moving it, you can use something like:
//Set the location of your directories
string sourceDirectory = #"";
string destDirectory = #"";
//Check if the directory exists, and if not create it
if (!Directory.Exists(destDirectory))
Directory.CreateDirectory(destDirectory);
DirectoryInfo sourceDirInfo = new DirectoryInfo(sourceDirectory);
//Iterate through directory and check the existance of each file
foreach (FileInfo sourceFileInfo in sourceDirInfo.GetFiles())
{
string fileName = sourceFileInfo.Name;
string destFile = Path.Combine(destDirectory, fileName);
if (File.Exists(destFile))
File.Delete(destFile);
//Finally move the file
File.Move(sourceFileInfo.FullName, destFile);
}
When using MoveTo, provide the full path of where you are sending the file, including the file name, eg, pic123.jpg. If you use DirectoryInfo to get an array of files and want to move any of them, append the Name property of the file to the directory path where you are sending the file.
imgFile.MoveTo("C:\myPictures\ArchiveFolder\pic123.jpg")

Visual Studio 2010 working directory

I'm developing a C# asp.net web application. I'm basically done with it, but I have this little problem. I want to save xml files to the "Users" folder within my project, but if I don't psychically hard code the path "C:......\Users" in my project it wants to save the file in this "C:\Program Files (x86)\Common Files\microsoft shared\DevServer\10.0\Users" folder, this is an annoying problem because I can't use the hard coded directory on our web hosts server. Also, I have a checkbox list that populates from the the "DownloadLibrary" folder in my project, and its suppose to download the files from that fold but its also looking to the "C:\Program Files (x86)\Common Files\microsoft shared\DevServer\10.0\" folder for download even though its populating from the correct folder. I'm very confused by this, its the first time something like this has ever happened to me. Can anyone please help me with this, its the only thing standing in my way to complete this project.
You don't want to use the working directory at all; you want to use a directory relative to where the web application is located (which can be retrieved from HttpRequest.ApplicationPath.
HttpRequest request = HttpContext.Current.Request;
// get the physical path to the web application
string pathToApp = request.MapPath(request.ApplicationPath);
string usersPath = System.IO.Path.Combine(pathToApp, "Users");
Update
As VincayC points out; asp.net development is not my strongest skill ;) The above code is essentially equivalent of this (much simpler) code:
string usersPath = HttpRequest.Current.Request.MapPath("~/Users");
If this code appears in the code-behind of a page, you can probably cut HttpContext.Current as well, since the page has a Request property.
That did fix the one problem I'm having, but the downloads are still not downloading from the right place, the program still wants to get the files from "C:\Program Files (x86)\Common Files\microsoft shared\DevServer\10.0\" directory here is the code I'm using
--Code to populate the checkbox--
HttpRequest request = HttpContext.Current.Request;
// get the physical path to the web application
string appPath = request.MapPath(request.ApplicationPath);
string directory = System.IO.Path.Combine(appPath, "DownloadLibrary/");
// Get the list of files into the CheckBoxList
var dirInfo = new DirectoryInfo(directory);
cblFiles.DataSource = dirInfo.GetFiles();
cblFiles.DataBind();
--Download Button Code--
// Tell the browser we're sending a ZIP file!
var downloadFileName = string.Format("Items-{0}.zip", DateTime.Now.ToString("yyyy-MM-dd-HH_mm_ss"));
Response.ContentType = "application/zip";
Response.AddHeader("Content-Disposition", "filename=" + downloadFileName);
// Zip the contents of the selected files
using (var zip = new ZipFile())
{
// Add the password protection, if specified
/*if (!string.IsNullOrEmpty(txtZIPPassword.Text))
{
zip.Password = txtZIPPassword.Text;
// 'This encryption is weak! Please see http://cheeso.members.winisp.net/DotNetZipHelp/html/24077057-63cb-ac7e-6be5-697fe9ce37d6.htm for more details
zip.Encryption = EncryptionAlgorithm.WinZipAes128;
}*/
// Construct the contents of the README.txt file that will be included in this ZIP
var readMeMessage = string.Format("Your ZIP file {0} contains the following files:{1}{1}", downloadFileName, Environment.NewLine);
// Add the checked files to the ZIP
foreach (ListItem li in cblFiles.Items)
if (li.Selected)
{
// Record the file that was included in readMeMessage
readMeMessage += string.Concat("\t* ", li.Text, Environment.NewLine);
// Now add the file to the ZIP (use a value of "" as the second parameter to put the files in the "root" folder)
zip.AddFile(li.Value, "Your Files");
}
// Add the README.txt file to the ZIP
//zip.AddEntry("README.txt", readMeMessage, Encoding.ASCII);
// Send the contents of the ZIP back to the output stream
zip.Save(Response.OutputStream);</pre></code>
I'm not sure how to get the downloads to point to my application directory,I tried everything I can think off.

Categories

Resources