Is there any way to determine which files stored in my site collection that are the largest? I would like to identify them somehow and then delete them to free up some space.
Thanks for any ideas.
You could use a site data query to find all documents that are bigger than a certain size:
SPWeb web = SPContext.Current.Web;
SPSiteDataQuery query = new SPSiteDataQuery();
// restrict to document libraries
query.Lists = "<Lists ServerTemplate=\"101\" />";
query.ViewFields = "<FieldRef Name=\"File_x0020_Size\" />";
query.RowLimit = 20;
query.Query = "<Where><Geq><FieldRef Name=\"File_x0020_Size\" /><Value Type=\"Number\">{size in bytes}</Value></Geq></Where><OrderBy><FieldRef Name=\"File_x0020_Size\" Ascending=\"FALSE\" /></OrderBy>";
DataTable bigFiles = web.GetSiteData(query);
Query in readable:
<Where>
<Geq>
<FieldRef Name="File_x0020_Size" />
<Value Type="Number">{size in bytes}</Value>
</Geq>
</Where>
<OrderBy>
<FieldRef Name="File_x0020_Size" Ascending="FALSE" />
</OrderBy>
You have to use SharePoint API and iterate through all items in all lists in all sites in your site collection.
Related
In my first outing with csom and the document library, I encountered a difficult error when attempting to access a document library object property as file.File.Title using the following code.
The error is
Object reference not set to an instance of an object on server.
The code shown is what "works" for my exercise.
What step am I missing to be able to use file.File.Title instead of file.FieldValues["Title"].
The code snippet is a very primitive attempt to get a list of files in the default Document library folder. In a following iteration, I need to update the caml to retrieve a specific file.
var lib = ctx.Web.DefaultDocumentLibrary();
ctx.Load(lib);
ctx.ExecuteQuery();
var files = lib.GetItems(CreateAllFilesQuery());
ctx.Load(files);
ctx.Load(files, items => items.Include( item => item.File.Title ));
ctx.ExecuteQuery();
foreach(var file in files )
{
if(!(file.FieldValues["Title"] == null) )
{
string FileName = file.FieldValues["Title"].ToString();
if (FileName == DocumentName)
return true;
}
}
public static CamlQuery CreateAllFilesQuery()
{
var qry = new CamlQuery();
qry.ViewXml = #"<View Scope=\'FilesOnly\'>
<Query></Query>
<ViewFields>
<FieldRef Name='Title' />
<FieldRef Name='ContentType' />
<FieldRef Name='DocIcon' />
</ViewFields>
</View>";
return qry;
}
After further research, I discovered that my caml query was at fault. The syntax error was placing slashes around the Scope value. The corrected query allows me to reference file.File.Title as expected. The additional benefit is that I am only getting back files rather than files and folders.
qry.ViewXml = #"<View Scope='FilesOnly'>
<Query></Query>
<ViewFields>
<FieldRef Name='Title' />
<FieldRef Name='ContentType' />
<FieldRef Name='DocIcon' />
</ViewFields>
</View>";
I have a list with a lot of documents (> 5000). I need to retrieve one particular document from it. I use this query:
#"<View>
<Query>
<Where>
<Contains>
<FieldRef Name=""FileLeafRef""/>
<Value Type=""Text"">MyDocumentName</Value>
</Contains>
</Where>
</Query>
<RowLimit>1</RowLimit>
</View>"
And I get a ServerException stating that this operation is forbidden because it goes over the list treshold.
But if I remove the <Query> tag:
#"<View>
<RowLimit>1</RowLimit>
</View>"
It works, and retrieve a single file, which sadly isn't the one I wanted, obviously.
So I'm puzzled here. Why is it behaving like that?
Try
Value Type=File
#"<View>
<Query>
<Where>
<Contains>
<FieldRef Name=""FileLeafRef""/>
<Value Type=""File"">MyDocumentName</Value>
</Contains>
</Where>
</Query>
<RowLimit>1</RowLimit>
</View>"
If you don't like building the query by hand then a couple of good tools are:
- U2U CAML Query Builder which gives you an UI for building the query.
- CAML.NET which is a library for safely building CAML queries
After eventually finding the right keywords to ask Google, I found this question.
The problem is that no field in my library is indexed, therefore when I try to add a query with conditions, all the library has to be read through in order to find the document(s) I need. So obviously, if there is too many documents, I get the exception.
<RowLimit> doesn't prevent this behavior, it only acts on the result of the query.
That being said, there is one field that is automatically indexed: ID. So we can change our query a bit to manually page the documents whose ID are between two values, and simply put the query in a while loop, incrementing the current ID paging each time, like so:
ListItemCollection items = null;
const int paging = 2000;
int currentPaging = paging;
while (items == null || items.Count == 0 || currentPaging < 100000)
{
var query = new CamlQuery
{
ViewXml = $"<View><Query><Where><And><Contains><FieldRef Name='FileLeafRef' /><Value Type='File'>MyDocumentName</Value></Contains><And><Leq><FieldRef Name='ID' /><Value Type='Counter'>{currentPaging}</Value></Leq><Gt><FieldRef Name='ID' /><Value Type='Counter'>{currentPaging - paging}</Value></Gt></And></And></Where></Query></View>"
};
items = list.GetItems(query);
ctx.Load(items);
ctx.ExecuteQuery();
currentPaging += paging;
}
Here's the formatted XML used in the query (query.ViewXml), for better readability:
<View>
<Query>
<Where>
<And>
<Contains>
<FieldRef Name='FileLeafRef' />
<Value Type='File'>MyDocumentName</Value>
</Contains>
<And>
<Leq>
<FieldRef Name='ID' />
<Value Type='Counter'>{currentPaging}</Value>
</Leq>
<Gt>
<FieldRef Name='ID' />
<Value Type='Counter'>{currentPaging - paging}</Value>
</Gt>
</And>
</And>
</Where>
</Query>
</View>
I am using SharePoint webservice to retrieve content type from the site. The output looks like this:
<ContentTypes ContentTypeOrder="0x010300971A94A609AC5F4390A1FF87A26CD05D" xmlns="http://schemas.microsoft.com/sharepoint/soap/">
<ContentType Name="Issue" ID="0x010300971A94A609AC5F4390A1FF87A26CD05D"
Description="Track an issue or problem."
Scope="https://practiv1.sharepoint.com/devtest/Lists/issueTracking"
Version="0"
BestMatch="TRUE">
<XmlDocuments>
<XmlDocument NamespaceURI="http://schemas.microsoft.com/sharepoint/v3/contenttype/forms">
<FormTemplates xmlns="http://schemas.microsoft.com/sharepoint/v3/contenttype/forms">
<Display>ListForm</Display>
<Edit>ListForm</Edit>
<New>ListForm</New>
</FormTemplates>
</XmlDocument>
</XmlDocuments>
</ContentType>
<ContentType Name="Folder"
ID="0x01200049A00CD1A9F3944A9AE7BCCAC15B02D4"
Description="Create a new folder."
Scope="https://practiv1.sharepoint.com/devtest/Lists/issueTracking"
Version="0">
<XmlDocuments>
<XmlDocument NamespaceURI="http://schemas.microsoft.com/sharepoint/v3/contenttype/forms">
<FormTemplates xmlns="http://schemas.microsoft.com/sharepoint/v3/contenttype/forms">
<Display>ListForm</Display>
<Edit>ListForm</Edit>
<New>ListForm</New>
</FormTemplates>
</XmlDocument>
</XmlDocuments>
</ContentType>
I want to use xpath to retrieve items. But I used the path like "//ContentType" or "/ContentTypes/ContentType", I couldn't find anything :
var listService = new ListWebService.Lists();
listService.Url = "xxx.sharepoint.com/xxx/_vti_bin/Lists.asmx";
var contents = listService.GetListContentTypes("issueTracking", "0x01");
Can someone help me what wrong with my xpath?
This is a common problem when dealing with XML having default namespace (xmlns="..."). The node where the prefix declared and all it's descendants, if not explicitly specified otherwise, are considered in the default namespace.
You need to register a prefix that points to the namespace URI and use that prefix in your XPath, for example :
var nsManager = new XmlNamespaceManager(new NameTable());
nsManager.AddNamespace("d", "http://schemas.microsoft.com/sharepoint/soap/");
var result = contents.SelectNodes("//d:ContentType", nsManager);
//or using the other XPath : "/d:ContentTypes/d:ContentType"
I am new to caml query and have been struggling for this.
I need the last modified List Item. Only one Item.
That means it should be orderby 'modified' and rowlimit should be 1.
But only rowlimit part of my query is working. Not the orderby part.
This is my Query :
var camlQuery = new SP.CamlQuery();
camlQuery.set_viewXml('<View><Query><OrderBy><FieldRef Name=\'Modified\' Ascending="FALSE"/></OrderBy><RowLimit>1</RowLimit></Query></View>";')
I dont know where I am going wrong.
I even tried removing the Query tags in the above mentioned query.
The query is working, its getting only one record. orderby isnt working i believe.
This is in jQuery. I have written in a function and am calling that function in my Ready function.
Please help me.
Thanks.
In fact, in your example the query returns all results since query contains some errors.
The line:
camlQuery.set_viewXml('<View><Query><OrderBy><FieldRef Name=\'Modified\' Ascending="FALSE"/></OrderBy><RowLimit>1</RowLimit></Query></View>";')
should be replaced with:
camlQuery.set_viewXml('<View><Query><OrderBy><FieldRef Name="Modified" Ascending="FALSE"/></OrderBy></Query><RowLimit>1</RowLimit></View>');
Example: how to get the last item
function getLastItem(listTitle,Success,Error){
var ctx = SP.ClientContext.get_current();
var web = ctx.get_web();
var list = web.get_lists().getByTitle(listTitle);
var query = new SP.CamlQuery();
query.set_viewXml('<View><Query><OrderBy><FieldRef Name="Modified" Ascending="FALSE"/></OrderBy></Query><RowLimit>1</RowLimit></View>');
var items = list.getItems(query);
ctx.load(items);
ctx.executeQueryAsync(
function() {
if(items.get_count() > 0) {
var item = items.getItemAtIndex(0);
Success(item);
}
else
{
Success(null);
}
},
Error
);
}
getLastItem('Contacts',function(item){
console.log(item.get_item('Modified'));
},function(sender,args){
console.log(args.get_message());
});
Rowlimit must be put outside the query. Actually I'm using SharepointPlus (a JavaScript API to deal with Sharepoint) that creates automatically the query for me :-)
So the XML code sent to the server should look like this:
<GetListItems xmlns="http://schemas.microsoft.com/sharepoint/soap/">
<listName>Your list</listName>
<viewName></viewName>
<query>
<Query>
<OrderBy>
<FieldRef Name="Status" Ascending="false"></FieldRef>
</OrderBy>
</Query>
</query>
<rowLimit>1</rowLimit>
<viewFields>
<ViewFields Properties="True">
<FieldRef Name="ID"></FieldRef>
</ViewFields>
</viewFields>
<queryOptions>
<QueryOptions>
<DateInUtc>False</DateInUtc>
<Paging ListItemCollectionPositionNext=""></Paging>
<IncludeAttachmentUrls>True</IncludeAttachmentUrls>
<IncludeMandatoryColumns>False</IncludeMandatoryColumns>
<ExpandUserField>False</ExpandUserField>
<ViewAttributes Scope="Recursive"></ViewAttributes>
</QueryOptions>
</queryOptions>
</GetListItems>
Here there is a full sample, Ascending='True' or Ascending='False' it's case sensitive
<View>
<Query>
<Where>
<Eq>
<FieldRef Name='OrderNum' />
<Value Type='Number'>90696</Value>
</Eq>
</Where>
<OrderBy>
<FieldRef Name='Modified' Ascending='False'/>
</OrderBy>
</Query>
<ViewFields>
<FieldRef Name='Title' />
<FieldRef Name='ID' />
</ViewFields>
<RowLimit>10</RowLimit>
Sharepoint tips
AymKdn is correct, the OrderBy clause should be outside of the Query clause in your Caml. Here's an example:
caml.set_viewXml('<View><OrderBy><FieldRef Name="Modified" Ascending="False"/></OrderBy><RowLimit>1</RowLimit></View>');
The Query clause is used for filtering (Where clause).
I am listing files from multiple folders using the below code:
SPSiteDataQuery q = new SPSiteDataQuery();
q.Lists = "<Lists BaseType='1'/>";
q.Query = "<Where> <Where>
<And><Neq><FieldRef Name='FSObjType'/><Value Type='Lookup'>1</Value></Neq>
<Contains><FieldRef Name='ProjectProperty.Title' /><Value Type='Text'>Site_Name_Value_From_TextBox</Value></Contains>
</And>
</Where></Where>";
q.Webs = "<Webs Scope='Recursive' />";
q.ViewFields = "<FieldRef Name='ID' /><FieldRef Name='LinkFilename' /><FieldRef Name='File_x0020_Type' /><FieldRef Name='Title' /><FieldRef Name='FileRef' /><ListProperty Name='Title' /><ProjectProperty Name='Title' />";
the code is working fine for listing items, but i need to filter items by Site name and Library Name, i used
<Contains><FieldRef Name='ProjectProperty.Title' /><Value Type='Text'>Site_NAme</Value></Contains>
but i get no results, when i use Title or FileRef or any other field filter is working fine, what should i use instead of "ProjectProperty" and "ListProperty "??
Try
<FieldRef Name="SiteName" /><Value Type='Text'>Site_Name</Value>
or
<FieldRef Name="ows_SiteName" /><Value Type='Text'>Site_Name</Value>