Read FTP file contents to a string in C# FluentFTP - c#

My class inherits from FluentFTP and I have created a class like this. I need to create a function called Read in this class. The purpose of the read function is to return a string to me by reading the contents of the files I have read from the FTP line by line. I'll process the rotating string later. Is there a method for this in FluentFTP? Ff there is none, how should I create the function?
using FluentFTP;
public class CustomFtpClient : FtpClient
{
public CustomFtpClient(
string host, int port, string username, string password) :
base(host, port, username, password)
{
Client = new FtpClient(host, port, username, password);
Client.AutoConnect();
}
private FtpClient Client { get; }
public string ReadFile(string remoteFileName)
{
Client.BufferSize = 4 * 1024;
return Client.ReadAllText(remoteFileName);
}
}
I can't write like this because the Client I'm writing comes from FTP. Since I derived it from SFTP in my previous codes, I wanted to use a similar code snippet to it, but there is no such code snippet in FluentFTP. How should I perform an operation in the Read function?
In another file, I want to call it like this.
CustomFtpClient = new CustomFtpClient(ftpurl, 21, ftpusername, ftppwd);
var listedfiles = CustomFtpClient.GetListing("inbound");
var onlyedifiles = listedfiles.Where(z =>
z.FullName.ToLower().Contains(".txt") || z.FullName.ToLower().Contains("940"))
.ToList();
foreach (var item in onlyedifiles)
{
//var filestr = CustomFtpClient.ReadFile(item.FullName);
}

To read file to a string using FluentFTP, you can use FtpClient.Download (FtpClient.DownloadStream or FtpClient.DownloadBytes in upcoming versions) that either writes the file contents to Stream or byte[] array. The following examples uses the latter.
if (!client.Download(out byte[] bytes, "/remote/path/file.txt"))
{
throw new Exception("Cannot read file");
}
string contents = Encoding.UTF8.GetString(bytes);

Related

C# WebApi How can i get complete Image from HttpPostedFile

Here I'm using WebApi I want an image for sending Email For that I wrote the code as:
var files = HttpContext.Current.Request.Files;
if (files.Count > 0) {
for (int i = 0; i < files.Count; i++) {
HttpPostedFile file = files[i];
mailModel.filename = file.FileName;
mailModel.filecontent = file.InputStream;
}
}
Here How can i Bind mailModel.Filecontent
My Class File as
public class SendMailRequest
{
public string filecontent { get; set; }
public string filename { get; set; }
}
My Mail Sending Code is:
if (mailModel.filename != null) {
string tempPath = WebConfigurationManager.AppSettings["TempFile"];
string filePath = Path.Combine(tempPath, mailModel.filename);
using(System.IO.FileStream reader = System.IO.File.Create(filePath)) {
byte[] buffer = Convert.FromBase64String(mailModel.filecontent);
reader.Write(buffer, 0, buffer.Length);
reader.Dispose();
}
msg.Attachments.Add(new Attachment(filePath));
How can I Bind my File to the FileContent?
I think you probably want to learn about using Streams in .Net? First use Stream not string here:
public class SendMailRequest
{
public Stream FileContent { get; set; }
public string FileName { get; set; }
}
Then, because it's utterly confusing, rename your reader to writer.
Then, don't do anything stringy with your Stream, just do:
await mailModel.filecontent.CopyToAsync(writer);
There is a complication here. This code assumes that the original uploaded filestream is still present and working, in memory, at the time that you try to send your email. Whether that is true depends on what happens in between.
Especially, if the Http request processing has finished and a response been returned before the email gets sent, the filecontent stream has probably already gone away. has A safer course is to do the copy straight away in the controller:
file.InputStream.CopyToASync(mailModel.filecontent)
but at this point I have to say, I would rather either (1) copy straight to a file or (2) copy into a MemoryStream. i.e.
mailModel.filecontent= new MemoryStream();
file.InputStream.CopyToASync(mailModel.filecontent)
(If you use MemoryStream, you must calculate what is the largest file you are willing to handle, and make sure bigger files are rejected before you create the memory stream).
Finally, if this populates your file with Base64 instead of the binary, look at the answers to this question: HttpRequest files is empty when posting through HttpClient

Azure stored file has different MD5 checksum than local file (being same file)

I'm using a could service to upload files to an Azure Storage service, so I want to check the file's integrity using MD5 checksum, so first I get the checksum from a function.
public static string GetMD5HashFromFile(Stream stream)
{
using (var md5 = MD5.Create())
{
return BitConverter.ToString(md5.ComputeHash(stream)).Replace("-", string.Empty);
}
}
for the test file I'm using I'm getting: 1dffc245282f4e0a45a9584fe90f12f2 and I got the same result when I use an online tool like this.
Then I upload the file to Azure and get it from my code like this: (In order to avoid include the validations let's assume the file and directories do exist.)
public bool CompareCheckSum(string fileName, string checksum)
{
this.storageAccount = CloudStorageAccount.Parse(CloudConfigurationManager.GetSetting("MyConnectionString"));
this.fileClient = this.storageAccount.CreateCloudFileClient();
this.shareReference = this.fileClient.GetShareReference(CloudStorageFileShareSettings.StorageFileShareName);
this.rootDir = this.shareReference.GetRootDirectoryReference();
this.directoryReference = this.rootDir.GetDirectoryReference("MyDirectory");
this.fileReference = this.directoryReference.GetFileReference(fileName);
Stream stream = new MemoryStream();
this.fileReference.DownloadToStream(stream);
string azureFileCheckSum = GetMD5HashFromFile(stream);
return azureFileCheckSum.ToLower() == checksum.ToLower();
}
I also tried to get the checksum using a different process like this:
public bool CompareCheckSum(string fileName, string checksum)
{
this.storageAccount = CloudStorageAccount.Parse(CloudConfigurationManager.GetSetting("MyConnectionString"));
this.fileClient = this.storageAccount.CreateCloudFileClient();
this.shareReference = this.fileClient.GetShareReference(CloudStorageFileShareSettings.StorageFileShareName);
this.rootDir = this.shareReference.GetRootDirectoryReference();
this.directoryReference =
this.rootDir.GetDirectoryReference("MyDirectory");
this.fileReference = this.directoryReference.GetFileReference(fileName);
this.fileReference.FetchAttributes();
string azureFileCheckSum = this.fileReference.Metadata["md5B64"];
return azureFileCheckSum.ToLower() == checksum.ToLower();
}
Finally, for the azureFileCheckSum I'm getting: d41d8cd98f00b204e9800998ecf8427e not sure if am I doing something wrong or if something change when I upload the file to the ftp...
Before you call md5.ComputeHash(stream), you need to reset the stream's position to the beginning.
stream.Position = 0;
Of course, this will fail with a NotSupportedException if the stream type doesn't support seeking, but in your case it should work.

C# create xls or csv file and create link to download the file

I now have this scenario:
I have a table in SQL Server, and a handful of webpage-user-defined queries that generates a results page showing the results. The controller functions are all ready to use.
Now I would like to be able to download the results to local computers accessing the website. I'm not sure yet what to put the results into. I've searched for it and both xls and csv files seem pretty straight-forward enough. But they only create a file and then save it onto the server side.
So my questions are:
Does the task must be accomplished by creating a temporary file ==> download the temporary file to client ==> delete the temporary file on the server?
If it must be so, how do I create a button for downloading that temporary file? And what will happen if it is serving multiple users at the same time?
Not sure what to do now and any help would be appreciated.
You should create a MemoryStream from the data received from Sql Server. Create a new class with the code below.
public abstract class FileActionResult : IHttpActionResult
{
private string MediaType { get; }
private string FileName { get; }
private Stream Data { get; }
protected FileActionResult(Stream data, string fileName, string mediaType)
{
Data = data;
FileName = fileName;
MediaType = mediaType;
}
public Task<HttpResponseMessage> ExecuteAsync(CancellationToken cancellationToken)
{
Data.Position = 0;
var response = new HttpResponseMessage
{
Content = new StreamContent(Data)
};
response.Content.Headers.ContentDisposition = new ContentDispositionHeaderValue("attachment");
response.Content.Headers.ContentType = new MediaTypeHeaderValue(MediaType);
response.Content.Headers.ContentDisposition.FileName = FileName;
response.Content.Headers.ContentLength = Data.Length;
return Task.FromResult(response);
}
}
public class ExcelFileActionResult : FileActionResult
{
public ExcelFileActionResult(Stream data) : base(data, "Exported.xls", "application/vnd.ms-excel")
{
}
}
Calling code from Controller.
return new ExcelFileActionResult(stream);
stream is the memorystream.

Provide file contents as a string instead of a filename

I'm very new to C#, but not to programming. I'm trying to use SSH.NET to make an SSH connection using a private key, using the example is here:
public ConnectionInfo CreateConnectionInfo()
{
const string privateKeyFilePath = #"C:\some\private\key.pem";
ConnectionInfo connectionInfo;
using (var stream = new FileStream(privateKeyFilePath, FileMode.Open, FileAccess.Read))
{
var privateKeyFile = new PrivateKeyFile(stream);
AuthenticationMethod authenticationMethod =
new PrivateKeyAuthenticationMethod("ubuntu", privateKeyFile);
connectionInfo = new ConnectionInfo(
"my.server.com",
"ubuntu",
authenticationMethod);
}
return connectionInfo;
}
I don't have the key stored in a file, it comes from another source and I have it in a string. I realize I could write it to a temporary file, then pass that filename, then trash the file, but I'd prefer not to have to write it out to disk if possible. I don't see anything in the documentation that lets me pass a string for this, only a filename. I've tried something like this to convert the string to a stream:
byte[] private_key = Encoding.UTF8.GetBytes(GetConfig("SSHPrivateKey"));
var private_key_stream = new PrivateKeyFile(new MemoryStream(private_key));
And then pass private_key_stream as the second parameter of PrivateKeyAuthenticationMethod. There seem to be no complaints from the compiler, but the method doesn't appear to actually be getting the key (SSH doesn't authenticate, and external attempts like PuTTY using this key to the server do work), so it looks like I'm missing something.
Any thoughts on how to accomplish this without writing out a temp file?

Read a PDF file and return as stream from a WCF service?

I want to create a WCF service (working like windows service). This service will read a PDF file from a specific path, extract pages, create a new PDF file and return it to the caller.
How can I do this ? I use QuickPDF to process on PDF files, I can extract and create new PDF file. How can use this in a WCF service ?
Waiting your helps...
This is only sample code :
public Stream ExtractPdf(string PathOfOriginalPdfFile, int StartPage,int PageCount)
{
PDFLibrary qp = new PDFLibrary();
Stream Stream_ = null;
if (qp.UnlockKey(".................") == 0)
{
string fileName = #"..\..\Test Files\sample1.pdf";
string OutputFile = #"..\..\Test Files\sample1_extracted.pdf";
if (qp.Unlocked() == 1)
{
int docID = qp.LoadFromFile(fileName, "");
int extractPageSuccess = qp.ExtractPages(StartPage, PageCount);
if (extractPageSuccess == 0)
{
// error
}
else
{
qp.SaveToFile(OutputFile);
}
}
}
//
// Codes here
//
return Stream_;
}
I edited it :
public byte[] ExtractPdf(string PathOfOriginalPdfFile, int StartPage,int PageCount)
{
QuickPDFDLL0815.PDFLibrary qp = new QuickPDFDLL0815.PDFLibrary(#"C:\Program Files (x86)\Quick PDF Library\DLL\QuickPDFDLL0815.dll");
string fileName = #"..\..\Test Files\sample1.pdf";
byte[] binFile = null;
if (qp.UnlockKey("...................") == 0)
{
if (qp.Unlocked() == 1)
{
int docID = qp.LoadFromFile(fileName, "");
int extractPageSuccess = qp.ExtractPages(StartPage, PageCount);
if (extractPageSuccess == 0)
{
// error
}
else
{
binFile = qp.SaveToString();
}
}
}
return binFile;
}
You could send the file as a Stream, see How to: Enable Streaming, then on the client save off the file and have the shell execute it. The MSDN article includes a sample GetStream method as well as a whole section on Writing a custom stream.
If you would like fuller sample code the forum post Streamed file transfer using WCF starts with some, however, note that the author posted it there because they were encountering issues running it.
As to byte[] or stream see Uploading Image Blobs–Stream vs Byte Array and Stream vs Raw Bytes. The second states
Streams will perform better for large files since not all of it needs to be read into memory at one time

Categories