I'm writing a program that uses an ftp server with credentials. I'm trying to retrieve the directory list from the server but when I get to the line:
string line = reader.ReadLine();
the string that I get contains only : "Can't open \"host:/lib1\"."
If I try to get another line, the next exception is thrown: The remote server returned an error: (550) File unavailable (e.g., file not found, no access).
I know for sure (using another ftp application) that 'lib1' directory exists on the ftp server and my credentials (username and password) are correct.
Here is my code:
public class FTPClient
{
public string UserName { get; set; }
public string Password { get; set; }
public string IpAddress { get; set; }
public int Port { get; set; }
public FTPClient(string _userName, string _password, string _address, int _port)
{
UserName = _userName;
Password = _password;
IpAddress = _address;
Port = _port;
}
public void GetDirectoriesList(string _path)
{
FtpWebRequest request = (FtpWebRequest)WebRequest.Create(new Uri("ftp://" +
IpAddress + _path));
request.UseBinary = true;
request.Method = WebRequestMethods.Ftp.ListDirectory;
request.Credentials = new NetworkCredential(UserName, Password);
FtpWebResponse response = (FtpWebResponse)request.GetResponse();
Stream responseStream = response.GetResponseStream();
StreamReader reader = new StreamReader(responseStream);
string line = reader.ReadLine();
while (line!=null)
{
... //do something with line
line = reader.ReadLine();
}
...
reader.Close();
response.Close();
}
And I use it as follows:
FTPClient ftpClient = new FTPClient("user1", "pass1", "192.168.2.110", 21);
string dirList = ftpClient.GetDirectoriesList("/lib1");
Can anyone spot the problem?
My solution:
public string[] GetDirectory()
{
StringBuilder result = new StringBuilder();
FtpWebRequest requestDir = (FtpWebRequest)WebRequest.Create("ftp://urserverip/");
requestDir.Method = WebRequestMethods.Ftp.ListDirectory;
requestDir.Credentials = new NetworkCredential("username", "password");
FtpWebResponse responseDir = (FtpWebResponse)requestDir.GetResponse();
StreamReader readerDir = new StreamReader(responseDir.GetResponseStream());
string line = readerDir.ReadLine();
while (line != null)
{
result.Append(line);
result.Append("\n");
line = readerDir.ReadLine();
}
result.Remove(result.ToString().LastIndexOf('\n'), 1);
responseDir.Close();
return result.ToString().Split('\n');
}
Some refinements to Abdul Waheed's answer:
Added using blocks to clean up the FtpWebResponse and StreamReader objects;
Reduced string manipulation:
private static string[] GetDirectoryListing()
{
FtpWebRequest directoryListRequest = (FtpWebRequest)WebRequest.Create("ftp://urserverip/");
directoryListRequest.Method = WebRequestMethods.Ftp.ListDirectory;
directoryListRequest.Credentials = new NetworkCredential("username", "password");
using (FtpWebResponse directoryListResponse = (FtpWebResponse)directoryListRequest.GetResponse())
{
using (StreamReader directoryListResponseReader = new StreamReader(directoryListResponse.GetResponseStream()))
{
string responseString = directoryListResponseReader.ReadToEnd();
string[] results = responseString.Split(new string[] { "\r\n", "\n" }, StringSplitOptions.RemoveEmptyEntries);
return results;
}
}
}
Related
How can I send a file to an ftp with C# ?
The only informations I have are :
FTP IP address
FTP port
FTP user
I've try this :
public void SendFile(string filePath)
{
String user = "UserID";
String IPAddr = "XXX.XXX.XXX.XXX";
int port = 9999;
using (WebClient client = new WebClient())
{
client.Credentials = new NetworkCredential(user, null);
Uri address = new Uri("ftp://" + IPAddr);
byte[] rawResponse = client.UploadFile(address, "STOR", filePath);
string response = System.Text.Encoding.ASCII.GetString(rawResponse);
// check response
}
}
But it doesn't work and it doesn't use the port (Error "unable to connect").
You can specify port in the address if you use an FtpWebRequest this is what i use and it works with specific port.
internal class FTPManager
{
private const string FTPAddress = "ftp://www.example.com:9211/";
private const string Username = "Yummy";
private const string Password = "Nachos";
public byte[] DownloadFile(string relativePath)
{
var fileData = new byte[0];
try
{
// parse the path
relativePath = ParseRelativePath(relativePath);
using (var request = new WebClient())
{
request.Credentials = new NetworkCredential(Username, Password);
fileData = request.DownloadData(FTPAddress + relativePath);
}
}
catch { }
return fileData;
}
public bool DoesFileExist(string relativePath)
{
var fileExist = false;
var request = WebRequest.Create(FTPAddress + ParseRelativePath(relativePath));
request.Method = WebRequestMethods.Ftp.GetFileSize;
request.Credentials = new NetworkCredential(Username, Password);
try
{
using (var response = request.GetResponse())
{
fileExist = true;
}
}
catch { }
return fileExist;
}
// upload file and handle everything
public void UploadFile(string relativePath, byte[] fileBinary)
{
// parse the path
relativePath = ParseRelativePath(relativePath);
// create the folder before writing the file
CreateFolders(relativePath);
// delete the file
DeleteFile(relativePath);
// upload the file
SendFile(relativePath, fileBinary);
}
private void SendFile(string relativePath, byte[] fileBinary)
{
try
{
var request = (FtpWebRequest)WebRequest.Create(FTPAddress + relativePath);
request.Method = WebRequestMethods.Ftp.UploadFile;
request.Credentials = new NetworkCredential(Username, Password);
var stream = request.GetRequestStream();
var sourceStream = new MemoryStream(fileBinary);
var length = 1024;
var buffer = new byte[length];
var bytesRead = 0;
do
{
bytesRead = sourceStream.Read(buffer, 0, length);
stream.Write(buffer, 0, bytesRead);
} while (bytesRead != 0);
sourceStream.Close();
stream.Close();
}
catch
{
}
}
private void DeleteFile(string relativePath)
{
try
{
WebRequest ftpRequest = WebRequest.Create(FTPAddress + relativePath);
ftpRequest.Method = WebRequestMethods.Ftp.DeleteFile;
ftpRequest.Credentials = new NetworkCredential(Username, Password);
ftpRequest.GetResponse();
}
catch { }
}
// parse the relative path for strange slashes
private string ParseRelativePath(string relativePath)
{
// split to remove all slashes and duplicates
var split = relativePath.Split(new string[] { "\\", "/" }, StringSplitOptions.RemoveEmptyEntries);
// join the string back with valid slash
var result = String.Join("/", split);
return result;
}
// Check if the relative path need folders to be created
private void CreateFolders(string relativePath)
{
if (relativePath.IndexOf("/") > 0)
{
var folders = relativePath.Split(new[] { "/" }, StringSplitOptions.None).ToList();
var folderToCreate = FTPAddress.Substring(0, FTPAddress.Length - 1);
for (int i = 0; i < folders.Count - 1; i++)
{
folderToCreate += ("/" + folders[i]);
CreateFolder(folderToCreate);
}
}
}
// create a single folder on the FTP
private void CreateFolder(string folderPath)
{
try
{
WebRequest ftpRequest = WebRequest.Create(folderPath);
ftpRequest.Method = WebRequestMethods.Ftp.MakeDirectory;
ftpRequest.Credentials = new NetworkCredential(Username, Password);
ftpRequest.GetResponse();
}
catch { } // create folder will fail if it already exist
}
}
My problem was undefined port. To set the port, just do :
Uri address = new Uri($"ftp://{IPAddr}:{port}");
byte[] rawResponse = client.UploadFile(address, "STOR", filePath);
I've been spending all day trying to figure this one out, but with no luck.
Basically I have a bunch of files and folders, that I want to upload to a FTP server, and everything works great on localhost. But when I deploy it to azure, it stops working. In my head it makes no sense, and my initial thought was it had to do with a firewall, upload timeout or something else.
Do you see anything I am missing in my code, or do I need to do some configuration on azure or my ftp server ?
Edit: I forgot to include the error message:
"The underlying connection was closed: An unexpected error occurred on a receive
Problem Id:System.Net.WebException at simplecms.Models.FtpConn.UploadFile"
public class FtpConn
{
public string UploadCms(string address, string username, string password, string host, bool userftp, string guid)
{
CreateFileUID(guid);
string location;
if (userftp)
{
location = address + "/simplecms/";
host = host + "/simplecms/";
}
else
{
location = address + "/simplecms" + guid + "/";
host = host + "/simplecms" + guid + "/";
}
FtpWebRequest request = (FtpWebRequest)WebRequest.Create(location);
request.Credentials = new NetworkCredential(username, password);
//request.Timeout = -1;
request.UsePassive = true;
request.UseBinary = true;
request.Timeout = 1000000000;
request.KeepAlive = false;
request.ReadWriteTimeout = 1000000000;
request.Method = WebRequestMethods.Ftp.MakeDirectory;
using (var resp = (FtpWebResponse)request.GetResponse())
{
Console.WriteLine(resp.StatusCode);
}
string cmsFolder = "wwwroot/dist/";
string[] cmsFiles = Directory.GetFiles(cmsFolder);
foreach (string file in cmsFiles)
{
string path = Path.GetFullPath(file);
string name = Path.GetFileName(file);
UploadFile(username, password, location, path, name);
}
string[] staticFiles = Directory.GetDirectories(cmsFolder);
string[] subs = Directory.GetDirectories(cmsFolder + "static/");
foreach (string file in staticFiles)
{
CreateDirectory(username, password, location + "/" + Path.GetFileName(file));
}
foreach (string folder in subs)
{
CreateDirectory(username, password, location + "/static/" + Path.GetFileName(folder));
foreach (string subfile in Directory.GetFiles(folder))
{
string path = Path.GetFullPath(subfile);
string name = Path.GetFileName(subfile);
UploadFile(username, password, location + "/static/" + Path.GetFileName(folder) + "/" + Path.GetFileName(subfile), path, "");
}
}
return host;
}
private void UploadFile(string username, string password, string location, string filePath, string fileName)
{
FtpWebRequest request = (FtpWebRequest)WebRequest.Create(location + fileName);
request.Credentials = new NetworkCredential(username, password);
//request.Timeout = -1;
request.UsePassive = true;
request.UseBinary = true;
request.Timeout = 1000000000;
request.KeepAlive = false;
request.ReadWriteTimeout = 1000000000;
request.Method = WebRequestMethods.Ftp.UploadFile;
FileStream stream = File.OpenRead(filePath);
byte[] buffer = new byte[stream.Length];
stream.Read(buffer, 0, buffer.Length);
stream.Close();
Stream reqStream = request.GetRequestStream();
reqStream.Write(buffer, 0, buffer.Length);
reqStream.Close();
}
private void CreateDirectory(string username, string password, string newDirectory)
{
try
{
FtpWebRequest ftpRequest = (FtpWebRequest)WebRequest.Create(newDirectory);
ftpRequest.Credentials = new NetworkCredential(username, password);
//ftpRequest.Timeout = -1;
ftpRequest.UseBinary = true;
ftpRequest.UsePassive = true;
ftpRequest.KeepAlive = false;
ftpRequest.Method = WebRequestMethods.Ftp.MakeDirectory;
FtpWebResponse ftpResponse = (FtpWebResponse)ftpRequest.GetResponse();
ftpResponse.Close();
ftpRequest = null;
}
catch (Exception ex) { Console.WriteLine(ex); }
return;
}
private void CreateFileUID(string uid)
{
string folderName = "wwwroot/dist/";
string[] txtList = Directory.GetFiles(folderName, "*.txt");
foreach (string f in txtList)
{
File.Delete(f);
}
string fileName = "uid.txt";
string pathString = Path.Combine(folderName, fileName);
using (FileStream fs = File.Create(pathString))
{
byte[] SimpleCmsUID = new UTF8Encoding(true).GetBytes(uid);
fs.Write(SimpleCmsUID, 0, SimpleCmsUID.Length);
}
}
}
I am trying to download a file from one FTP server, and then upload it to a different FTP. I only figured out how to upload local files and download XML via FTP so far.
Here is my method to upload local file to FTP:
private void UploadLocalFile(string sourceFileLocation, string targetFileName)
{
try
{
string ftpServerIP = "ftp://testing.com/ContentManagementSystem/"+ Company +"/Prod";
string ftpUserID = Username;
string ftpPassword = Password;
string filename = "ftp://" + ftpServerIP + "/" + targetFileName;
FtpWebRequest ftpReq = (FtpWebRequest)WebRequest.Create(filename);
ftpReq.UseBinary = true;
ftpReq.Method = WebRequestMethods.Ftp.UploadFile;
ftpReq.Credentials = new NetworkCredential(ftpUserID, ftpPassword);
ftpReq.Proxy = null;
byte[] b = File.ReadAllBytes(sourceFileLocation);
ftpReq.ContentLength = b.Length;
using (Stream s = ftpReq.GetRequestStream())
{
s.Write(b, 0, b.Length);
}
}
catch (WebException ex)
{
String status = ((FtpWebResponse)ex.Response).StatusDescription;
Console.WriteLine(status);
}
}
And here is my method for downloading XML from FTP:
private static XmlDocument DownloadFtpXml(string uri, int retryLimit)
{
var returnDocument = new XmlDocument();
try
{
FtpWebRequest request = (FtpWebRequest)WebRequest.Create(uri);
request.Method = WebRequestMethods.Ftp.DownloadFile;
request.Credentials = new NetworkCredential(Username, Password);
request.UsePassive = true;
request.Proxy = new WebProxy();
FtpWebResponse response = (FtpWebResponse)request.GetResponse();
using (Stream responseStream = response.GetResponseStream())
{
returnDocument.Load(responseStream);
}
}
catch (WebException ex)
{
if (ex.Response != null)
{
FtpWebResponse response = (FtpWebResponse)ex.Response;
if (response.StatusCode == FtpStatusCode.ActionNotTakenFileUnavailable)
{
}
}
}
return returnDocument;
}
I'm unsure exactly how to do it, but I'm trying to create a method that will download something (content will be a video or image) from one FTP and then turn around and upload what I've just downloaded (that I'll have held in memory) to a different FTP.
Please help!
You were so close! Use a stream to convert your download into a byte array for upload.
I recently made a program to do just this! This will currently copy all files from one FTP directory to another so long as there is not a file in the target directory with the same name. It would be easy to change if you only wanted to copy one file, just use the copyFile, toByteArray and upload functions:
using System;
using System.Collections.Generic;
using System.IO;
using System.Net;
namespace Copy_From_FTP
{
class Program
{
public static void Main(string[] args)
{
List<FileName> sourceFileList = new List<FileName>();
List<FileName> targetFileList = new List<FileName>();
//string targetURI = ftp://www.target.com
//string targetUser = userName
//string targetPass = passWord
//string sourceURI = ftp://www.source.com
//string sourceUser = userName
//string sourcePass = passWord
getFileLists(sourceURI, sourceUser, sourcePass, sourceFileList, targetURI, targetUser, targetPass, targetFileList);
Console.WriteLine(sourceFileList.Count + " files found!");
CheckLists(sourceFileList, targetFileList);
targetFileList.Sort();
Console.WriteLine(sourceFileList.Count + " unique files on sourceURI"+Environment.NewLine+"Attempting to move them.");
foreach(var file in sourceFileList)
{
try
{
CopyFile(file.fName, sourceURI, sourceUser, sourcePass, targetURI, targetUser, targetPass);
}
catch
{
Console.WriteLine("There was move error with : "+file.fName);
}
}
}
public class FileName : IComparable<FileName>
{
public string fName { get; set; }
public int CompareTo(FileName other)
{
return fName.CompareTo(other.fName);
}
}
public static void CheckLists(List<FileName> sourceFileList, List<FileName> targetFileList)
{
for (int i = 0; i < sourceFileList.Count;i++ )
{
if (targetFileList.BinarySearch(sourceFileList[i]) > 0)
{
sourceFileList.RemoveAt(i);
i--;
}
}
}
public static void getFileLists(string sourceURI, string sourceUser, string sourcePass, List<FileName> sourceFileList,string targetURI, string targetUser, string targetPass, List<FileName> targetFileList)
{
string line = "";
/////////Source FileList
FtpWebRequest sourceRequest;
sourceRequest = (FtpWebRequest)WebRequest.Create(sourceURI);
sourceRequest.Credentials = new NetworkCredential(sourceUser, sourcePass);
sourceRequest.Method = WebRequestMethods.Ftp.ListDirectory;
sourceRequest.UseBinary = true;
sourceRequest.KeepAlive = false;
sourceRequest.Timeout = -1;
sourceRequest.UsePassive = true;
FtpWebResponse sourceRespone = (FtpWebResponse)sourceRequest.GetResponse();
//Creates a list(fileList) of the file names
using (Stream responseStream = sourceRespone.GetResponseStream())
{
using (StreamReader reader = new StreamReader(responseStream))
{
line = reader.ReadLine();
while (line != null)
{
var fileName = new FileName
{
fName = line
};
sourceFileList.Add(fileName);
line = reader.ReadLine();
}
}
}
/////////////Target FileList
FtpWebRequest targetRequest;
targetRequest = (FtpWebRequest)WebRequest.Create(targetURI);
targetRequest.Credentials = new NetworkCredential(targetUser, targetPass);
targetRequest.Method = WebRequestMethods.Ftp.ListDirectory;
targetRequest.UseBinary = true;
targetRequest.KeepAlive = false;
targetRequest.Timeout = -1;
targetRequest.UsePassive = true;
FtpWebResponse targetResponse = (FtpWebResponse)targetRequest.GetResponse();
//Creates a list(fileList) of the file names
using (Stream responseStream = targetResponse.GetResponseStream())
{
using (StreamReader reader = new StreamReader(responseStream))
{
line = reader.ReadLine();
while (line != null)
{
var fileName = new FileName
{
fName = line
};
targetFileList.Add(fileName);
line = reader.ReadLine();
}
}
}
}
public static void CopyFile(string fileName, string sourceURI, string sourceUser, string sourcePass,string targetURI, string targetUser, string targetPass )
{
try
{
FtpWebRequest request = (FtpWebRequest)WebRequest.Create(sourceURI + fileName);
request.Method = WebRequestMethods.Ftp.DownloadFile;
request.Credentials = new NetworkCredential(sourceUser, sourcePass);
FtpWebResponse response = (FtpWebResponse)request.GetResponse();
Stream responseStream = response.GetResponseStream();
Upload(fileName, ToByteArray(responseStream),targetURI,targetUser, targetPass);
responseStream.Close();
}
catch
{
Console.WriteLine("There was an error with :" + fileName);
}
}
public static Byte[] ToByteArray(Stream stream)
{
MemoryStream ms = new MemoryStream();
byte[] chunk = new byte[4096];
int bytesRead;
while ((bytesRead = stream.Read(chunk, 0, chunk.Length)) > 0)
{
ms.Write(chunk, 0, bytesRead);
}
return ms.ToArray();
}
public static bool Upload(string FileName, byte[] Image, string targetURI,string targetUser, string targetPass)
{
try
{
FtpWebRequest clsRequest = (FtpWebRequest)WebRequest.Create(targetURI+FileName);
clsRequest.Credentials = new NetworkCredential(targetUser, targetPass);
clsRequest.Method = WebRequestMethods.Ftp.UploadFile;
Stream clsStream = clsRequest.GetRequestStream();
clsStream.Write(Image, 0, Image.Length);
clsStream.Close();
clsStream.Dispose();
return true;
}
catch
{
return false;
}
}
}
}
You may run into issues if you are using things that have special encoding, like text documents. That can be changed by the way the upload function is used. If you're doing text files, use:
System.Text.Encoding.UTF8.GetBytes(responseStream)
instead of
ToByteArray(responseStream)
You could do a simple extension check of your file before executing the upload.
I am trying to get full list of files, directories and sub-directories on tree view using StreamReader. The problem is it took too long and throws *"Operation time out exception" and shows only one level.
Here is my code
public void getServerSubfolder(TreeNode tv, string parentNode) {
string ptNode;
List<string> files = new List<string> ();
try {
FtpWebRequest request = (FtpWebRequest) WebRequest.
Create(parentNode);
request.Method = WebRequestMethods.Ftp.ListDirectoryDetails;
request.Credentials = new NetworkCredential(this.userName, this.Password);
request.UseBinary = true;
request.UsePassive = true;
request.Timeout = 10000;
request.ReadWriteTimeout = 10000;
request.KeepAlive = false;
FtpWebResponse response = (FtpWebResponse) request.GetResponse();
Stream responseStream = response.GetResponseStream();
StreamReader reader = new StreamReader(responseStream);
string fileList;
string[] fileName;
//MessageBox.Show(reader.ReadToEnd().ToString());
while (!reader.EndOfStream) {
fileList = reader.ReadLine();
fileName = fileList.Split(' ');
if (fileName[0] == "drwxr-xr-x") {
// if it is directory
TreeNode tnS = new TreeNode(fileName[fileName.Length - 1]);
tv.Nodes.Add(tnS);
ptNode = parentNode + "/" + fileName[fileName.Length - 1] + "/";
getServerSubfolder(tnS, ptNode);
} else files.Add(fileName[fileName.Length - 1]);
}
reader.Close();
response.Close();
} catch (Exception ex) {
MessageBox.Show("Sub--here " + ex.Message + "----" + ex.StackTrace);
}
}
You have to read (and cache) whole listing before recursing into subdirectories, otherwise the top-level request will timeout before you complete subdirectories listing.
You can keep using ReadLine, no need to use ReadToEnd and separate the lines yourself.
void ListFtpDirectory(
string url, string rootPath, NetworkCredential credentials, List<string> list)
{
FtpWebRequest listRequest = (FtpWebRequest)WebRequest.Create(url + rootPath);
listRequest.Method = WebRequestMethods.Ftp.ListDirectoryDetails;
listRequest.Credentials = credentials;
List<string> lines = new List<string>();
using (FtpWebResponse listResponse = (FtpWebResponse)listRequest.GetResponse())
using (Stream listStream = listResponse.GetResponseStream())
using (StreamReader listReader = new StreamReader(listStream))
{
while (!listReader.EndOfStream)
{
lines.Add(listReader.ReadLine());
}
}
foreach (string line in lines)
{
string[] tokens =
line.Split(new[] { ' ' }, 9, StringSplitOptions.RemoveEmptyEntries);
string name = tokens[8];
string permissions = tokens[0];
string filePath = rootPath + name;
if (permissions[0] == 'd')
{
ListFtpDirectory(url, filePath + "/", credentials, list);
}
else
{
list.Add(filePath);
}
}
}
Use the function like:
List<string> list = new List<string>();
NetworkCredential credentials = new NetworkCredential("user", "mypassword");
string url = "ftp://ftp.example.com/";
ListFtpDirectory(url, "", credentials, list);
A disadvantage of the above approach is that it has to parse server-specific listing to retrieve information about files and folders. The code above expects a common *nix-style listing. But many servers use a different format.
The FtpWebRequest unfortunately does not support the MLSD command, which is the only portable way to retrieve directory listing with file attributes in FTP protocol.
If you want to avoid troubles with parsing the server-specific directory listing formats, use a 3rd party library that supports the MLSD command and/or parsing various LIST listing formats; and recursive downloads.
For example with WinSCP .NET assembly you can list whole directory with a single call to the Session.EnumerateRemoteFiles:
// Setup session options
SessionOptions sessionOptions = new SessionOptions
{
Protocol = Protocol.Ftp,
HostName = "ftp.example.com",
UserName = "user",
Password = "mypassword",
};
using (Session session = new Session())
{
// Connect
session.Open(sessionOptions);
// List files
IEnumerable<string> list =
session.EnumerateRemoteFiles("/", null, EnumerationOptions.AllDirectories).
Select(fileInfo => fileInfo.FullName);
}
Internally, WinSCP uses the MLSD command, if supported by the server. If not, it uses the LIST command and supports dozens of different listing formats.
(I'm the author of WinSCP)
I'm doing similar things, but instead of using StreamReader.ReadLine() for each one, I get it all at once with StreamReader.ReadToEnd(). You don't need ReadLine() to just get a list of directories. Below is my entire code (Entire howto is explained in this tutorial):
FtpWebRequest request=(FtpWebRequest)FtpWebRequest.Create(path);
request.Method=WebRequestMethods.Ftp.ListDirectoryDetails;
List<ftpinfo> files=new List<ftpinfo>();
//request.Proxy = System.Net.WebProxy.GetDefaultProxy();
//request.Proxy.Credentials = CredentialCache.DefaultNetworkCredentials;
request.Credentials = new NetworkCredential(_username, _password);
Stream rs=(Stream)request.GetResponse().GetResponseStream();
OnStatusChange("CONNECTED: " + path, 0, 0);
StreamReader sr = new StreamReader(rs);
string strList = sr.ReadToEnd();
string[] lines=null;
if (strList.Contains("\r\n"))
{
lines=strList.Split(new string[] {"\r\n"},StringSplitOptions.None);
}
else if (strList.Contains("\n"))
{
lines=strList.Split(new string[] {"\n"},StringSplitOptions.None);
}
//now decode this string array
if (lines==null || lines.Length == 0)
return null;
foreach(string line in lines)
{
if (line.Length==0)
continue;
//parse line
Match m= GetMatchingRegex(line);
if (m==null) {
//failed
throw new ApplicationException("Unable to parse line: " + line);
}
ftpinfo item=new ftpinfo();
item.filename = m.Groups["name"].Value.Trim('\r');
item.path = path;
item.size = Convert.ToInt64(m.Groups["size"].Value);
item.permission = m.Groups["permission"].Value;
string _dir = m.Groups["dir"].Value;
if(_dir.Length>0 && _dir != "-")
{
item.fileType = directoryEntryTypes.directory;
}
else
{
item.fileType = directoryEntryTypes.file;
}
try
{
item.fileDateTime = DateTime.Parse(m.Groups["timestamp"].Value);
}
catch
{
item.fileDateTime = DateTime.MinValue; //null;
}
files.Add(item);
}
return files;
Hi all i want to access azure tables entities from windows phone either using rest API or using Odata.
I have written a code but that this giving me NULL response. Every time i want to access a table entity i call GetEntity function. Below is the code that i am using.
Please if anybody know what wrong in this code or any help reply asap.
//////////// GetEntity Function.//////////
private void GetEntity(String tableName, String partitionKey, String rowKey)
{
String requestMethod = "GET";
String urlPath = String.Format("{0}(PartitionKey='{1}',RowKey='{2}')", tableName, partitionKey, rowKey);
String dateInRfc1123Format = DateTime.Now.ToString("R", System.Globalization.CultureInfo.InvariantCulture);
String canonicalizedResource = String.Format("/{0}/{1}", AzureStorageConstants.Account, urlPath);
String stringToSign = String.Format(
"{0}\n\n\n{1}\n{2}",
requestMethod,
dateInRfc1123Format,
canonicalizedResource);
String authorizationHeader = CreateAuthorizationHeader(stringToSign);
HttpWebResponse response;
Uri uri = new Uri(AzureStorageConstants.TableEndPoint + urlPath);
HttpWebRequest request = (HttpWebRequest)HttpWebRequest.Create(uri);
request = (HttpWebRequest)WebRequest.Create(uri);
request.Method = requestMethod;
request.Headers[HttpRequestHeader.ProxyAuthorization] = null;
request.Headers["Address"] = uri.ToString();
request.Headers["Method"] = requestMethod;
request.Headers["x-ms-date"]= DateTime.Now.ToString("R", System.Globalization.CultureInfo.InvariantCulture);
request.Headers["x-ms-version"]= "2011-08-18";
request.Headers["Authorization"] = authorizationHeader;
request.Headers["Accept-Charset"] = "UTF-8";
request.Headers["ContentType"] = "application/atom+xml,application/xml";
request.ContentType = "application/atom+xml,application/xml";
request.Headers["DataServiceVersion"] = "1.0;NetFx";
request.Headers["MaxDataServiceVersion"] = "1.0;NetFx";
using (response = GetResponse(request))
{
Stream dataStream = response.GetResponseStream();
using (StreamReader reader = new StreamReader(dataStream))
{
String responseFromServer = reader.ReadToEnd();
}
}
}
// GetResponse Function.
public HttpWebResponse GetResponse(HttpWebRequest request)
{
var dataReady = new AutoResetEvent(false);
HttpWebResponse response = null;
var callback = new AsyncCallback(delegate(IAsyncResult asynchronousResult)
{
response = (HttpWebResponse)request.EndGetResponse(asynchronousResult);
dataReady.Set();
});
request.BeginGetResponse(callback, request);
return response;
}
////// CreateAuthorization Function.///
private String CreateAuthorizationHeader(String canonicalizedString)
{
String signature = string.Empty;
using (HMACSHA256 hmacSha256 = new HMACSHA256(Convert.FromBase64String(AzureStorageConstants.Key)))
{
Byte[] dataToHmac = System.Text.Encoding.UTF8.GetBytes(canonicalizedString);
signature = Convert.ToBase64String(hmacSha256.ComputeHash(dataToHmac));
}
String authorizationHeader = String.Format(
CultureInfo.InvariantCulture,
"{0} {1}:{2}",
AzureStorageConstants.SharedKeyAuthorizationScheme,
AzureStorageConstants.Account,
signature);
return authorizationHeader;
}
////////AzureStorageConstants.
public static class AzureStorageConstants
{
private static String TableAccount = "datablobs";
private static String cloudEndPointFormat = "http://" + TableAccount + ".table.core.windows.net/";
private static String cloudKey = "Primary Access Key";// Here actual key is written.
private static string AzureStorage_SharedKeyAuthorizationScheme = "SharedKey";
public static String Account
{
get { return TableAccount; }
}
public static string SharedKeyAuthorizationScheme
{
get { return AzureStorage_SharedKeyAuthorizationScheme; }
}
public static string Key
{
get { return cloudKey; }
}
public static String TableEndPoint
{
get { return cloudEndPointFormat; }
}
}
for solution refer to below linked i have posted the solution there http://social.msdn.microsoft.com/Forums/en-US/windowsazureconnectivity/thread/84415c36-9475-4af0-9f52-c534f5681432
I checked you code and found the GetEntity() function does have some problem with regard to creating signature to access the Windows Azure Table Storage, so I hack together the following code which does work. You can just replace your GetEntity() and add two other function included in the code below to work signature process properly.
private string GetEntity(String tableName, String partitionKey, String rowKey)
{
string result = "";
String requestMethod = "GET";
String urlPath = String.Format("{0}(PartitionKey='{1}',RowKey='{2}')",tableName, partitionKey, rowKey);
DateTime now = DateTime.UtcNow;
HttpWebResponse response;
string uri = AzureStorageConstants.TableEndPoint + urlPath;
HttpWebRequest request = (HttpWebRequest)HttpWebRequest.Create(uri);
request.Method = requestMethod;
request.ContentLength = 0;
request.Headers.Add("x-ms-date", now.ToString("R", System.Globalization.CultureInfo.InvariantCulture));
request.Headers.Add("x-ms-version", "2009-09-19");
request.ContentType = "application/atom+xml";
request.Headers.Add("DataServiceVersion", "1.0;NetFx");
request.Headers.Add("MaxDataServiceVersion", "1.0;NetFx");
request.Headers.Add("If-Match", "*");
request.Headers.Add("Accept-Charset", "UTF-8");
request.Headers.Add("Authorization", AuthorizationHeader(requestMethod, now, request));
request.Accept = "application/atom+xml";
using (response = request.GetResponse() as HttpWebResponse)
{
Stream dataStream = response.GetResponseStream();
using (StreamReader reader = new StreamReader(dataStream))
{
result = reader.ReadToEnd();
}
}
return result;
}
public string AuthorizationHeader(string method, DateTime now, HttpWebRequest request)
{
string MessageSignature;
MessageSignature = String.Format("{0}\n\n{1}\n{2}\n{3}",
method,
"application/atom+xml",
now.ToString("R", System.Globalization.CultureInfo.InvariantCulture),
GetCanonicalizedResource(request.RequestUri, AzureStorageConstants.Account)
);
byte[] SignatureBytes = System.Text.Encoding.UTF8.GetBytes(MessageSignature);
System.Security.Cryptography.HMACSHA256 SHA256 = new System.Security.Cryptography.HMACSHA256(Convert.FromBase64String(AzureStorageConstants.Key));
String AuthorizationHeader = "SharedKey " + AzureStorageConstants.Account + ":" + Convert.ToBase64String(SHA256.ComputeHash(SignatureBytes));
return AuthorizationHeader;
}
public string GetCanonicalizedResource(Uri address, string accountName)
{
StringBuilder str = new StringBuilder();
StringBuilder builder = new StringBuilder("/");
builder.Append(accountName);
builder.Append(address.AbsolutePath);
str.Append(builder.ToString());
NameValueCollection values2 = new NameValueCollection();
NameValueCollection values = HttpUtility.ParseQueryString(address.Query);
foreach (string str2 in values.Keys)
{
ArrayList list = new ArrayList(values.GetValues(str2));
list.Sort();
StringBuilder builder2 = new StringBuilder();
foreach (object obj2 in list)
{
if (builder2.Length > 0)
{
builder2.Append(",");
}
builder2.Append(obj2.ToString());
}
values2.Add((str2 == null) ? str2 : str2.ToLowerInvariant(), builder2.ToString());
}
ArrayList list2 = new ArrayList(values2.AllKeys);
list2.Sort();
foreach (string str3 in list2)
{
StringBuilder builder3 = new StringBuilder(string.Empty);
builder3.Append(str3);
builder3.Append(":");
builder3.Append(values2[str3]);
str.Append("\n");
str.Append(builder3.ToString());
}
return str.ToString();
}
To fix your Signature related problem, I took the code from Storage_REST_CS sample which has superb implementation of accessing Windows Azure (Blob, Table & Queue) Storage over REST interface.