I cannot delete a file via FTP - c#

I am trying to delete all the files in a folder via FTP. Below is the code I am trying.
Files is an array of strings each one if the name of a file in the folder with its extension.
When I run it I get an a reply of 206 but when I look in the folder all the files remain. I tried variations of the code below, including adding a delay, but still cannot delete the files. What have I missed?
foreach (var FileName2 in Files)
{
if (File.Exists(txtbx_save_backup_to.Text + "/" + FileName2))
{
FtpWebRequest Delrequest = (FtpWebRequest)WebRequest.Create(ftp_address + "/Temp/Backup/" + FileName2);
Delrequest.Credentials = new NetworkCredential(username, password);
Delrequest.Method = WebRequestMethods.Ftp.DeleteFile;
Task.Delay(1000);
using (FtpWebResponse response2 = (FtpWebResponse)request.GetResponse())
{
rchtxtbx_backup_comms.AppendText("Deleted File, status " + response2.StatusDescription + "\r");
rchtxtbx_backup_comms.ScrollToCaret();
}
}
}

The comments above gave me the clue I needed in a roundabout way so thanks to you for answering.
I had missed out the part to "action" the delete request. So I added the following and now it works.
WebResponse GetResponse = Delrequest.GetResponse();
Stream GResponseStream = GetResponse.GetResponseStream();
I removed the wait and the complete code is now
foreach (var FileName2 in Files)
{
if (File.Exists(txtbx_save_backup_to.Text + "/" + FileName2))
{
FtpWebRequest Delrequest = (FtpWebRequest)WebRequest.Create(ftp_address + "/Temp/Backup/" + FileName2);
Delrequest.Credentials = new NetworkCredential(username, password);
Delrequest.Method = WebRequestMethods.Ftp.DeleteFile;
//Action request
WebResponse GetResponse = Delrequest.GetResponse();
Stream GResponseStream = GetResponse.GetResponseStream();
using (FtpWebResponse response2 = (FtpWebResponse)request.GetResponse())
{
rchtxtbx_backup_comms.AppendText("Deleted File, status " + response2.StatusDescription + "\r");
rchtxtbx_backup_comms.ScrollToCaret();
}
GResponseStream.Close();
}
}

Related

AzureDevops Api: Get item API with download true return a json

I'm trying to download a Git File using C#. I use the following code:
Stream response = await client.GetStreamAsync(url);
var splitpath = path.Split("/");
Stream file = File.OpenWrite(splitpath[splitpath.Length - 1]);
response.CopyToAsync(file);
response.Close();
file.Close();
Following this documentation, I use the following url:
string url = mainurl + name + "/_apis/git/repositories/" + rep + "/items?path=" + path + "&download=true&api-version=6.0";
but the file saved contains a json containing different links and information about the git file.
To check if all was working well, I tried to download it in a zip format, using the following url:
string url = mainurl + name + "/_apis/git/repositories/" + rep + "/items?path=" + path + "&$format=zip";
And it works fine, the file downloaded is a zip file containing the original file with its content...
Can someone help me? Thanks
P.S. I know that I can set IncludeContent to True, and get the content in the json, but I need the original file.
Since you are using C#, I will give you a C# sample to get the original files:
using RestSharp;
using System;
using System.IO;
using System.IO.Compression;
namespace xxx
{
class Program
{
static void Main(string[] args)
{
string OrganizationName = "xxx";
string ProjectName = "xxx";
string RepositoryName = "xxx";
string Personal_Access_Token = "xxx";
string archive_path = "./"+RepositoryName+".zip";
string extract_path = "./"+RepositoryName+"";
string url = "https://dev.azure.com/"+OrganizationName+"/"+ProjectName+"/_apis/git/repositories/"+RepositoryName+"/items?$format=zip&api-version=6.0";
var client = new RestClient(url);
//client.Timeout = -1;
var request = new RestRequest(url, Method.Get);
request.AddHeader("Authorization", "Basic "+Personal_Access_Token);
var response = client.Execute(request);
//save the zip file
File.WriteAllBytes("./PushBack.zip", response.RawBytes);
//unzip the file
if (Directory.Exists(extract_path))
{
Directory.Delete(extract_path, true);
ZipFile.ExtractToDirectory(archive_path, extract_path);
}
else
{
ZipFile.ExtractToDirectory(archive_path, extract_path);
}
}
}
}
Successfully on my side:
Let me know whether this works on your side.
var personalaccesstoken = "xyz....";
using (HttpClient client = new HttpClient())
{
client.DefaultRequestHeaders.Accept.Add(
new System.Net.Http.Headers.MediaTypeWithQualityHeaderValue("*/*")); //this did the magic for me
client.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Basic",
Convert.ToBase64String(
System.Text.ASCIIEncoding.ASCII.GetBytes(
string.Format("{0}:{1}", "", personalaccesstoken))));
using (Stream stream = await client.GetStreamAsync(
"https://dev.azure.com/fabrikam/myproj/_apis/git/repositories/myrepoid/items?path=%2Fsrc%2Ffolder%2Ffile.txt&api-version=7.0")) //no download arg
{
StreamReader sr = new StreamReader(stream);
var text = sr.ReadToEnd();
return text; // text has the content of the source file
}
}
no need for download parameter in the url
request headers should not be json

Resuming interrupted upload using Google drive v3 C# sdk

I want to resume interrupted resumable upload using Google Drive v3 C# SDK.
The reason why I want this is to create resumable upload in Restful Web API.
There is google drive api instance in this RestAPI, so this is relaying chunk data from client program to google drive.
As you know, client program cannot upload whole file data at one time to Web API, so we need to resume interrupted resumable upload.
So my plan is here.
First, we need to create upload session and receive Session URI.
Second, Create Upload instance every time from returned URI and add chunk data.
Third, repeat 2nd process until EOF.
For this, I made test code, but it does not work at all.
var uploadStream = new System.IO.FileStream(UploadFileName, System.IO.FileMode.Open,
System.IO.FileAccess.Read);
var insert = service.Files.Create(new Google.Apis.Drive.v3.Data.File { Name = title }, uploadStream, ContentType);
Uri uploadUri = insert.InitiateSessionAsync().Result;
int chunk_size = ResumableUpload.MinimumChunkSize;
while (uploadStream.Length != uploadStream.Position)
{
byte[] temp = new byte[chunk_size];
uploadStream.Read(temp, 0, temp.Length);
MemoryStream stream = new MemoryStream(temp);
ResumableUpload resume_uploader = ResumableUpload.CreateFromUploadUri(uploadUri, stream);
resume_uploader.ChunkSize = chunk_size;
IUploadProgress ss = resume_uploader.Resume();
Console.WriteLine("Uploaded " + ss.BytesSent.ToString());
}
Frankly, I expected to receive 308 Resume Incomplete Code, but the result is different.
"Invalid request. According to the Content-Range header, the final size of the upload is 262144 byte(s). This does not match the expected size of 1193188 byte(s), which was specified in an earlier request."
This means that I need to create code that resumes interrupted resumable upload using Google Drive C# SDK.
Anybody can help me?
Finally, I solved issue. Exact code is below. Actually, I could not find any source code on Google, so I was so sad. Every developer who wants to solve this issue, use my code please. Hope you are fine. :)
public static async Task<Google.Apis.Drive.v3.Data.File> UploadSync(DriveService driveService, string filepath)
{
string destfilename = Path.GetFileName(filepath);
List<string> parents = new List<string>();
parents.Add("root");
// Prepare the JSON metadata
string json = "{\"name\":\"" + destfilename + "\"";
if (parents.Count > 0)
{
json += ", \"parents\": [";
foreach (string parent in parents)
{
json += "\"" + parent + "\", ";
}
json = json.Remove(json.Length - 2) + "]";
}
json += "}";
Debug.WriteLine(json);
Google.Apis.Drive.v3.Data.File uploadedFile = null;
try
{
System.IO.FileInfo info = new System.IO.FileInfo(filepath);
ulong fileSize = (ulong)info.Length;
var uploadStream = new System.IO.FileStream(filepath, System.IO.FileMode.Open, System.IO.FileAccess.Read);
var insert = driveService.Files.Create(new Google.Apis.Drive.v3.Data.File { Name = destfilename, Parents = new List<string> { "root" } }, uploadStream, "application/octet-stream");
Uri uploadUri = insert.InitiateSessionAsync().Result;
int chunk_size = ResumableUpload.MinimumChunkSize;
int bytesSent = 0;
while (uploadStream.Length != uploadStream.Position)
{
byte[] temp = new byte[chunk_size];
int cnt = uploadStream.Read(temp, 0, temp.Length);
if (cnt == 0)
break;
HttpWebRequest httpRequest = (HttpWebRequest)WebRequest.Create(uploadUri);
httpRequest.Method = "PUT";
httpRequest.Headers["Authorization"] = "Bearer " + ((UserCredential)driveService.HttpClientInitializer).Token.AccessToken;
httpRequest.ContentLength = (long)cnt;
httpRequest.Headers["Content-Range"] = string.Format("bytes {0}-{1}/{2}", bytesSent, bytesSent + cnt - 1, fileSize);
using (System.IO.Stream requestStream = httpRequest.GetRequestStreamAsync().Result)
{
requestStream.Write(temp, 0, cnt);
}
HttpWebResponse httpResponse;
try
{
httpResponse = (HttpWebResponse)httpRequest.GetResponse();
}
catch (WebException ex)
{
httpResponse = (HttpWebResponse)ex.Response;
}
if (httpResponse.StatusCode == HttpStatusCode.OK)
{ }
else if ((int)httpResponse.StatusCode != 308)
break;
bytesSent += cnt;
Console.WriteLine("Uploaded " + bytesSent.ToString());
}
if (bytesSent != uploadStream.Length)
{
return null;
}
// Try to retrieve the file from Google
FilesResource.ListRequest request = driveService.Files.List();
if (parents.Count > 0)
request.Q += "'" + parents[0] + "' in parents and ";
request.Q += "name = '" + destfilename + "'";
FileList result = request.Execute();
if (result.Files.Count > 0)
uploadedFile = result.Files[0];
}
catch (Exception ex)
{
Debug.WriteLine(ex.Message);
}
return uploadedFile;
}

Check whether a folder exists on FTP server before uploading to that folder

I've checked other posts on this topic, but I can't seem to figure out the fundamentals of checking whether or not a directory exists on an FTP server before trying to upload a file there.
With the following code I get an exception when trying to upload to a folder that already exists. I feel that it shouldn't be too hard to just use some kind of folder.Exists before creating the directory, but I can't get it to work. Any ideas?
Upload method as of now:
String id = Request.QueryString["ID"];
String path = Server.MapPath("~/temp/");
String filename = Path.GetFileName(fuPicture.PostedFile.FileName);
if (fuPicture.HasFile)
{
try
{
fuPicture.PostedFile.SaveAs(path + fuPicture.FileName);
}
catch (Exception ex)
{
lblFeedback.Text = "Fel vid uppladdning";
}
path += fuPicture.FileName;
String ftpServer = "ftp://xxx";
String userName = "xx";
String password = "xx";
FtpWebRequest request = (FtpWebRequest)WebRequest.Create(new Uri("ftp://xx/" + id));
// I want to implement an if-condition here
// whether or not the folder exists
request.Method = WebRequestMethods.Ftp.MakeDirectory;
request.Credentials = new NetworkCredential(userName, password);
using (var resp = (FtpWebResponse)request.GetResponse())
{
WebClient client = new WebClient();
client.Credentials = new NetworkCredential(userName, password);
client.UploadFile(ftpServer + "/" + id + "/" + new FileInfo(path).Name, "STOR", path);
resp.Close();
}
Try listing directory ListDirectory, if not found then create MakeDirectory
request.Method = WebRequestMethods.Ftp.ListDirectory;
request.Credentials = new NetworkCredential(userName, password);
try
{
using (request.GetResponse())
{
//continue
}
}
catch (WebException)
{
request.Method = WebRequestMethods.Ftp.MakeDirectory;
using (request.GetResponse())
{
//continue
}
}

Possible to temporarily store a file locally before sending to ftp server?

I've got an ASP control for file upload. When the user posts it, it's first locally stored on where I run the website and then I copy it to a remote ftp server.
However, is it possible to remove it from the local server once it's been copied to the ftp server? I'm thinking like storing it in a ~temp folder, but I can't get that to work. As of now I need to create a folder within my project called "temp". Any ideas? Here the method:
String id = Request.QueryString["ID"];
String path = Server.MapPath("~/temp/");
String filename = Path.GetFileName(fuPicture.PostedFile.FileName);
if (fuPicture.HasFile)
{
try
{
if (
fuPicture.PostedFile.ContentType == "image/jpeg" ||
fuPicture.PostedFile.ContentType == "image/png" ||
fuPicture.PostedFile.ContentType == "image/gif"
)
{
fuPicture.PostedFile.SaveAs(path + fuPicture.FileName);
}
else
{
lblFeedback.Text = "Not allowed file extension";
}
}
catch (Exception ex)
{
lblFeedback.Text = "Error when uploading";
}
path += fuPicture.FileName;
String ftpServer = "ftp://xxxx:xxxx";
String userName = "xx";
String password = "xx";
FtpWebRequest request =
(FtpWebRequest)WebRequest.Create(new Uri("ftp://xxxx:xxxx/" + id));
request.Method = WebRequestMethods.Ftp.MakeDirectory;
request.Credentials = new NetworkCredential(userName, password);
using (var resp = (FtpWebResponse)request.GetResponse())
{
WebClient client = new WebClient();
client.Credentials = new NetworkCredential(userName, password);
client.UploadFile(ftpServer + "/" + id + "/" +
new FileInfo(path).Name, "STOR", path);
}
You can call client.UploadData() to upload a byte array from memory, without involving your local disk at all.
Why you don't do a file.delete after the using statement?

Error while uploading a text file to FTP server C#

I am building a simple application that uploads a .txt file to a FTP server. I have done this before and i am using the same code as i used for the other application.
this is my code:
string localFilePath = #"\\fileprint\data\Groups\Operation\fileExports\dls\";
string archiveFilePath = #"\\fileprint\data\Groups\Operation\fileExports\dls\Archive\";
string logFilePath = #"C:\Users\lmy\Desktop\Logs";
string ftpServer = "ftp://server:21/home/out2233/tmp";
private string logFileName = "" + DateTime.Now.Year.ToString() + "-" + DateTime.Now.Month.ToString() + "-" + DateTime.Now.Day.ToString();
public void UploadFile()
{
try
{
string[] files = Directory.GetFiles(localFilePath);
foreach (string file in files)
{
string fileName = Path.GetFileName(file);
string modified = file.Remove(60, 6);
string modifiedFile = Path.GetFileName(modified);
FtpWebRequest ftpReq = (FtpWebRequest)FtpWebRequest.Create(new Uri(ftpServer + modifiedFile));
ftpReq.Method = WebRequestMethods.Ftp.UploadFile;
ftpReq.Method = WebRequestMethods.Ftp.ListDirectoryDetails;
ftpReq.UsePassive = true;
ftpReq.UseBinary = true;
ftpReq.KeepAlive = true;
ftpReq.Credentials = new NetworkCredential("out2233", "password");
ftpReq.EnableSsl = true;
FileInfo fileInfo = new FileInfo(localFilePath + #"\" + fileName);
FileStream fileStream = fileInfo.OpenRead();
byte[] fileContent = new byte[fileInfo.Length];
fileStream.Read(fileContent, 0, Convert.ToInt32(fileInfo.Length));
Stream writer = ftpReq.GetRequestStream();
writer.Write(fileContent, 0, fileContent.Length);
fileStream.Close();
writer.Close();
FtpWebResponse response = (FtpWebResponse)ftpReq.GetResponse();
AppendLogFile(response, "Uploaded Files: ", fileName);
MoveToArchive(file, archiveFilePath + fileName);
}
}
catch (Exception exception)
{
Console.WriteLine(exception.Message);
}
}
But it get this error:
exception = {"Cannot send a content-body with this verb-type."}
when the code reaches this line:
Stream writer = ftpReq.GetRequestStream();
I have googled this but i can only find ASP examples. I cant seem to find out what i am doing wrong here. Hope you guys can help me.
thanks!
Looks like, you're trying to list ftp directory content, with this line:
ftpReq.Method = WebRequestMethods.Ftp.ListDirectoryDetails;
(http://msdn.microsoft.com/en-us/library/system.net.webrequestmethods.ftp.listdirectorydetails%28v=vs.110%29.aspx)
Try removing it, leaving only this line:
ftpReq.Method = WebRequestMethods.Ftp.UploadFile;
http://msdn.microsoft.com/en-us/library/system.net.webrequestmethods.ftp.uploadfile%28v=vs.110%29.aspx

Categories