Creation of torrent using monotorrent c# - c#

I am trying to create a torrent for the files in my desktop using monotorrent i have tried like the below code
i am able to get the byte code i am not able to save it as torrent it shows access denied
enter code here string path = "C:/Users/snovaspace12/Desktop/monotorrent-0.90/files";
string savepath = "D:/results";
TorrentCreator nnnn = new TorrentCreator();
nnnn.CreateTorrent(path, savepath);
public void CreateTorrent(string path, string savePath)
{
// The class used for creating the torrent
TorrentCreator c = new TorrentCreator();
// Add one tier which contains two trackers
//RawTrackerTier tier = new RawTrackerTier();
//tier.Add("http://localhost/announce");
//c.Announces.Add(tier);
c.Comment = "This is the comment";
c.CreatedBy = "Doug using " + VersionInfo.ClientVersion;
c.Publisher = "www.aaronsen.com";
// Set the torrent as private so it will not use DHT or peer exchange
// Generally you will not want to set this.
c.Private = true;
// Every time a piece has been hashed, this event will fire. It is an
// asynchronous event, so you have to handle threading yourself.
c.Hashed += delegate(object o, TorrentCreatorEventArgs e)
{
Console.WriteLine("Current File is {0}% hashed", e.FileCompletion);
Console.WriteLine("Overall {0}% hashed", e.OverallCompletion);
Console.WriteLine("Total data to hash: {0}", e.OverallSize);
};
// ITorrentFileSource can be implemented to provide the TorrentCreator
// with a list of files which will be added to the torrent metadata.
// The default implementation takes a path to a single file or a path
// to a directory. If the path is a directory, all files will be
// recursively added
ITorrentFileSource fileSource = new TorrentFileSource(path);
// Create the torrent file and save it directly to the specified path
// Different overloads of 'Create' can be used to save the data to a Stream
// or just return it as a BEncodedDictionary (its native format) so it can be
// processed in memory
c.Create(fileSource, savePath);
}
public void Create(ITorrentFileSource fileSource, string savePath)
{
Check.SavePath(savePath);
var file = Create(fileSource);//getting the fbyte code
File.WriteAllBytes( savePath, Create(fileSource).Encode()); //getting exception here
}
when i checked the byte code is returning properly to the file
it shows access is denied

You’ve probably solved this already but I just encountered the same issue. The solution, at least in my case, was pretty simple.
The problem originated with the savePath parameter in c.Create(fileSource, savePath);
I assumed savePath was a directory where the torrent would be saved. It should be a file path instead. For example savePath = “C:\pathtomytorrents\content.torrent”
Hopefully that works for you!

Related

System.UnauthorizedAccessException, trying to use XML serialization

This is the function I use to save the data. The data is stored inside holder(SettingsHolder). The directory I need is recognised but it does not have permission.
//Save the data of a new user, called by NewUser();
public static void SaveNew(string filename)
{
UserLogins.SettingsHolder holder = new UserLogins.SettingsHolder();
FileStream stream = new FileStream(filename, FileMode.Create);
var XML = new XmlSerializer(typeof(UserLogins.SettingsHolder));
XML.Serialize(stream, holder);
}
This is where I call SaveNew:
public static void NewUser()
{
UserSlot = FindLastEmptyUser();
// Set user default settings.
Console.WriteLine(users[UserSlot]);
Console.WriteLine("What will the new user's name be?");
UserLogins.SettingsHolder.name = Console.ReadLine();
users[UserSlot] = UserLogins.SettingsHolder.name;
UserLogins.SettingsHolder.status = 0;
Console.WriteLine("Ok, I made a new user called " + users[UserSlot]);
Console.WriteLine("");
// Write defaults to XML file
SaveNew(Environment.CurrentDirectory + users[UserSlot]);
UserDataLoader.PromptUsers();
}
I have tried the instructions of other people who have asked this question but they didn't work.
The exact error message is System.UnauthorizedAccessException: 'Access to the path 'C:\Users\(my user)\OneDrive\Desktop\Projects\dotnet\dotnet1\bin
Can anyone help me here?
Fixed it, the file was in the Users(my user) directory so it did not have access, only the user and admins have access to that. I moved it to C:\ and it fixed itself.
I had the problem again on a different project so just in case that didn't work for other people, I had set filename to a directory, make sure it includes the name of the file as well as the directory

How to delete the last character of a file with C#

Hello I'm beginner with C# and I want to delete the last character of my file to inject JSON objects to this file manually (I know that's not the best way to do that), so I can get the right format I tried with multiple ways like open the file, manipulating the string (deleting the last character) and when I try to replace the text in that same file I have errors like IOException: The process cannot access the file 'file path' because it is being used by another process or System.UnauthorizedAccessException : 'Access to the path 'C:\Users\ASUS\Desktop\Root' is denied.
I'll show you the code :
StoreLogs Log = new StoreLogs()
{
Id = ID,
DateTime = dateT,
TaskName = task,
SrcAddress = srcPath,
DstAddress = path,
FileSize = DirSize(new DirectoryInfo(srcPath)),
DelayTransfer = ts.Milliseconds,
};
// Record JSON data in the variable
string strResultJson = JsonConvert.SerializeObject(Log);
// Show the JSON Data
// Console.WriteLine(strResultJson);
// Write JSON Data in another file
string MyJSON = null;
string strPath = #"C:\Users\ASUS\Desktop\Backup\logs\log.json";
if (File.Exists(strPath))
{
//FileInfo table = new FileInfo(strPath);
//string strTable = table.OpenText().ReadToEnd();
//string erase = strTable.Remove(strTable.LastIndexOf(']'));
//Console.WriteLine(erase);
//StreamReader r1 = new StreamReader(strPath);
//string strTable = r1.OpenText().ReadToEnd();
//string erase = strTable.Remove(strTable.LastIndexOf(']'));
//r1.Close();
using (StreamReader sr = File.OpenText(strPath))
{
string table = sr.ReadToEnd();
string erase = table.Remove(table.LastIndexOf(']'));
sr.Close();
File.WriteAllText(strPath, erase);
}
//MyJSON = "," + strResultJson;
//File.AppendAllText(strPath, MyJSON + "]");
//Console.WriteLine("The file exists.");
}
else if (!File.Exists(strPath))
{
MyJSON = "[" + strResultJson + "]";
File.WriteAllText(strPath, MyJSON);
Console.WriteLine("The file doesn't exists.");
}
else
{
Console.WriteLine("Error");
}
// End
Console.WriteLine("JSON Object generated !");
Console.ReadLine();
And that's the result I want :
[{"Id":"8484","DateTime":"26 novembre 2019 02:33:35 ","TaskName":"dezuhduzhd","SrcAddress":"C:\\Users\\ASUS\\Desktop\\Root","DstAddress":"C:\\Users\\ASUS\\Desktop\\Backup","FileSize":7997832.0,"DelayTransfer":0.0},{"Id":"8484","DateTime":"26 novembre 2019 02:33:35 ","TaskName":"dezuhduzhd","SrcAddress":"C:\\Users\\ASUS\\Desktop\\Root","DstAddress":"C:\\Users\\ASUS\\Desktop\\Backup","FileSize":7997832.0,"DelayTransfer":0.0},{"Id":"8484","DateTime":"26 novembre 2019 02:33:35 ","TaskName":"dezuhduzhd","SrcAddress":"C:\\Users\\ASUS\\Desktop\\Root","DstAddress":"C:\\Users\\ASUS\\Desktop\\Backup","FileSize":7997832.0,"DelayTransfer":0.0}]
Edit :
Thank you all for your advices
Solution:
FileStream fs = new FileStream(strPath, FileMode.Open, FileAccess.ReadWrite);
fs.SetLength(fs.Length - 1);
fs.Close();
In the code example you have posted you are opening a stream to read the file. A using block will dispose the stream after you exit the block. You are trying to write to the file, while the read stream is still accessing it (the read stream still exists). You've basically opened the file, you read from it, and are trying to write back to it while still holding it open. The reason this is a problem is that you are not using the stream to write. So your second, write, process is unable to access the file. I see you are closing the stream prior to write, but I'm willing to bet it's still holding the reference open.
I would try this method:
How to both read and write a file in C#
what it says is the access to the path (C:\Users\ASUS\Desktop\Root) denied for the user who is running the application. for ex: If you are running from Visual studio on user1 windows login then user1 should have appropriate rights to that root folder. If the code is running by itself (exe) then check the access for that user who is invoking that exe.
Based on the errors you posted seems that:
Maybe you're leaving some stream open pointing to the file you want to edit, use the 'using' statement to avoid this (see this link for more info)
You're trying to access a file when you don't have needed permissions (you aren't a system admin or file is read-only), try changing file ubication or setting it to be writeable (see this link for mor info about the UnauthorizedAccessException exception)
Hope this helps you!

C# Drag and Drop attached file from outlook email

I want to use/read attached files from an outlook email into a WinForm solution.
Ex: the email has a TXT file attached; I want to perform a Drag&Drog of the TXT file into the WinForm and read the TXT at the same time.
This is an old question, but I'll provide another answer anyhow that doesn't involve using the Outlook objects.
This URL provides working code that is about 13 years old, but still seems to work, on how to handle the "FileGroupDescriptor" and "FileContents" data that Outlook passes to the DropDrop event. Just in case that link dies, here is the relevant code, copy/pasted directly:
DragEnter event:
private void Form1_DragEnter(object sender, System.Windows.Forms.DragEventArgs e)
{
// for this program, we allow a file to be dropped from Explorer
if (e.Data.GetDataPresent(DataFormats.FileDrop))
{ e.Effect = DragDropEffects.Copy;}
// or this tells us if it is an Outlook attachment drop
else if (e.Data.GetDataPresent("FileGroupDescriptor"))
{ e.Effect = DragDropEffects.Copy;}
// or none of the above
else
{ e.Effect = DragDropEffects.None;}
}
DragDrop event:
private void Form1_DragDrop(object sender, System.Windows.Forms.DragEventArgs e)
{
string [] fileNames = null;
try
{
if ( e.Data.GetDataPresent(DataFormats.FileDrop,false) == true)
{
fileNames = (string []) e.Data.GetData(DataFormats.FileDrop);
// handle each file passed as needed
foreach( string fileName in fileNames)
{
// do what you are going to do with each filename
}
}
else if (e.Data.GetDataPresent("FileGroupDescriptor"))
{
//
// the first step here is to get the filename
// of the attachment and
// build a full-path name so we can store it
// in the temporary folder
//
// set up to obtain the FileGroupDescriptor
// and extract the file name
Stream theStream = (Stream) e.Data.GetData("FileGroupDescriptor");
byte [] fileGroupDescriptor = new byte[512];
theStream.Read(fileGroupDescriptor,0,512);
// used to build the filename from the FileGroupDescriptor block
StringBuilder fileName = new StringBuilder("");
// this trick gets the filename of the passed attached file
for(int i=76; fileGroupDescriptor[i]!=0; i++)
{ fileName.Append(Convert.ToChar(fileGroupDescriptor[i]));}
theStream.Close();
string path = Path.GetTempPath();
// put the zip file into the temp directory
string theFile = path+fileName.ToString();
// create the full-path name
//
// Second step: we have the file name.
// Now we need to get the actual raw
// data for the attached file and copy it to disk so we work on it.
//
// get the actual raw file into memory
MemoryStream ms = (MemoryStream) e.Data.GetData(
"FileContents",true);
// allocate enough bytes to hold the raw data
byte [] fileBytes = new byte[ms.Length];
// set starting position at first byte and read in the raw data
ms.Position = 0;
ms.Read(fileBytes,0,(int)ms.Length);
// create a file and save the raw zip file to it
FileStream fs = new FileStream(theFile,FileMode.Create);
fs.Write(fileBytes,0,(int)fileBytes.Length);
fs.Close(); // close the file
FileInfo tempFile = new FileInfo(theFile);
// always good to make sure we actually created the file
if ( tempFile.Exists == true)
{
// for now, just delete what we created
tempFile.Delete();
}
else
{ Trace.WriteLine("File was not created!");}
}
}
catch (Exception ex)
{
Trace.WriteLine("Error in DragDrop function: " + ex.Message);
// don't use MessageBox here - Outlook or Explorer is waiting !
}
}
Note that this code doesn't Dispose of objects that it should, such as the MemoryStream and FileStream objects.
You can get the running Outlook instance by using the GetActiveObject method which allows to obtain a running instance of the specified object from the running object table (ROT). Then you can automate Outlook to get the currently selected or opened item from which an attachment might be dragged. See C# app automates Outlook (CSAutomateOutlook) for the sample code.

File.Replace throwing exception if FileToDelete resides in a different drive

I am not sure if this is the reason why its throwing error. But for me the test where I perform the File.Replace with files residing in different directories failed. Just want to know if this is the case with others too.
[TestMethod]
public void TestFileReplaceDifferentDirectory()
{
string FileToReplace = #"c:\tools\file2.txt";
string FileToDelete = #"D:\DropFolder\file0.txt";
string strToWrite;
using (var wtr = File.CreateText(FileToDelete))
{
long ticks = DateTime.Now.Ticks;
strToWrite = string.Join(",", ticks, ticks, ticks);
wtr.WriteLine(strToWrite);
wtr.Flush();
wtr.Close();
}
string BackupFileName = Path.Combine(
Path.GetDirectoryName(FileToReplace),
string.Format("{0}_{1}{2}",
Path.GetFileNameWithoutExtension(FileToReplace),
DateTime.Now.Ticks,
Path.GetExtension(FileToReplace))
);
File.Replace(FileToDelete, FileToReplace, BackupFileName, false);
using (StreamReader rdr = new StreamReader(FileToReplace))
{
string line = rdr.ReadLine();
Assert.AreEqual(strToWrite, line);
}
}
[TestMethod]
public void TestFileReplaceSameDirectory()
{
string FileToReplace = #"c:\tools\file2.txt";
string FileToDelete = #"c:\tools\file0.txt";
string strToWrite;
using (var wtr = File.CreateText(FileToDelete))
{
long ticks = DateTime.Now.Ticks;
strToWrite = string.Join(",", ticks, ticks, ticks);
wtr.WriteLine(strToWrite);
wtr.Flush();
wtr.Close();
}
string BackupFileName = Path.Combine(
Path.GetDirectoryName(FileToReplace),
string.Format("{0}_{1}{2}",
Path.GetFileNameWithoutExtension(FileToReplace),
DateTime.Now.Ticks,
Path.GetExtension(FileToReplace))
);
File.Replace(FileToDelete, FileToReplace, BackupFileName, false);
using (StreamReader rdr = new StreamReader(FileToReplace))
{
string line = rdr.ReadLine();
Assert.AreEqual(strToWrite, line);
}
}
I was trying to write to a temporary file (using Path.GetTempFileName()) and replace a file in D:\DropFolder. It wasn't happening; it threw an System.IO.Exception
So does this mean my only option is to create a kind of temporary file in the same directory as that of FileToReplace and carry out this task?
This is by design. The point of using File.Replace() is to be able to replace a file that's locked by another process. Very important if you have just one shot at saving precious data, common at machine shutdown or unexpected program termination. Needless to say, that does takes a trick or two since Windows is adamant about stopping you from overwriting a locked file.
It is possible at all because the operating system only puts a lock on the file data but not on the directory entry for a file. In other words, it is valid to rename the file, even though it is locked. The underlying system call is the same as File.Move().
Which operates two distinct ways, depending on the destFileName. If the destination path is on the same drive, the file system merely has to move the directory entry. Very fast and trouble-free. But that cannot work if it is not on the same drive, that requires moving the file data as well. Which is of course slow and not possible at all in a scenario where the file data is locked.
It is therefore imperative that the destinationBackupFileName argument you pass to File.Replace() is a path that's on the same drive as sourceFileName. Not doing this causes the exception when the move fails. Not otherwise hard to do in general, boilerplate is to make the backup filename simply the same as the source filename with, say, ".bak" appended to the path.

How to calculate size of directory on FTP?

How to calculate size of FTP folder? Do you know any tool or programmatic way in C#?
If you have FileZilla, you can use this trick:
click on the folder(s) whose size you want to calculate
click on Add files to queue
This will scan all folders and files and add them to the queue. Then look at the queue pane and below it (on the status bar) you should see a message indicating the queue size.
You can use the du command in lftp for this purpose, like this:
echo "du -hs ." | lftp example.com 2>&1
This will print the current directory's disk size incl. all subdirectories, in human-readable format (-h) and omitting output lines for subdirectories (-s). stderr output is rerouted to stdout with 2>&1 so that it is included in the output.
However, lftp is a Linux-only software, so to use it from C# under Windows you would need to install it in the integrated Windows Subsystem for Linux (WSL) or using Cygwin or MSYS2. (Thanks to the commenters for the hints!)
The lftp du command documentation is missing from its manpage, but available within the lftp shell with the help du command. For reference, I copy its output here:
lftp :~> help du
Usage: du [options] <dirs>
Summarize disk usage.
-a, --all write counts for all files, not just directories
--block-size=SIZ use SIZ-byte blocks
-b, --bytes print size in bytes
-c, --total produce a grand total
-d, --max-depth=N print the total for a directory (or file, with --all)
only if it is N or fewer levels below the command
line argument; --max-depth=0 is the same as
--summarize
-F, --files print number of files instead of sizes
-h, --human-readable print sizes in human readable format (e.g., 1K 234M 2G)
-H, --si likewise, but use powers of 1000 not 1024
-k, --kilobytes like --block-size=1024
-m, --megabytes like --block-size=1048576
-S, --separate-dirs do not include size of subdirectories
-s, --summarize display only a total for each argument
--exclude=PAT exclude files that match PAT
WinSCP (free GUI on Microsoft Windows):
If you just need the work done, then SmartFTP might help you, it also has a PHP and ASP script to get the total folder size by recursively going through all the files.
You could send the LIST command which should give you a list of files in the directory and some info about them (fairly certain the size is included), which you could then parse out and add up.
Depends on how you connect to the server, but if you're useing the WebRequest.Ftp class there's the ListDirectoryDetails method to do this. See here for details and here for some sample code.
Just be aware, if you want to have the total size including all subdirectories, I think you'll have to enter each subdirectory and call it recursively so it could be quite slow. It can be quite slow thought so normally I'd recommended, if possible, to have a script on the server calculate the size and return the result in some way (possibly storing it in a file you could download and read).
Edit: Or if you just mean that you'd be happy with a tool that does it for you, I think FlashFXP does it and probably other advanced FTP clients will as well. Or if it's a unix server I have a vague memory that you could just login and type ls -laR or something to get a recursive directory listing.
I use the FTPS library from Alex Pilotti with C# to execute some FTP commands in a few production environments. The library works well, but you have to recursively get a list of files in the directory and add their sizes together to get the result. This can be a bit time consuming on some of our larger servers (sometimes 1-2 min) with complex file structures.
Anyway, this is the method I use with his library:
/// <summary>
/// <para>This will get the size for a directory</para>
/// <para>Can be lengthy to complete on complex folder structures</para>
/// </summary>
/// <param name="pathToDirectory">The path to the remote directory</param>
public ulong GetDirectorySize(string pathToDirectory)
{
try
{
var client = Settings.Variables.FtpClient;
ulong size = 0;
if (!IsConnected)
return 0;
var dirList = client.GetDirectoryList(pathToDirectory);
foreach (var item in dirList)
{
if (item.IsDirectory)
size += GetDirectorySize(string.Format("{0}/{1}", pathToDirectory, item.Name));
else
size += item.Size;
}
return size;
}
catch (Exception ex)
{
Console.WriteLine(ex.Message);
}
return 0;
}
Simplest and Efficient way to Get FTP Directory Size with it's all Contents recursively.
var size = FtpHelper.GetFtpDirectorySize("ftpURL", "userName",
"password");
using System;
using System.Collections.Generic;
using System.IO;
using System.Net;
using System.Threading;
using System.Threading.Tasks;
public static class FtpHelper
{
public static long GetFtpDirectorySize(Uri requestUri, NetworkCredential networkCredential, bool recursive = true)
{
//Get files/directories contained in CURRENT directory.
var directoryContents = GetFtpDirectoryContents(requestUri, networkCredential);
long ftpDirectorySize = default(long); //Set initial value of the size to default: 0
var subDirectoriesList = new List<Uri>(); //Create empty list to fill it later with new founded directories.
//Loop on every file/directory founded in CURRENT directory.
foreach (var item in directoryContents)
{
//Combine item path with CURRENT directory path.
var itemUri = new Uri(Path.Combine(requestUri.AbsoluteUri + "\\", item));
var fileSize = GetFtpFileSize(itemUri, networkCredential); //Get item file size.
if (fileSize == default(long)) //This means it has no size so it's a directory and NOT a file.
subDirectoriesList.Add(itemUri); //Add this item Uri to subDirectories to get it's size later.
else //This means it has size so it's a file.
Interlocked.Add(ref ftpDirectorySize, fileSize); //Add file size to overall directory size.
}
if (recursive) //If recursive true: it'll get size of subDirectories files.
//Get size of selected directory and add it to overall directory size.
Parallel.ForEach(subDirectoriesList, (subDirectory) => //Loop on every directory
Interlocked.Add(ref ftpDirectorySize, GetFtpDirectorySize(subDirectory, networkCredential, recursive)));
return ftpDirectorySize; //returns overall directory size.
}
public static long GetFtpDirectorySize(string requestUriString, string userName, string password, bool recursive = true)
{
//Initialize Uri/NetworkCredential objects and call the other method to centralize the code
return GetFtpDirectorySize(new Uri(requestUriString), GetNetworkCredential(userName, password), recursive);
}
public static long GetFtpFileSize(Uri requestUri, NetworkCredential networkCredential)
{
//Create ftpWebRequest object with given options to get the File Size.
var ftpWebRequest = GetFtpWebRequest(requestUri, networkCredential, WebRequestMethods.Ftp.GetFileSize);
try { return ((FtpWebResponse)ftpWebRequest.GetResponse()).ContentLength; } //Incase of success it'll return the File Size.
catch (Exception) { return default(long); } //Incase of fail it'll return default value to check it later.
}
public static List<string> GetFtpDirectoryContents(Uri requestUri, NetworkCredential networkCredential)
{
var directoryContents = new List<string>(); //Create empty list to fill it later.
//Create ftpWebRequest object with given options to get the Directory Contents.
var ftpWebRequest = GetFtpWebRequest(requestUri, networkCredential, WebRequestMethods.Ftp.ListDirectory);
try
{
using (var ftpWebResponse = (FtpWebResponse)ftpWebRequest.GetResponse()) //Excute the ftpWebRequest and Get It's Response.
using (var streamReader = new StreamReader(ftpWebResponse.GetResponseStream())) //Get list of the Directory Contentss as Stream.
{
var line = string.Empty; //Initial default value for line
while (!string.IsNullOrEmpty(line = streamReader.ReadLine())) //Read current line of Stream.
directoryContents.Add(line); //Add current line to Directory Contentss List.
}
}
catch (Exception) { throw; } //Do nothing incase of Exception occurred.
return directoryContents; //Return all list of Directory Contentss: Files/Sub Directories.
}
public static FtpWebRequest GetFtpWebRequest(Uri requestUri, NetworkCredential networkCredential, string method = null)
{
var ftpWebRequest = (FtpWebRequest)WebRequest.Create(requestUri); //Create FtpWebRequest with given Request Uri.
ftpWebRequest.Credentials = networkCredential; //Set the Credentials of current FtpWebRequest.
if (!string.IsNullOrEmpty(method))
ftpWebRequest.Method = method; //Set the Method of FtpWebRequest incase it has a value.
return ftpWebRequest; //Return the configured FtpWebRequest.
}
public static NetworkCredential GetNetworkCredential(string userName, string password)
{
//Create and Return NetworkCredential object with given UserName and Password.
return new NetworkCredential(userName, password);
}
}
As the answer by #FranckDernoncourt shows, if you want a GUI tool, you can use WinSCP GUI. Particularly its folder properties dialog.
If you need a code, you can use WinSCP too. Particularly with WinSCP .NET assembly and its Session.EnumerateRemoteFiles method it is easy to implement in many languages, including C#.
It is also doable with .NET built-in FtpWebRequest, but that's lot more work.
Both are covered in How to get a directories file size from an FTP protocol in a .NET application.
You can use The FileZilla client. Download here: https://filezilla-project.org/download.php?type=client
If you want more readable size go to:
Edit -> Settings -> Interface -> filesize format -> size formatting -> select binary prefixes using SI symbols.
When you select a directory you can see its size.
Just use FTP "SIZE" command...

Categories

Resources