I have code that allows me to access a server to do ftp transactions. I have tested the connection and it works. the problem is saving files. to help paint a picture this is how the address are set up.
ftp server: ftp.MyMainDomain.com
path login ftp points to: www.another_website_Under_myDomain.com/gallery/images
when I tested connection, ftp server tacks me directly to images folder and I have even read the subdirectories out (ie ..images/subdirectory1, ..images/subdirectory2).
What I need now it to be able to save files into each of the folders. I thought that all I had to do was add subdir that I wanted to access to the end of the ftp_server uri but that doesn't work. What should I do?
Uri ftpUri = new Uri((Ftp_Server_Address + "/" + SubDirectory+ "/"), UriKind.Absolute);
if (ftpUri.Scheme == Uri.UriSchemeFtp)// check ftp address,
{
DirRequest = (FtpWebRequest)FtpWebRequest.Create(ftpUri);
DirRequest.Method = ReqMethod;
DirRequest.Credentials = new NetworkCredential(FtpUserName, FtpPassword);
DirRequest.UsePassive = true;
DirRequest.UseBinary = true;
DirRequest.KeepAlive = false;
//change picture to stream
Stream PicAsStream = Pic.Bitmap_to_Stream(Pic.BitmapImage_to_Bitmap(Pic.Photo));
//send ftp with picture
Stream ftpReqStream = DirRequest.GetRequestStream();
ftpReqStream = PicAsStream;
ftpReqStream.Close();
SendFtpRequest(ReqMethod);
}
In this line:
ftpReqStream = PicAsStream;
You are not sending the Stream to ftp Server but you are assigning PicAsStream to ftpReqStream and then closing it. Your code does nothing.
Do it like this:
Create a buffer of your image file (not a stream):
FileStream ImageFileStream = File.OpenRead(your_file_path_Here);
byte[] ImageBuffer = new byte[ImageFileStream.Length];
ImageFileStream.Read(ImageBuffer, 0, ImageBuffer.Length);
ImageFileStream.Close();
and then simply write it to your ftpReqStream:
Stream ftpReqStream = DirRequest.GetRequestStream();
ftpReqStream.Write(ImageBuffer, 0, ImageBuffer.Length);
ftpReqStream.Close();
Related
I need to upload a few files from Azure Storage to an external Ftp server.
Is there any way with Azure to uplodad these files directly without download them before ?
You will need to use two classes/libraries and create two methods here:
WebClient class to download the file from the blob storage to your local drive
FTP library such WinSCP to move the file
WebClient Class:
You need to supply the URI parameter with the format: https://[accountname].blob.core.windows.net/[containername]/[filetodownloadincludingextension]
The download location must then be a variable as the origin location of the file to be uploaded to your FTP server.
string uri = "https://[accountname].blob.core.windows.net/[containername]/[filetodownloadincludingextension]/";
string file = "file1.txt";
string downloadLocation = #"C:\";
WebClient webClient = new WebClient();
Log("Downloading File from web...");
try
{
webClient.DownloadFile(new Uri(uri+file), downloadLocation);
Log("Download from web complete");
webClient.Dispose();
}
catch (Exception ex)
{
Log("Error Occurred in downloading file. See below for exception details");
Log(ex.Message);
webClient.Dispose();
}
return downloadLocation + file;
Once downloaded in your local drive, you need to upload it to your FTP/SFTP server. You may use the library of WinSCP for this:
string absPathSource = downloadLocation + file;
string destination = "/root/folder"; //this basically is your FTP path
// Setup session options
SessionOptions sessionOptions = new SessionOptions
{
Protocol = Protocol.Sftp,
HostName = ConfigurationManager.AppSettings["scpurl"],
UserName = ConfigurationManager.AppSettings["scpuser"],
Password = ConfigurationManager.AppSettings["scppass"].Trim(),
SshHostKeyFingerprint = ConfigurationManager.AppSettings["scprsa"].Trim()
};
using (Session session = new Session())
{
//disable version checking
session.DisableVersionCheck = true;
// Connect
session.Open(sessionOptions);
// Upload files
TransferOptions transferOptions = new TransferOptions();
transferOptions.TransferMode = TransferMode.Binary;
TransferOperationResult transferResult;
transferResult = session.PutFiles(absPathSource, destination, false, transferOptions);
// Throw on any error
transferResult.Check();
// Print results
foreach (TransferEventArgs transfer in transferResult.Transfers)
{
//Console.WriteLine("Upload of {0} succeeded", transfer.FileName);
}
}
You may include a File.Delete code at the end of the upload to FTP code if you want to delete the file from your local hard drive after the upload.
I came across this question whilst looking for the same answer, I came up with the following solution:
Get the Azure file as a Stream [Handled by Azure Functions for you]
Using WebClient Upload the Stream
This allowed me to transfer the file directly from Blob Storage to an FTP client. For me the Azure Blob file as a Stream was already done as I was creating an Azure Function based on a blob trigger.
I then converted the Stream to a MemoryStream and passed that to WebClient.UploadData() as a byte array [very roughly something like]:
// ... Get the Azure Blob file in to a Stream called myBlob
// As mentioned above the Azure function does this for you:
// public static void Run([BlobTrigger("containerName/{name}", Connection = "BlobConnection")]Stream myBlob, string name, ILogger log)
public void UploadStreamToFtp(Stream file, string targetFilePath)
{
using (MemoryStream ms = new MemoryStream())
{
// As memory stream already handles ToArray() copy the Stream to the MemoryStream
file.CopyTo(ms);
using (WebClient client = new WebClient())
{
// Use login credentails if required
client.Credentials = new NetworkCredential("username", "password");
// Upload the stream as Data with the STOR method call
// targetFilePath is a fully qualified filepath on the FTP, e.g. ftp://targetserver/directory/filename.ext
client.UploadData(targetFilePath, WebRequestMethods.Ftp.UploadFile, ms.ToArray());
}
}
}
I am new to C# and want to get list of file names in ftp directory. But i read some answer on other topics WebRequestMethods is for the single request.
Here is my current code getting FTP object for a specific files.
I want all files ends with ".txt" and want regex like "*.txt". How can I get all file names
in FTP directory?
reqFTP = (System.Net.FtpWebRequest)System.Net.FtpWebRequest.Create(new Uri("ftp://95.0.181.84/bankToCompany/" + fileName));
reqFTP.Method = WebRequestMethods.Ftp.DownloadFile;
reqFTP.UseBinary = true;
reqFTP.Credentials = new NetworkCredential(obj.ftpUserName,obj.ftpPassword);
System.Net.FtpWebResponse response = (System.Net.FtpWebResponse)reqFTP.GetResponse();
Stream ftpStream = response.GetResponseStream();
FileStream outputStream = new FileStream(obj.collectionFileDownloadAddress + renameAddress, FileMode.Create);
StreamReader reader = new StreamReader(responseStream);
string contents = reader.ReadToEnd();
How to: List Directory Contents with FTP
FTP is an old and horrible protocol to work with even in .Net but MSDN has some documentaion about it here.
Check out the "How to: Download Files with FTP" and "How to: Upload Files with FTP" links to the left aswell if you need.
i downloaded images from my deployed website and save it into my WPF app folder , basically i am running 2 platforms , a website and WPF . What i am trying to do is users uploaded their images using the web , so on the WPF side , i download the image from the web and display on my WPF app but i got this error :
The process cannot access the file
'C:\Users\apr13mpsipa\Desktop\OneOrganizer\OneOrganizer\bin\Debug\TaskImage\Fill
in the blanks.jpg' because it is being used by another process.
This is the code :
protected void DownloadData(string strFileUrlToDownload, string taskName)
{
WebClient client = new WebClient();
byte[] myDataBuffer = client.DownloadData(strFileUrlToDownload);
MemoryStream storeStream = new MemoryStream();
storeStream.SetLength(myDataBuffer.Length);
storeStream.Write(myDataBuffer, 0, (int)storeStream.Length);
storeStream.Flush();
currentpath = System.IO.Directory.GetCurrentDirectory() + #"\TaskImage\" + taskName + ".jpg"; //folder to contain files.
using (FileStream file = new FileStream(currentpath, FileMode.Create, System.IO.FileAccess.ReadWrite)) // ERROR HERE
{
byte[] bytes = new byte[storeStream.Length];
storeStream.Read(bytes, 0, (int)storeStream.Length);
file.Write(myDataBuffer, 0, (int)storeStream.Length);
storeStream.Close();
}
//The below Getstring method to get data in raw format and manipulate it as per requirement
string download = Encoding.ASCII.GetString(myDataBuffer);
}
I got the error when i try to display a image on a first button click , then i display the image again on the other button . basically this happens when i try to display the image 2 times.
---EDIT ------
Updated as of baldrick's comment :
DownloadData(fileUploadDirectory + daoTask.GetImage(aid, actTask.taskID).Substring(1), daoTask.GetTaskName(aid, actTask.taskID));
Image imgActivityTask = new Image();
imgActivityTask.Height = 90;
imgActivityTask.Width = 90;
imgActivityTask.Margin = new Thickness(10);
BitmapImage img = new BitmapImage();
img.BeginInit();
img.UriSource = new Uri(currentpath, UriKind.Absolute);
img.CreateOptions = BitmapCreateOptions.IgnoreImageCache;
img.EndInit();
imgActivityTask.Source = img;
Its still giving me the same error on the using line.
In you WPF code, you might need to specify the IgnoreImageCache setting:
yourImage.CacheOption = BitmapCacheOption.OnLoad;
yourImage.CreateOptions = BitmapCreateOptions.IgnoreImageCache
This might force it to load, and not lock the file.
The answer here deals with the same problem.
I am guessing you are leaving the file stream open.
Not sure why you are creating a memory stream (by the way, don't forget to close memory stream), and a file stream when you already have the bytes? Why not directly write to the file using File.WriteAllBytes?
WebClient client = new WebClient();
byte[] myDataBuffer = client.DownloadData(strFileUrlToDownload);
currentpath = System.IO.Directory.GetCurrentDirectory() + #"\TaskImage\" + taskName + ".jpg"; //folder to contain files.
File.WriteAllBytes(currentPath, myDataBuffer);
//The below Getstring method to get data in raw format and manipulate it as per requirement
string download = Encoding.ASCII.GetString(myDataBuffer);
Not sure why you are creating a memory stream (by the way, don't forget to close memory stream), and a file stream when you already have the bytes? Why not directly write to the file using File.WriteAllBytes?
WebClient client = new WebClient();
byte[] myDataBuffer = client.DownloadData(strFileUrlToDownload);
currentpath = System.IO.Directory.GetCurrentDirectory() + #"\TaskImage\" + taskName + ".jpg"; //folder to contain files.
File.WriteAllBytes(currentPath, myDataBuffer);
//The below Getstring method to get data in raw format and manipulate it as per requirement
string download = Encoding.ASCII.GetString(myDataBuffer);
Thanks
I have trouble with webbrowser or may be ftp. I am uploading a picture and when I navigate the webbrowser it shows me the old photo, yet the picture im uploading gets to the ftp and gets overwrite. Here is the code:
webBrowser1.Refresh(WebBrowserRefreshOption.Completely);
webBrowser1.Navigate("www.google.com");
openFileDialog1.ShowDialog();
string filename = Path.GetFullPath(openFileDialog1.FileName);
FileInfo toUpload = new FileInfo(#"upload.jpg");
FtpWebRequest request = (FtpWebRequest)WebRequest.Create("ftp://fingercube.co.cc/public_html/objimg/" + toUpload.Name);
request.Method = WebRequestMethods.Ftp.UploadFile;
request.Credentials = new NetworkCredential("username", "pass");
Stream ftpStream = request.GetRequestStream();
FileStream file = File.OpenRead(filename);
int lenght = 2;
byte[] buffer = new byte[lenght];
int bytesRead = 0;
do
{
bytesRead = file.Read(buffer, 0, lenght);
ftpStream.Write(buffer, 0, bytesRead);
}
while (bytesRead != 0);
file.Close();
ftpStream.Close();
webBrowser1.Navigate("http://fingercube.co.cc/objimg/"+toUpload.Name);
It shows me the old photo everytime, but the photo is uploaded every time. :(
If the caching suggestion doesn't work try doing the following.
this.webBrowser1.Navigate("about:blank");
HtmlDocument doc = this.wbbFinalise.Document;
doc.Write(string.Empty);
Then navigate to your ftp location.
I had a similar issue while trying to refresh a locally generated HTTP page in the web browser and this fixed the issue.
The image is cached to IE cache. You must clear the cache before refreshing the control. Have a look here: http://www.gutgames.com/post/Clearing-the-Cache-of-a-WebBrowser-Control.aspx
Also, a related question on SO: WebBrowser control caching issue
got the solution .. the problem was with the cache easy solution to it was to make new request everytime .
I have a windows form application in which i am using a background worker to ftp upload files. After uploading 209 files successfully it gave error on file which only had size of 7.8kb that While Processing Img1.jpg Unable to write data to the transport connection. An existing connection was forcibly closed by the remote host.
string uri1;
ftpInfoUpload = LoadHostedSiteData(hs);
ftpInfoUpload[5] = imgRow["Filename"].ToString();
uri1 = String.Format("ftp://{0}/{1}/images/{2}", ftpInfoUpload[1], ftpInfoUpload[2], ftpInfoUpload[5]);
requestUpload = (FtpWebRequest)WebRequest.Create(uri1);
requestUpload.UsePassive = false;
requestUpload.UseBinary = true;
requestUpload.Method = WebRequestMethods.Ftp.UploadFile;
requestUpload.Credentials = new NetworkCredential(ftpInfoUpload[3], ftpInfoUpload[4]);
requestUpload.ContentLength = memStream.Length;
byte[] buff = new byte[bufferSize];
int contentLen;
// Stream to which the file to be upload is written
Stream strm = requestUpload.GetRequestStream();
memStream.Seek(0, SeekOrigin.Begin);
contentLen = memStream.Read(buff, 0, bufferSize);
// Till Stream content ends
while (contentLen > 0)
{
// Write Content from the file stream to the FTP Upload Stream
strm.Write(buff, 0, contentLen);
contentLen = memStream.Read(buff, 0, bufferSize);
}
//Close the file stream and the Request Stream
strm.Close();
strm.Dispose();
ftpStream.Close();
memStream.Close();
//responseUpload.Close();
responseDownload.Close();
And ideas whats happening?
I have set ftprequest.KeepAlive=true & set ftprequest.ConnectionGroupName = "Some Value", so that underlying code does not have to new create connection which have the same ftp server. I found this solution here. I also found this helpful. Also make sure not to create a new NetworkCredential object everytime you transfer a file that can cause exception. I have tested my code twice transferring 300 files and seems to work perfectly and quick. Setting KeepAlive=false can make transfers slow