Uploading files to Sharepoint (WSS 3.0) document library using HTTP PUT - c#

Hi I have the following piece of code to upload a file to Sharepoint. It uses HTTP PUT:
public static string UploadFile(string destUrl, string sourcePath)
{
try
{
Uri destUri = new Uri(destUrl);
FileStream inStream = File.OpenRead(sourcePath);
WebRequest req = WebRequest.Create(destUri);
req.Method = "PUT";
req.Headers.Add("Overwrite", "F");
req.Timeout = System.Threading.Timeout.Infinite;
req.Credentials = CredentialCache.DefaultCredentials;
Stream outStream = req.GetRequestStream();
string status = CopyStream(inStream, outStream);
if (status == "success")
{
outStream.Close();
WebResponse ores = req.GetResponse();
return "success";
}
else
{
return status;
}
}
catch (WebException we)
{
return we.Message;
}
catch (System.Exception ee)
{
return ee.Message;
}
}
When I run this code I get the exception:
"The remote server returned an error: (409) Conflict."
Does anyone have any ideas as to where I am going wrong?
Thanks,
Alex

I've had this issue when I was referencing the url of the document library and not the destination file itself.
i.e. try http://server name/document library name/new file name.doc

No clue. But why dont you use Remote Procedure Calls (RPC) thats how i usually do it.
I found this example that might get you started http://geek.hubkey.com/2007/11/upload-file-to-sharepoint-document.html

Try:
void StorePlainFile(string target_url, string filename, byte[] file_bytes)
{
string url = target_url + "/" + filename;
System.Net.WebClient client = new System.Net.WebClient();
client.Credentials = System.Net.CredentialCache.DefaultCredentials;
client.Headers.Add("Overwrite", "F");
byte[] response = client.UploadData(url, "PUT", file_bytes);
}

I haven't solved my problem yet, that's why I'm here, but I know why you're getting this error.
The error results because you are not setting a hidden, but required, field. In my case, I had no columns, and certainly none that were required. However, there is a versioning field that is in conflict.
My intent is to 1) upload the document, and 2) set the document's metadata. 1) and 2) occur over separate HTTP calls. Ideally, I want to do this in a single call, but I don't know how to do this.
To accomplish this, 1) succeeds, so the document appears in the library. Then when I try to update the metadata, that's when I get the 409 error.
I'm pretty sure that I first need to insert a step in between 1) and 2) which first downloads the document's list (or manifest) which would in theory contain the needed versioning information. All I would need to do is set the metadata fields I need, and send back to the server.
No, we don't want to use the Sharepoint API because there are no libraries for it in Java. ;-)

Is there a paticular reason you can't just use the Sharepoint API (eg. SPFolder.Files.Add) to upload the file? As follows:
http://msdn.microsoft.com/en-us/library/ms454491.aspx
public void UploadFile(string srcUrl, string destUrl)
{
if (! File.Exists(srcUrl))
{
throw new ArgumentException(String.Format("{0} does not exist",
srcUrl), "srcUrl");
}
SPWeb site = new SPSite(destUrl).OpenWeb();
FileStream fStream = File.OpenRead(srcUrl);
byte[] contents = new byte[fStream.Length];
fStream.Read(contents, 0, (int)fStream.Length);
fStream.Close();
EnsureParentFolder(site, destUrl);
site.Files.Add(destUrl, contents);
}

Alex,
This happened to me too. You probable should create another another lit or document library and upload files into it to test.
You may want to check the variable "destUri" to see if it points to exactly the expected sharepoint list.
My situation is I firstly created a document library "Requrements", there is a typo mistake, then i changed the title to "Requirements". You should notice that sharepoint still keeps the URL to this list as http://server:port/Requrements
This is an exeption. Hopefully it helps.

Related

How to Download File

I have been following these links all listed below, i found the best way to write this SMALL create Excel and Download function. ( Using EPPlus for Excel )
Download file of any type in Asp.Net MVC using FileResult? + How to convert an Stream into a byte[] in C#?
Using a FileStreamResult with a MemoryStream in ASP.NET MVC 3
Writing A Custom File Download Action Result For ASP.NET MVC
It runs through the code perfectly without error every time I run this but does not "Kick out" the file to be downloaded ( in a save as dialogue or w/e ).
public ActionResult ShowReport()
{
using (var stream = new MemoryStream())
{
ExcelPackage pck = new ExcelPackage();
var ws = pck.Workbook.Worksheets.Add("Sample1");
ws.Cells["A1"].Value = "Sample 1";
ws.Cells["A1"].Style.Font.Bold = true;
var shape = ws.Drawings.AddShape("Shape1", eShapeStyle.Rect);
shape.SetPosition(50, 200);
shape.SetSize(200, 100);
shape.Text = "Sample 1 text text text";
var fileDownloadName = "sample.xlsx";
var contentType = "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet";//System.Net.Mime.MediaTypeNames.Application.Octet
var fileStream = new MemoryStream();
pck.SaveAs(fileStream);
fileStream.Position = 0;
var fsr = new FileStreamResult(fileStream, contentType);
fsr.FileDownloadName = fileDownloadName;
byte[] fileBytes = ReadToEnd(fileStream);
string fileName = "example";
return File(fileBytes, contentType, fileName);
}
}
What am I doing wrong / missing? - Must i write that Dialogue myself?
PN: I have also attempted this way
byte[] fileBytes = ReadToEnd(fileStream);
string fileName = "example";
return File(fileBytes, contentType, fileName);
ofcourse i had to figure out how to convert Stream to Byte but it also did not show anything.
Image of Chrome's Network Development Tool
Sorry about the small image ( if you can't see it scroll in with ctl+MouseWheel ) if your in a supporting browswer.
(In response to the comment thread above.)
From the image posted it looks like the actual file request (the last one in the list) is coming from JavaScript code instead of from a normal document-level request. Given this, it's highly likely that the server-side code is working correctly and returning the correct response.
However, since it's an AJAX request, the browser doesn't actually know what to do with the response. There are some potential solutions here. Ideally, you'll want to make this a normal request and remove AJAX from the picture if possible. If that's not an option, you can still initiate a document-level request from JavaScript. Something as simple as this:
window.location = '#Url.Action("Method", "Controller")';
This would be initiated from JavaScript code as it currently is, but would be for the whole browser instead of an AJAX request. That should do the trick.
Using the memory stream you have you can simple pass that to the Response object once you have saved the Excel Package
Code:
Response.AddHeader("content-disposition", "attachment;filename=FILENAME.xlsx")
Response.Charset = String.Empty
Response.ContentType = "application/ms-excel"
Response.BinaryWrite(stream.ToArray())
Response.End()

Does any one know about this error: "Wrong Local header signature: 0x6D74683C"?

The following code is used to download a zip file and unzip it on phone.
The same code used to work on WP7, I started tested on WP8 device, and strange thing is happening... now it works on WP8 but NOT on WP7 anymore.
On the WP7 it gives an ERROR:
Wrong Local header signature: 0x6D74683C
Could someone tell me what's wrong here?
THE OBSERVATION (2 days after posting the question)
I have some observations.... Sharing here in detail (Image format) or (Excel format)
THE CODE
using ICSharpCode.SharpZipLib.Zip;
using System;
using System.Diagnostics;
using System.IO;
using System.IO.IsolatedStorage;
using System.Net;
namespace iq_main.Network
{
public class IQ_Download
{
private string zipFilePassword = String.Empty;
private string fileNameToBeStoredAs = String.Empty;
private string urlToBeDownloaded = String.Empty;
private HttpWebResponse response;
public void Download(string _urlToBeDownloaded = GlobalConstants.DownloadLanguageConfigurationUrl, string _fileNameToBeStoredAs = GlobalConstants.DownloadLanguageConfigurationXmlFilename, string _zipFilePassword = GlobalConstants.DownloadZipsPassword)
{
urlToBeDownloaded = _urlToBeDownloaded;
fileNameToBeStoredAs = _fileNameToBeStoredAs;
zipFilePassword = _zipFilePassword;
System.Uri targetUri = new System.Uri(urlToBeDownloaded);
HttpWebRequest request = (HttpWebRequest)HttpWebRequest.Create(targetUri);
request.BeginGetResponse(new AsyncCallback(WebRequestCallBack), request);
}
void WebRequestCallBack(IAsyncResult result)
{
HttpWebRequest resultInfo = (HttpWebRequest)result.AsyncState;
response = (HttpWebResponse)resultInfo.EndGetResponse(result);
try
{
using (StreamReader httpwebStreamReader = new StreamReader(response.GetResponseStream()))
{
//open isolated storage to save files
using (IsolatedStorageFile isoStore = IsolatedStorageFile.GetUserStoreForApplication())
{
using (ZipInputStream s = new ZipInputStream(httpwebStreamReader.BaseStream))
{
if (zipFilePassword != String.Empty)
s.Password = zipFilePassword;//if archive is encrypted
ZipEntry theEntry;
try
{
//EXCEPTION OCCURS ON THE VERY NEXT LINE (while...)
while ((theEntry = s.GetNextEntry()) != null)
{
string directoryName = Path.GetDirectoryName(theEntry.Name);
string fileName = Path.GetFileName(theEntry.Name);
fileName = fileNameToBeStoredAs;
// create directory
if (directoryName.Length > 0)
{
isoStore.CreateDirectory(directoryName);
//Directory.CreateDirectory(directoryName);
}
if (fileName != String.Empty)
{
//save file to isolated storage
using (BinaryWriter streamWriter =
new BinaryWriter(new IsolatedStorageFileStream(theEntry.Name,
FileMode.Create, FileAccess.Write, FileShare.Write, isoStore)))
{
int size = 2048;
byte[] data = new byte[2048];
while (true)
{
size = s.Read(data, 0, data.Length);
if (size > 0)
streamWriter.Write(data, 0, size);
else
break;
}
}
}
}
}
catch (ZipException ze)
{
Debug.WriteLine(ze.Message);
}
}
}
}
} //try
catch (Exception ex)
{
Debug.WriteLine(ex.Message);
}
}//WebRequestCallBack Method */
} //Class ends
}
THE OUTPUT STACK
Step into: Stepping over method without symbols 'string.operator !='
Step into: Stepping over method without symbols 'ICSharpCode.SharpZipLib.Zip.ZipInputStream.Password.set'
Step into: Stepping over method without symbols 'string.operator !='
Step into: Stepping over method without symbols 'ICSharpCode.SharpZipLib.Zip.ZipInputStream.Password.set'
Step into: Stepping over method without symbols 'ICSharpCode.SharpZipLib.Zip.ZipInputStream.GetNextEntry'
A first chance exception of type 'ICSharpCode.SharpZipLib.Zip.ZipException' occurred in SharpZipLib.WindowsPhone7.dll
Step into: Stepping over method without symbols 'System.Exception.Message.get'
Step into: Stepping over method without symbols 'System.Diagnostics.Debug.WriteLine'
Wrong Local header signature: 0x6D74683C
A first chance exception of type 'ICSharpCode.SharpZipLib.Zip.ZipException' occurred in SharpZipLib.WindowsPhone7.dll
Wrong Local header signature: 0x6D74683C
The header code 0x6D74683C corresponds to the ASCII sequence <htm, which I presume is the truncated HTML header in a web page. If you are downloading the content of the .zip archive, then perhaps it means the web server is returning HTML code instead of the intended archive (an error page or something like that). Maybe you should check the HTTP Content-Type header before feeding the stream to the ICSharpCode.SharpZipLib.
When you use WP7 you receive a html from dropbox:
Found
The resource was found at {"your new link here}; you should be
redirected automatically.
------------------------------------ WSGI Server
In Wp8 ithis redirect works automatically, but in Wp7 this redirect doesn't work.
I think the solution for you: just change link to new(you can find it in html file that you receive)
The problem was same as "Leandro Taset" and "d.lavysh" explained in their answers. However, it's still unknown that why WP7 gets additions HTML headers?
Anyway, the modified code, which is now working for both WP7 and WP8 devices. This code is also capable of downloading files either from a Web-Hosting service or from DropBox.
The code I posted above is almost the same, I only modified the Download method, which, after modification, looks like this:
public async void Download(string _urlToBeDownloaded = GlobalConstants.DownloadLanguageConfigurationUrl, string _fileNameToBeStoredAs = GlobalConstants.DownloadLanguageConfigurationXmlFilename, string _zipFilePassword = GlobalConstants.DownloadZipsPassword)
{
//The following IF block is addition to the code above.
//Here the headers are checked and if "WP7" and the URL is pointing to the "Dropbox", the inner URL is fetched out of the headers.
if (GlobalVariables.IsWP7 && _urlToBeDownloaded.ToLower().Contains("dropbox"))
{
HttpWebRequest webRequest = (HttpWebRequest)WebRequest.Create(_urlToBeDownloaded);
HttpWebResponse webResponse = await webRequest.GetResponseAsync() as HttpWebResponse;
for (int i = 0; i < webResponse.Headers.Count; ++i)
{
if (webResponse.Headers.AllKeys[i].ToLower() == "location")
{
_urlToBeDownloaded = webResponse.Headers["location"] ;
break;
}
}
}
urlToBeDownloaded = _urlToBeDownloaded ;
fileNameToBeStoredAs = _fileNameToBeStoredAs;
zipFilePassword = _zipFilePassword;
System.Uri targetUri = new System.Uri(urlToBeDownloaded);
HttpWebRequest request = (HttpWebRequest)HttpWebRequest.Create(targetUri);
request.BeginGetResponse(new AsyncCallback(WebRequestCallBack), request);
}

Upload file to skydrive through SkyDrive API

I try to upload a text file to my skydrive or at least create new text file in SD and edit it's content, through SkyDrive API in my Windows 8 application.
How can I do that?
I tried to do something like that:
LiveConnectClient client = new LiveConnectClient(session);
var fileData = new Dictionary<string, object>();
fileData.Add("name", "new_file.txt");
try
{
LiveOperationResult fileOperationResult = await client.PutAsync("me/skydrive", fileData);
this.infoTextBlock.Text = fileOperationResult.ToString();
}
catch (LiveConnectException exception)
{
this.infoTextBlock.Text = exception.Message;
}
but I get error
"The provided request is not valid. The root SkyDrive folder cannot be updated."
If I write something like "me/skydrive/" I get
"The provided URL is not valid. The requested path '' is not supported".
Method LiveConnectClient.PutAsync allows me only to update existing properties (but not it's content).
How it should be done properly?
Btw - Is content on LCDC(http://msdn.microsoft.com/en-us/library/live/hh826531.aspx) updated? I'm asking because some methods, which are in documentation, doesn't exist in dlls (f.e. LiveConnectClient.Upload. There's only BackgroundUploadAsync).
Thanks for help in advance,
Micheal
Close but as I wrote: I can't use client.upload method because LiveConnectClient class doesn't contain it. That's why I asked about site content update.
Anyway - I've got an answer:
//create a StorageFile (here is one way to do that if it is stored in your ApplicationData)
StorageFile file = awaitApplicationData.Current.LocalFolder.GetFileAsync("yourfilename.txt");
try {
client = new LiveConnectClient(session);
LiveOperationResult operationResult = await client.BackgroundUploadAsync("me/skydrive", file.Name, file, OverwriteOption.Overwrite);
}
catch (LiveConnectException exception) {
//handle exception
}
You should use the Upload method on LiveConnectionClient. For example, see the Uploading Files example in the Live SDK. Something like ...
LiveOperationResult fileOperationResult =
await client.Upload("me/skydrive", /*file name here*/, /*file stream here*/);
Here's another way to upload a file from a console application using a SkyDriveApiClient downloaded from http://skydriveapiclient.codeplex.com/releases/view/103081
static void Main(string[] args)
{
var client = new SkyDriveServiceClient();
client.LogOn("YourEmail#hotmail.com", "password");
WebFolderInfo wfInfo = new WebFolderInfo();
WebFolderInfo[] wfInfoArray = client.ListRootWebFolders();
wfInfo = wfInfoArray[0];
client.Timeout = 1000000000;
string fn = #"test.txt";
if (File.Exists(fn))
{
client.UploadWebFile(fn, wfInfo);
}
}

C# FTP, how to check if a Path is a File or a Directory?

I have an array that contains some FTP pathes, like follows:
"ftp//ip/directory/directory1",
"ftp//ip/directory/directory2",
"ftp//ip/directory/file.txt",
"ftp//ip/directory/directory3",
"ftp//ip/directory/another_file.csv"
How can i find out if the path is a file or a directory?
Thanks in advance.
Use the LIST command, which you can refer to RFC959, to get the details about items under the specified path. Take FileZilla Server for example, the LIST command will return standard LINUX permission format which you can find here. The first letter indicates if the requested path is file or directory. Also a simple library written in C# can be found here
I had the same problem. I worked off of hughs answer. You need to make an FTPRequest like:
request.Method = WebRequestMethods.Ftp.ListDirectoryDetails;
grab it from streamreader and stick it in a string
StreamReader reader = new StreamReader(responseStream);
string directoryRaw = null;
try { while (reader.Peek() != -1) { directoryRaw += reader.ReadLine() + "|"; } }
catch (Exception ex) { Console.WriteLine(ex.ToString()); }
when you print this it is going to look like:
|-rw-r--r-- 1 user user 1699 Jun 1 2015
404.shtml
|drwxr-xr-x 2 user user 4096 Sep 8 19:39 cgi-bin
|drwxr-xr-x 2 user user 4096 Nov 3 10:52 css
These are seperated by | so that will be the delim for a splitstring
if it starts with a d and not a - then its a directory, else its a file.
these are all the same size before file name so make a new string for each of these strings starting at position 62 to end and that will be the file name.
Hope it helps
There's no direct way.
Indirectly you could assume that filenames that have no period "." are directories, but that is not going to always be true.
Best is to write the code that consumes these paths carefully so it e.g. treats the path as a directory, then if the FTP server reports an error, treat it as a file.
One way to do it is if we can assume that all files will end in an extension and all directories will not have an extension, we can use the System.IO.Path.GetExtension() method like this:
public bool IsDirectory(string directory)
{
if(directory == null)
{
throw new ArgumentNullException(); // or however you want to handle null values
}
// GetExtension(string) returns string.Empty when no extension found
return System.IO.Path.GetExtension(directory) == string.Empty;
}
You can use System.IO.Path.GetExtension(path)` as a way to check if your path has a file extension.
Given "ftp//ip/directory/directory1" or "ftp//ip/directory/directory2/", GetExtension will return a String.Empty to you.
This isn't foolproof, and it's possible though if there was a file without an extension that this would break down completely, or a directory with a period in it could cause issues.
I have found "hack" how to determine target type.
If you will use
request.Method = WebRequestMethods.Ftp.GetFileSize;
on a folder, it will result in Exception
Unhandled Exception: System.Net.WebException: The remote server
returned an erro r: (550) File unavailable (e.g., file not found, no
access).
But using it on file, it will naturally return its size.
I have create sample code for such method.
static bool IsFile(string ftpPath)
{
var request = (FtpWebRequest)WebRequest.Create(ftpPath);
request.Method = WebRequestMethods.Ftp.GetFileSize;
request.Credentials = new NetworkCredential("foo", "bar");
try
{
using (var response = (FtpWebResponse)request.GetResponse())
using (var responseStream = response.GetResponseStream())
{
return true;
}
}
catch(WebException ex)
{
return false;
}
}
You might want to alter it, because this one will catch any FTP error.
I had the same problem so I used GetFileSize to check if it's a File or Directory
var isFile = FtpHelper.IsFile("ftpURL", "userName", "password");
using System;
using System.Net;
public static class FtpHelper
{
public static bool IsFile(Uri requestUri, NetworkCredential networkCredential)
{
return GetFtpFileSize(requestUri, networkCredential) != default(long); //It's a Directory if it has no size
}
public static FtpWebRequest GetFtpWebRequest(Uri requestUri, NetworkCredential networkCredential, string method = null)
{
var ftpWebRequest = (FtpWebRequest)WebRequest.Create(requestUri); //Create FtpWebRequest with given Request Uri.
ftpWebRequest.Credentials = networkCredential; //Set the Credentials of current FtpWebRequest.
if (!string.IsNullOrEmpty(method))
ftpWebRequest.Method = method; //Set the Method of FtpWebRequest incase it has a value.
return ftpWebRequest; //Return the configured FtpWebRequest.
}
public static long GetFtpFileSize(Uri requestUri, NetworkCredential networkCredential)
{
//Create ftpWebRequest object with given options to get the File Size.
var ftpWebRequest = GetFtpWebRequest(requestUri, networkCredential, WebRequestMethods.Ftp.GetFileSize);
try { return ((FtpWebResponse)ftpWebRequest.GetResponse()).ContentLength; } //Incase of success it'll return the File Size.
catch (Exception) { return default(long); } //Incase of fail it'll return default value to check it later.
}
}

Selenium c# - how do i test that an image src file exists (verifying if the image shows on the page)

im new to Selenium and c# so I've hit a dead end. I need to know how to check weather an images src file exists or not. When I mean exists, is it showing on the page (not the red x box you get when no image is present).
I have tried file.exists(#c://imagename); and System.File.Exists.
I don't know if this is correct or not.
Any help would be great!! My heads fried with this
Thanks
Assuming that the path to the image is relative in the src attribute you would need to work out the URL then run a test similar to the one outlined in this answer:
Test to see if an image exists in C#
If you really need to check if the image exists and has been deployed (I would question if this is a qorthwhile test to be honest) you could use something like the code below:
HttpWebRequest request = (HttpWebRequest)HttpWebRequest.Create("http://full-path-to-your-image.png");
request.Method = "HEAD";
bool exists;
try
{
request.GetResponse();
exists = true;
}
catch
{
exists = false;
}
It basically checks the URL (of the image in your case), to see if the images exists.
If you need a hand with it turn round and ask ;)
My solutions was to check length of the file.
you can modify this solution to your need:
/// <summary>
/// Gets the file lenght from location.
/// </summary>
/// <param name="location">The location where file location sould be located.</param>
/// <returns>Lenght of the content</returns>
public int GetFileLenghtFromUrlLocation(string location)
{
int len = 0;
int timeoutInSeconds = 5;
// paranoid check for null value
if (string.IsNullOrEmpty(location)) return 0;
// Create a web request to the URL
HttpWebRequest myRequest = (HttpWebRequest)WebRequest.Create(location);
myRequest.Timeout = timeoutInSeconds * 1000;
myRequest.AddRange(1024);
try
{
// Get the web response
HttpWebResponse myResponse = (HttpWebResponse)myRequest.GetResponse();
// Make sure the response is valid
if (HttpStatusCode.OK == myResponse.StatusCode)
{
// Open the response stream
using (Stream myResponseStream = myResponse.GetResponseStream())
{
if (myResponseStream == null) return 0;
using (StreamReader rdr = new StreamReader(myResponseStream))
{
len = rdr.ReadToEnd().Length;
}
}
}
}
catch (Exception err)
{
throw new Exception("Error saving file from URL:" + err.Message, err);
}
return len;
}
You can't do it, at least not solely with Selenium. Depending on which browser you're testing with, you might be able to look into the on-disk browser cache and find the file, but not all browsers cache everything to disk, and figuring out the filename may be very difficult.
Without Selenium, of course, you can use curl, wget, et al. to download the image file, or you could possibly screen-shot the browser and search for the "red X box" yourself. But neither is really a nice answer.

Categories

Resources