I have this method:
public async Task CopyFileToOurFTP(FtpCredentialModel model)
{
foreach (var fileName in model.FileNames)
{
try
{
string uri = model.Host + "/" + fileName;
Uri serverUri = new Uri(uri);
if (serverUri.Scheme != Uri.UriSchemeFtp)
{
return;
}
FtpWebRequest reqFTP = (FtpWebRequest)FtpWebRequest.Create(new Uri(uri));
reqFTP.Credentials = new NetworkCredential(model.Username, model.Password);
reqFTP.KeepAlive = false;
reqFTP.Method = WebRequestMethods.Ftp.DownloadFile;
FtpWebResponse response = (FtpWebResponse)reqFTP.GetResponse();
Stream responseStream = response.GetResponseStream();
FileStream writeStream = new FileStream("D:\\Dev" + "\\" + fileName, FileMode.Create);
int Length = 2048;
Byte[] buffer = new Byte[Length];
int bytesRead = await responseStream.ReadAsync(buffer, 0, Length);
while (bytesRead > 0)
{
writeStream.Write(buffer, 0, bytesRead);
bytesRead = await responseStream.ReadAsync(buffer, 0, Length);
}
writeStream.Close();
response.Close();
}
catch (WebException wEx)
{
_logger.Error($"{wEx.Message} >>> {wEx.StackTrace}");
}
catch (Exception ex)
{
_logger.Error($"{ex.Message} >>> {ex.StackTrace}");
}
}
}
My credential model class:
public class FtpCredentialModel
{
public string Host { get; set; }
public string FileMask { get; set; }
public List<string> FileNames { get; set; }
public string Username { get; set; }
public string Password { get; set; }
public FtpCredentialModel()
{
FileNames = new List<string>();
}
}
and json
{
"host": "ftp://ftp.com:21",
"fileMask": ".txt",
"fileNames": [
"test.txt",
"test_01.txt"
],
"username": "guest",
"password": "guest"
}
and I want make it async and return count of download files.
As far as I understand, I need to make FtpWebResponse asynchronous, but I don't understand how. Who can help me?
The FtpWebRequest class implements both GetResponseAsync and GetRequestStreamAsync which you can use to make your request async
FtpWebRequest reqFTP;
reqFTP = (FtpWebRequest)FtpWebRequest.Create(new Uri(uri));
reqFTP.Credentials = new NetworkCredential(model.Username, model.Password);
reqFTP.KeepAlive = false;
reqFTP.Method = WebRequestMethods.Ftp.DownloadFile;
FtpWebResponse response = await reqFTP.GetResponseAsync();
Stream responseStream = await response.GetRequestStreamAsync();
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);
The Below is my program in c# to connect to Ftp Server.While Uploading the .txt file from local system to ftp server i am getting the error "The remote server returned an error: (404) Not Found". Please help me on this so that I can resolve my error.
The below is the free ftp server what i am using to up-load the file with username and password
Location: http://demo.wftpserver.com/
Username: demo-user
Password: demo-user
public static void Main(string[] args)
{
Ftp testConnec = new Ftp();
testConnec.CheckFTPConnection("http://demo.wftpserver.com/");
testConnec.uploadFileToFTP(#"C:\TestFtpConnection", "test_new.txt", "upload", "http://demo.wftpserver.com");
}
public class Ftp
{
#region checkFTPConnection
public bool CheckFTPConnection(string URL)
{
// Uri myUri = new Uri("http://demo.wftpserver.com/");
Uri myUri = new Uri(URL);
// WebRequest myRequest = WebRequest.Create(myUri);
//FtpWebRequest myRequest = (FtpWebRequest)WebRequest.Create(myUri);
WebRequest myRequest = WebRequest.Create(myUri);
myRequest.Credentials = new NetworkCredential("demo-admin", "demo-admin");
myRequest.Method = WebRequestMethods.Ftp.GetDateTimestamp;
try
{
WebResponse myResponse = myRequest.GetResponse();
long i = myResponse.ContentLength;
return true;
myResponse.Close();
}
// catch (Exception ex)
catch (WebException e)
{
if (e.Status == WebExceptionStatus.ProtocolError)
{
return true;
}
else
{
return false;
}
}
}
#endregion
public bool uploadFileToFTP(string LocalFilePath, string FileName, string Directory,string URL)
{
try
{
Uri myUri = new Uri(URL);
WebRequest myRequest = WebRequest.Create(myUri);
WebRequest ftpClient = WebRequest.Create(myUri + Directory + "/" + FileName);
ftpClient.Credentials = new NetworkCredential("demo-admin", "demo-admin");
ftpClient.Method = System.Net.WebRequestMethods.Ftp.UploadFile;
System.IO.FileInfo fi = new System.IO.FileInfo(LocalFilePath + "/" + FileName);
ftpClient.ContentLength = fi.Length;
byte[] buffer = new byte[4097];
int bytes = 0;
int total_bytes = (int)fi.Length;
System.IO.FileStream fs = fi.OpenRead();
System.IO.Stream rs = ftpClient.GetRequestStream();
while (total_bytes > 0)
{
bytes = fs.Read(buffer, 0, buffer.Length);
rs.Write(buffer, 0, bytes);
total_bytes = total_bytes - bytes;
}
//fs.Flush();
fs.Close();
rs.Close();
WebResponse uploadResponse = ftpClient.GetResponse();
// string value = uploadResponse.StatusDescription;
uploadResponse.Close();
return true;
}
catch (Exception ex)
{
return false;
}
}
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 have been fighting with this upload problem for a couple of days and searched the forum for a good answer but have not seen it yet. I am using asp.net and I am currently receiving a timeout when I try to post a file to upload. I have taken the MultipartWebRequest class from the V1 C# Api and changed it(i believe to be correctly but it may be my problem) to work with my program.
public sealed class MultipartWebRequest
{
public string AcceptCharset { get; set; }
public string AcceptEncoding { get; set; }
public string Url { get; set; }
public string Boundary { get; set; }
public string ApiKey { get; private set; }
public string Token { get; private set; }
public MultipartWebRequest(string apiKey, string token, string submitUrl,string acceptCharset = "ISO-8859-1", string acceptEncoding = "gzip,deflate" )
{
Boundary = "----------------" + DateTime.Now.Ticks;
ApiKey = apiKey;
Token = token;
Url = submitUrl;
AcceptCharset = acceptCharset;
AcceptEncoding = acceptEncoding;
}
public string SubmitFiles(
//string[] filePaths,
UploadableFile[] files,
bool isShared,
string message,
string[] emailsToNotify,
string folderId)
{
byte[] buffer;
using (MemoryStream resultStream = new MemoryStream())
{
if (files != null)
{
buffer = AssembleFilesBlock(files, folderId);
resultStream.Write(buffer, 0, buffer.Length);
}
if (!string.IsNullOrEmpty(message))
{
buffer = AssembleMessageBlock(message);
resultStream.Write(buffer, 0, buffer.Length);
}
//buffer = AssembleSharedBlock(isShared);
//resultStream.Write(buffer, 0, buffer.Length);
if (emailsToNotify != null)
{
buffer = AssembleEmailsBlock(emailsToNotify);
resultStream.Write(buffer, 0, buffer.Length);
}
buffer = GetFormattedBoundary(true);
resultStream.Write(buffer, 0, buffer.Length);
resultStream.Flush();
buffer = resultStream.ToArray();
}
HttpWebRequest myRequest = CreateRequest(buffer.Length);
using (Stream stream = myRequest.GetRequestStream())
{
stream.Write(buffer, 0, buffer.Length);
stream.Close();
}
string response;
using (HttpWebResponse myHttpWebResponse = (HttpWebResponse)myRequest.GetResponse())
using (Stream responseStream = myHttpWebResponse.GetResponseStream())
{
StreamReader reader = new StreamReader(responseStream);
response = reader.ReadToEnd();
responseStream.Close();
}
myHttpWebResponse.Close();
return response;
}
private byte[] GetFormattedBoundary(bool isEndBoundary)
{
string template = isEndBoundary ? "--{0}--{1}" : "--{0}{1}";
return Encoding.ASCII.GetBytes(string.Format(template, Boundary, Environment.NewLine));
}
private byte[] AssembleEmailsBlock(string[] emailsToNotify)
{
return new byte[1];
}
private byte[] AssembleSharedBlock(bool isShared)
{
byte[] boundaryContent = GetFormattedBoundary(false);
return new byte[1];
}
private byte[] AssembleMessageBlock(string message)
{
return new byte[1];
}
private byte[] AssembleFilesBlock(UploadableFile[] files, string folderId)
{
byte[] buffer = null;
using (MemoryStream resultStream = new MemoryStream())
{
for (int i = 0; i < files.Length ; i++)
{
buffer = GetFormattedBoundary(false);
resultStream.Write(buffer, 0, buffer.Length);
buffer = AssembleFile(files[i]);
resultStream.Write(buffer, 0, buffer.Length);
}
buffer = GetFormattedBoundary(false);
resultStream.Write(buffer, 0, buffer.Length);
buffer = AssembleStringValue("folder_id", folderId);
resultStream.Write(buffer, 0, buffer.Length);
resultStream.Flush();
buffer = resultStream.ToArray();
}
return buffer;
}
private byte[] AssembleStringValue(string paramName, string paramValue)
{
StringBuilder result = new StringBuilder();
result.AppendFormat("Content-Disposition: form-data; name=\"{0}\"{1}", paramName, Environment.NewLine);
result.AppendLine();
result.AppendLine(paramValue);
return Encoding.ASCII.GetBytes(result.ToString());
}
private byte[] AssembleFile(UploadableFile file)
{
byte[] buffer;
using (MemoryStream resultStream = new MemoryStream())
{
buffer = Encoding.ASCII.GetBytes(string.Format("Content-Disposition: form-data; name=\"{0}\"; filename=\"{1}\"{2}", Guid.NewGuid(), file.FileName, Environment.NewLine));
resultStream.Write(buffer, 0, buffer.Length);
buffer = Encoding.ASCII.GetBytes("Content-Type: application/octet-stream" + Environment.NewLine + Environment.NewLine);
resultStream.Write(buffer, 0, buffer.Length);
buffer = Encoding.ASCII.GetBytes(file.FileContents);
//buffer = File.ReadAllBytes(filePath);
resultStream.Write(buffer, 0, buffer.Length);
buffer = Encoding.ASCII.GetBytes(Environment.NewLine);
resultStream.Write(buffer, 0, buffer.Length);
resultStream.Flush();
buffer = resultStream.ToArray();
}
return buffer;
}
private HttpWebRequest CreateRequest(long contentLength)
{
HttpWebRequest webRequest = (HttpWebRequest)WebRequest.Create(Url);
webRequest.Method = "POST";
//webRequest.AllowWriteStreamBuffering = true;
webRequest.ContentType = string.Concat("multipart/form-data;boundary=", Boundary);
webRequest.Headers.Add("Authorization", "BoxAuth api_key=" + ApiKey + "&auth_token=" + Token);
webRequest.Headers.Add("Accept-Encoding", AcceptEncoding);
webRequest.Headers.Add("Accept-Charset", AcceptCharset);
webRequest.ContentLength = contentLength;
webRequest.ServicePoint.ConnectionLeaseTimeout = 0;
return webRequest;
}
}
Here is my default asp.net page... This is mainly just a testing page. And I can to GET requests and login and get the token and folders and everything else.
public partial class _Default : System.Web.UI.Page
{
public const string APIKEY = "{APIKEY}";
public const string AUTH_STRING = "https://www.box.com/api/1.0/auth/";
public const string GET_TOKEN_STRING = "https://www.box.com/api/1.0/rest?action=get_auth_token&api_key={0}&ticket={1}";
public const string BASE_URL = "https://api.box.com/2.0/";
public string ticket = "";
public string token = "";
public string login = "";
public BoxUser boxUser;
HttpContext http;
protected void Page_Load(object sender, EventArgs e)
{
http = HttpContext.Current;
ticket = http.Request["ticket"];
token = http.Request["auth_token"];
login = http.Request["login"];
}
protected void btnBoxLogin_Click(object sender, EventArgs e)
{
string bURL = "https://www.box.com/api/1.0/rest?action=get_ticket&api_key=" + APIKEY;
HttpWebRequest wGetUrl = (HttpWebRequest)WebRequest.Create(bURL);
wGetUrl.ServicePoint.ConnectionLeaseTimeout = 0;
WebResponse response = wGetUrl.GetResponse();
Stream stream = response.GetResponseStream();
StreamReader reader = new StreamReader(stream);
if (reader != null)
{
string xmlString = "";
string tmpString = reader.ReadLine();
while (tmpString != null)
{
xmlString += tmpString;
tmpString = reader.ReadLine();
}
//txtResponse.Text = xmlString;
GetResponseTicket(xmlString);
}
if(ticket != "")
txtResponse.Text = "\nThe Ticket returned is: " + ticket;
response.Close();
stream.Close();
Response.Redirect(AUTH_STRING + ticket, false);
}
protected void btnGetAuthToken_Click(object sender, EventArgs e)
{
string bURL = "https://www.box.com/api/1.0/rest?action=get_auth_token&api_key="+APIKEY+"&ticket=" + ticket;
HttpWebRequest wGetUrl = (HttpWebRequest)WebRequest.Create(bURL);
wGetUrl.ServicePoint.ConnectionLeaseTimeout = 0;
WebResponse response = wGetUrl.GetResponse();
Stream stream = response.GetResponseStream();
StreamReader reader = new StreamReader(stream);
if (reader != null)
{
string xmlString = "";
string tmpString = reader.ReadLine();
while (tmpString != null)
{
xmlString += tmpString;
tmpString = reader.ReadLine();
}
//txtResponse.Text = xmlString;
GetResponseUser(xmlString);
}
//txtResponse.Text += token + "\n";
//txtResponse.Text += login;
response.Close();
reader.Close();
stream.Close();
}
protected void btnGetUserFolderInfo_Click(object sender, EventArgs e)
{
string usersUrl = "folders/0/items";
string url = BASE_URL + usersUrl;
HttpWebRequest request = (HttpWebRequest)WebRequest.Create(url);
request.Headers.Add("Authorization", "BoxAuth api_key=" + APIKEY + "&auth_token=" + token);
request.ServicePoint.ConnectionLeaseTimeout = 0;
WebResponse response = request.GetResponse();
Stream stream = response.GetResponseStream();
StreamReader reader = new StreamReader(stream);
JavaScriptSerializer js = new JavaScriptSerializer();
object o = js.DeserializeObject(reader.ReadLine());
if (reader != null)
{
string txt = reader.ReadLine();
txtResponse.Text += "\n" + txt;
while (!reader.EndOfStream)
{
txt = reader.ReadToEnd();
txtResponse.Text += "\n" + txt;
}
}
stream.Close();
response.Close();
reader.Close();
}
private void GetResponseTicket(string xmlString)
{
using (XmlReader reader = XmlReader.Create(new StringReader(xmlString)))
{
reader.ReadToFollowing("status");
string status = reader.ReadElementContentAsString();
if (status != null && status == "get_ticket_ok")
{
ticket = reader.ReadElementContentAsString();
if (String.IsNullOrEmpty(ticket))
throw new Exception("Ticket was empty");
}
else
throw new Exception("For some reason Status was null or not right");
}
}
private void GetResponseUser(string xmlString)
{
XmlDocument doc = new XmlDocument();
doc.LoadXml(xmlString);
XmlNode root = doc.DocumentElement;
XmlNode user = root.LastChild;
//XmlNamespaceManager xmlns = new XmlNamespaceManager(doc.NameTable);
//XmlNode node = root.SelectSingleNode(login).InnerText
string login = user.SelectSingleNode("login").InnerText;
string email = user.SelectSingleNode("email").InnerText;
string access_id = user.SelectSingleNode("access_id").InnerText;
string user_id = user.SelectSingleNode("user_id").InnerText;
long space_amount = long.Parse(user.SelectSingleNode("space_amount").InnerText);
long space_used = long.Parse(user.SelectSingleNode("space_used").InnerText);
long max_upload_size = long.Parse(user.SelectSingleNode("max_upload_size").InnerText);
boxUser = new BoxUser(login, email, access_id, user_id, space_amount, space_used, max_upload_size);
}
protected void CreateNewFolder_Click(object sender, EventArgs e)
{
string url = BASE_URL + "folders/389813359";
HttpWebRequest request = (HttpWebRequest)WebRequest.Create(url);
request.Headers.Add("Authorization", "BoxAuth api_key=" + APIKEY + "&auth_token=" + token);
request.Method = "POST";
request.ServicePoint.ConnectionLeaseTimeout = 0;
ASCIIEncoding encoding = new ASCIIEncoding();
string postData = "{\"name\":\"" + txtNewFolderName.Text+"\"}";
byte[] data = encoding.GetBytes(postData);
using (Stream datastream = request.GetRequestStream())
{
datastream.Write(data, 0, data.Length);
datastream.Close();
}
WebResponse response = request.GetResponse();
Console.WriteLine(((HttpWebResponse)response).StatusDescription);
Stream stream = response.GetResponseStream();
StreamReader reader = new StreamReader(stream);
string responseFromServer = reader.ReadToEnd();
lblResult.Text = responseFromServer;
reader.Close();
stream.Close();
response.Close();
}
protected void UploadNewFile_Click(object sender, EventArgs e)
{
//string url = BASE_URL + "files/data";
string url = "https://upload.box.com/api/2.0/" + "files/data";
//string url = "https://upload.box.com/api/1.0/upload" + token + "/0";
/*string boundary = "----------------------" + DateTime.Now.Ticks;
var newLine = Environment.NewLine;
string propFormat = "--" + boundary + newLine + "Content-Disposition: form-data; {0}={1}" + newLine;
HttpWebRequest request = (HttpWebRequest)HttpWebRequest.Create(url);
request.Headers.Add("Authorization", "BoxAuth api_key=" + APIKEY + "&auth_token=" + token);
request.Method = WebRequestMethods.Http.Post;
request.ContentType = "multipart/form-data; boundary=" + boundary;
string fileName = fileUpload.FileName;
byte[] file = fileUpload.FileBytes;
using (Stream stream = request.GetRequestStream())
{
StreamWriter writer = new StreamWriter(stream);
string tmp = String.Format(propFormat, fileName, file);
writer.Write(tmp);
tmp = String.Format(propFormat, "folder_id", "389813359");
writer.Write(tmp);
writer.Write("--" + boundary + "--");
writer.Flush();
}
WebResponse response = request.GetResponse();
using (Stream resStream = response.GetResponseStream())
{
StreamReader reader = new StreamReader(resStream);
lblResult.Text = reader.ReadToEnd();
}*/
Stream stream = fileUpload.PostedFile.InputStream;
StreamReader reader = new StreamReader(stream);
string text = reader.ReadToEnd();
UploadableFile file = new UploadableFile(fileUpload.FileName, text, ".txt");
UploadableFile[] files = new UploadableFile[1];
files[0] = new UploadableFile(fileUpload.FileName, text, ".txt"); ;
MultipartWebRequest myRequest = new MultipartWebRequest(APIKEY,token,url);
string response = myRequest.SubmitFiles(files, false, null, new string[] { }, "0");
txtResponse.Text = response;
}
}
As you can see I have tried all of the different upload urls that I have found around the site. And with all the different ones, not sure exactly which one to use, but doc appears to be the latest "most" correct one? Any help with this would be greatly appreciated as I am fairly new (but understand) to post requests in C#, but VERY new (never done one) to multipart forms in C# (or really anywhere).
The current recommended URL for the API (including file uploads) appears to now be https://api.box.com/2.0. Have you tried using that base URL?
How to POST attachment to JIRA using JIRA REST API and HttpWebRequest in C#?
From the documentation under /rest/api/2/issue/{issueIdOrKey}/attachments:
POST
Add one or more attachments to an issue.
This resource expects a multipart post. The media-type multipart/form-data is defined in RFC 1867. Most client libraries have classes that make dealing with multipart posts simple. For instance, in Java the Apache HTTP Components library provides a MultiPartEntity that makes it simple to submit a multipart POST.
In order to protect against XSRF attacks, because this method accepts multipart/form-data, it has XSRF protection on it. This means you must submit a header of X-Atlassian-Token: nocheck with the request, otherwise it will be blocked.
The name of the multipart/form-data parameter that contains attachments must be "file"
A simple example to upload a file called "myfile.txt" to issue REST-123:
curl -D- -u admin:admin -X POST -H "X-Atlassian-Token: nocheck" -F "file=#myfile.txt" http://myhost.test/rest/api/2/issue/TEST-123/attachments
I have
foreach (JIRAAttachments attachm in attachments.attachments)
{
request = HttpWebRequest.Create(
logInformation.GetUri() + "/rest/api/2/issue/" + key + "/attachments"
) as HttpWebRequest;
request.Headers.Add("Authorization: Basic " + logInformation.GetEncodeAuthentication());
request.Method = "POST";
request.ContentType = "multipart/form-data";
request.Headers.Add("X-Atlassian-Token: nocheck file=#" + Path.GetFullPath(#"..\Attachments\" + attachm.filename));
request.KeepAlive = true;
request.Proxy = wp;
response = (HttpWebResponse)request.GetResponse();
Stream s = response.GetResponseStream();
FileStream fs = new FileStream(Path.GetFullPath(#"..\Attachments\" + attachm.filename), FileMode.Open);
byte[] write = new byte[256];
int count = fs.Read(write, 0, write.Length);
while (count > 0)
{
s.Write(write, 0, count);
count = fs.Read(write, 0, write.Length);
}
fs.Close();
s.Close();
response.Close();
}
but it returns a 404 error...
solved your problem:
var boundary = string.Format("----------{0:N}", Guid.NewGuid());
System.IO.MemoryStream content = new MemoryStream();
var writer = new StreamWriter(content);
foreach (var att in attachments)
{
writer.WriteLine("--{0}", boundary);
writer.WriteLine("Content-Disposition: form-data; name=\"{0}\"; filename=\"{1}\"", "file", Path.GetFileName(att["filename"]));
writer.WriteLine("Content-Type: {0}", att.ContentType);
writer.WriteLine();
writer.Flush();
att.Stream.CopyTo(content);
writer.WriteLine();
}
writer.WriteLine("--" + boundary + "--");
writer.Flush();
content.Seek(0, SeekOrigin.Begin);
HttpWebRequest oRequest = null;
oRequest = (HttpWebRequest)HttpWebRequest.Create(string.Format(RestBaseURI + "issue/{0}/attachments", item.Key));
oRequest.ContentType = string.Format("multipart/form-data; boundary={0}", boundary);
oRequest.Method = "POST";
oRequest.Headers.Add("Authorization", AuthData);
oRequest.Headers.Add("X-Atlassian-Token", "nocheck");
oRequest.UseDefaultCredentials = true;
oRequest.KeepAlive = true;
oRequest.ContentLength = content.Length;
using (var oStream = oRequest.GetRequestStream())
{
content.CopyTo(oStream);
}
using (var oResponse = (HttpWebResponse)oRequest.GetResponse())
{
using (var reader = new StreamReader(oResponse.GetResponseStream()))
{
var responseData = reader.ReadToEnd();
var data = JObject.Parse(responseData);
}
}
PS: thanks2mod to delete my previous post! nice ...
There was a couple of mistakes in the OP's code.
With the snippet provided by #mabu and the code I found on http://www.briangrinstead.com/blog/multipart-form-post-in-c, here's a *functional** Code Block to Upload attachment to Jira.
public bool AddAttachments(string issueKey, IEnumerable<string> filePaths)
{
string restUrl = Jira.FormatRestUrl(m_JiraId, true);
string issueLinkUrl = String.Format("{0}/issue/{1}/attachments", restUrl, issueKey);
var filesToUpload = new List<FileInfo>();
foreach (var filePath in filePaths)
{
if (!File.Exists(filePath))
{
Jira.LogError("File '{0}' doesn't exist", filePath);
return false;
}
var file = new FileInfo(filePath);
if (file.Length > 10485760) // TODO Get Actual Limit
{
Jira.LogError("Attachment too large");
return false;
}
filesToUpload.Add(file);
}
if (filesToUpload.Count <= 0)
{
Jira.LogWarning("No file to Upload");
return false;
}
return PostMultiPart(issueLinkUrl, filesToUpload);
}
private Boolean PostMultiPart(string restUrl, IEnumerable<FileInfo> filePaths)
{
HttpWebResponse response = null;
HttpWebRequest request = null;
try
{
var boundary = string.Format("----------{0:N}", Guid.NewGuid());
var content = new MemoryStream();
var writer = new StreamWriter(content);
foreach (var filePath in filePaths)
{
var fs = new FileStream(filePath.FullName, FileMode.Open, FileAccess.Read);
var data = new byte[fs.Length];
fs.Read(data, 0, data.Length);
fs.Close();
writer.WriteLine("--{0}", boundary);
writer.WriteLine("Content-Disposition: form-data; name=\"file\"; filename=\"{0}\"", filePath.Name);
writer.WriteLine("Content-Type: application/octet-stream");
writer.WriteLine();
writer.Flush();
content.Write(data, 0, data.Length);
writer.WriteLine();
}
writer.WriteLine("--" + boundary + "--");
writer.Flush();
content.Seek(0, SeekOrigin.Begin);
request = WebRequest.Create(restUrl) as HttpWebRequest;
if (request == null)
{
Jira.LogError("Unable to create REST query: {0}", restUrl);
return false;
}
request.Method = "POST";
request.ContentType = string.Format("multipart/form-data; boundary={0}", boundary);
request.Accept = "application/json";
request.Headers.Add("Authorization", "Basic " + m_EncodedCredential);
request.Headers.Add("X-Atlassian-Token", "nocheck");
request.ContentLength = content.Length;
using (Stream requestStream = request.GetRequestStream())
{
content.WriteTo(requestStream);
requestStream.Close();
}
using (response = request.GetResponse() as HttpWebResponse)
{
if (response.StatusCode != HttpStatusCode.OK)
{
var reader = new StreamReader(response.GetResponseStream());
Jira.LogError("The server returned '{0}'\n{1}", response.StatusCode, reader.ReadToEnd());
return false;
}
return true;
}
}
catch (WebException wex)
{
if (wex.Response != null)
{
using (var errorResponse = (HttpWebResponse)wex.Response)
{
var reader = new StreamReader(errorResponse.GetResponseStream());
Jira.LogError("The server returned '{0}'\n{1}).", errorResponse.StatusCode, reader.ReadToEnd());
}
}
if (request != null)
{
request.Abort();
}
return false;
}
finally
{
if (response != null)
{
response.Close();
}
}
}
I really didn't want to deal with all that boundary stuff, so here's my shot at it. This works against Confluence whose API looks identical to Jira.
Thanks to Michael Teper at ASP.NET WebApi: how to perform a multipart post with file upload using WebApi HttpClient
and Jeff Caron (above).
var contents = "some long HTML that I wanted to upload";
var fileName = "Some fancy file name.html";
using (var client = new HttpClient())
{
var uri = new Uri(URL);
client.BaseAddress = new Uri(URL);
client.DefaultRequestHeaders.Accept.Clear();
client.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));
client.DefaultRequestHeaders.Authorization = authorization;
client.DefaultRequestHeaders.Add("X-Atlassian-Token", "nocheck");
var uriPath = String.Format(AttachmentPath, pageId);
var content = new MultipartFormDataContent();
var fileContent = new StringContent(contents);
// also tested to work:
// var fileContent = new ByteArrayContent(Encoding.UTF8.GetBytes(contents));
content.Add(fileContent, "file", fileName);
var response = await client.PostAsync(uriPath, content);
if (response.IsSuccessStatusCode)
{
return TaskResult.Success(null, response.ReasonPhrase);
}
else
{
return TaskResult.Failure("Service responded with Status Code: " + response.StatusCode + Environment.NewLine + "Reason Phrase: " + response.ReasonPhrase);
}
}
You're also able to do with Restsharp as follow
using System;
using System.Collections.Generic;
using System.IO;
using System.Net;
using Jira
using RestSharp;
using RestSharp.Authenticators;
namespace Jira
{
class Program
{
static void Main(string[] args)
{
var client = new RestClient("http://{URL}/rest/api/2");
var request = new RestRequest("issue/", Method.POST);
client.Authenticator = new HttpBasicAuthenticator("user", "pass");
var issue = new Issue
{
fields =
new Fields
{
description = "Issue Description",
summary = "Issue Summary",
project = new Project { key = "KEY" },
issuetype = new IssueType { name = "ISSUE_TYPE_NAME" }
}
};
request.AddJsonBody(issue);
var res = client.Execute<Issue>(request);
if (res.StatusCode == HttpStatusCode.Created)
{
Console.WriteLine("Issue: {0} successfully created", res.Data.key);
#region Attachment
request = new RestRequest(string.Format("issue/{0}/attachments", res.Data.key), Method.POST);
request.AddHeader("X-Atlassian-Token", "nocheck");
var file = File.ReadAllBytes(#"C:\FB_IMG_1445253679378.jpg");
request.AddHeader("Content-Type", "multipart/form-data");
request.AddFileBytes("file", file, "FB_IMG_1445253679378.jpg", "application/octet-stream");
var res2 = client.Execute(request);
Console.WriteLine(res2.StatusCode == HttpStatusCode.OK ? "Attachment added!" : res2.Content);
#endregion
}
else
Console.WriteLine(res.Content);
}
}
public class Issue
{
public string id { get; set; }
public string key { get; set; }
public Fields fields { get; set; }
}
public class Fields
{
public Project project { get; set; }
public IssueType issuetype { get; set; }
public string summary { get; set; }
public string description { get; set; }
}
public class Project
{
public string id { get; set; }
public string key { get; set; }
}
public class IssueType
{
public string id { get; set; }
public string name { get; set; }
}
}
The whole code is on gist https://gist.github.com/gandarez/c2c5b2b27dbaf62a0d634253529bcb59