Tuesday, November 11, 2008

Forcing a PDF to download in browser and Adobe error

A while back I had a request to offer two options to access a PDF file from a SharePoint site. One was to allow the PDF to open in the browser like normal and the second was to force the download prompt to the user. The second one was a little more tricky and I finally found a way to send the file in the Reponse in code and send it as an attachment and thus prompt the user to download the file. The code for that looks like this:



'Create an array that contains the contents of the file.

Dim mystream As Byte() = file.OpenBinary


'Clear the Response headers and set the response to be an attachment

Response.ClearHeaders()

Response.ContentType = "APPLICATION/PDF"

Response.Clear()

Response.AddHeader("Content-Disposition", "attachment; filename=" & file.Name) Response.BinaryWrite(mystream)


This seemed to do the trick until the other day when I had a client call and say that when they used the download mechanism to open the file and save it to their desktop they were getting an error in Adobe Reader 7. I tested it out and found the same issue when I downloaded the file. The error said that the file was corrupted and that reader could not repair it. I could open the file just fine using Adobe Reader 8.


The solution to this issue turns out to be that I missed a line of code in the above block that must leave the PDF file unwritten and Adobe Reader 8 can repair the file but 7 can't. I found a post by Rahul that described 4 different ways to download a PDF file. In one of the ways was the way I had used to force the download. I noticed a line that said Response. End().


I added this line to my code and suddenly the PDF files were no longer corrupt and could be opened in Adobe 7 as well as 8.


The final code ended up looking like this:


'Create an array that contains the contents of the file.

Dim mystream As Byte() = file.OpenBinary


'Clear the Response headers and set the response to be an attachment

Response.ClearHeaders()

Response.ContentType = "APPLICATION/PDF"

Response.Clear()

Response.AddHeader("Content-Disposition", "attachment; filename=" & file.Name) Response.BinaryWrite(mystream)

Response.End()


The nice thing about the above code is that the file.OpenBinary method is an SPFile method that opens a file from SharePoint as a byte array. It works really well for items like this.

Labels: ,

Tuesday, November 4, 2008

When STSADM Export runs out of space

A little while back I had a client that called about a script we had created to automate SharePoint site backups. The script was written in PowerShell and basically went through the entire site and exported each site to a directory and then moved onto each subsite of that site. Once all of the sites were exported, it zipped all the files up and created one ZIP file.


The client was calling because the backups seemed to be sporadic in size. One dat the backup file would be 14GB and then the next it would be 35GB and then it would be 8GB. I knew that the script was not doing anything special so I looked into the client's server and found that there was only about 100MB of free space on their hard drive. It then made sense to me that the size of the files was so sporadic. What was happening is that there would be enough space on the drive to complete the first day's backup. Since the script was keeping 7 days of files, when it got to the next day it could complete that backup. But by the 6th or 7th day there was not enough space on the drive so it would back up what it could until it ran out of space and then fail. The next day the script would run and delete one of the large backup files and there would once again be enough space to backup completely. This would continue on.


I told the client that they would need more disk space as they were running out and that is why the files were different sizes. I just heard back from the client the other day and they said that the files were now the same size.


The reason I knew that the script was bombing out and just finishing was that I tried manually doing an export of a fairly large site and the export failed when disk space ran out but still created a file that just didn't include the entire site. Once you know that you would see why there were no errors anyplace to indicate a problem.

Labels: ,

Monday, October 27, 2008

Application Pages in SharePoint

Application pages allow you to create custom screens in SharePoint and make them available at any site level, similar to the accessdenied.aspx and error.aspx that come out of the box with SharePoint. To create an application page, follow the article by Ted Pattison to get the minimal code that is needed in an application page.


Once you have the page built you place it in the 12 hive in the Layouts folder. To access your cuastom page you then navigate to a site (i.e. http://sharepointserver/site/_layouts/nameofcustompage.aspx. This will display your custom page. You can access it at any level of your site.


Application pages provide an excellent way to add custom code to your site and can be debugged by attaching to the W3WP process on the SharePoint server that matches the AppId of the site you want.

Labels: , ,

Tuesday, October 21, 2008

The Network Path was not found. in SharePoint Search

Today I was working with Search Server Express 2008 to index a folder share on our network. I set up the share and pointed it to the correct path. I then set the content source to run a full crawl and monitored the results of the crawl. After 7 seconds it had finished the crawl and I knew that that was a little too soon considering there were a few items in that folder. So I took a look at the crawl logs and saw that there was an error that said 'The Network Path was not found.' So I clicked on the link that is above the error and was able to open the path just fine.


I then thought about the account that the crawl was running as and the account that I am using when clicking on the link. So I tried indexing a folder share that the content crawling account did have access to and it was able to index the content without any problems.


Something to keep in mind when using the SharePoint search or Search Server 2008: make sure that your content crawl access account has access to the content you want to crawl because the error log will not report a useful error. If you try to look into the SharePoint 12 hive logs you will not see any errors in there. So if you run across 'The Network Path was not found' error check the permissions on the share to make sure your index account has access to it.

Labels: , ,

Thursday, October 16, 2008

Minimal Master Page

One of the things I frequently find myself doing is creating a master page for some custom layout. There are many controls that need to be on a master page or errors will be thrown by SharePoint. To make sure you have all the controls the first time, Microsoft created an article with the code needed to create a minimal master page.


I use this article all the time and thought other people would like to have a place to go instead of trying to figure out what controls are needed.

Labels: , ,

Wednesday, October 15, 2008

User Information List

The other day I was trying to create a list event receiver that would fire when a user was added to SharePoint. I did some research and found the User Information List, which is the list that contains all the users in SharePoint. You access this list when you click on the People and Groups link. I built the event receiver and attached it to the list and added some users, only to find out that the event was not firing.

I did some debugging and the code was working fine, so I decided to attach the event receiver to another custom list and added some items to that. The event receiver fired perfectly. I used the U2U CAML Query Builder to run some queries against the User Information List and was able to get back the type of data I wanted in my event receiver.

I tried to do some more research and could not find anyone else out there that was trying to do the same thing as me and so I came to the conclusion that there is some special setting on the User Information List that does not allow the events to fire. I will keep this on the list of items to watch out for and if anyone has any ideas feel free to let me know.

Labels:

Sunday, October 12, 2008

Remote Debugging Custom Code in SharePoint

The other day I ran into a situation where I needed to debug an assembly that I had placed in the GAC of the SharePoint server and did not have Visual Studio installed on the SharePoint machine. I knew there were ways to attach to a process so I did a search to see if there was a way I could remotely attach to the process from Visual Studio running on my machine.


The process is pretty easy:


1. Locate the msvsmon.exe file located in C:\Program Files\Microsoft Visual Studio 8\Common7\IDE\Remote Debugger\x86. This file is located on the machine that has Visual Studio installed on it.


2. Copy this file to the machine that you want to debug the code on (the SharePoint machine).


3. Run the exe. This will create a small window on the server that says the remote debugging server is waiting.


4. In Visual Studio on your machine, select Tools -> Attach to Process.


5. Get the process ID for the SharePoint web app you want to debug. You can do this by running the iisapp command from the SharePoint server command line. This will list the AppIDs and the name of the Web applications running on your server.


6. In the Attach to Process dialog, in the Qualifier drop down select the browse button and browse for the SharePoint machine.


7. Once you have the machine, select the process name (w3wp.exe) and the ID that matches the Web app that you want to debug.


8. Click attach and start debugging.


This works fairly well. Some things you are trying to do will not work all that well with the remote debugging, such as updating a list item, but it will allow you to step through your code to figure out why something might not be working.

Labels: