3

I have a web part in which I am listing files from a library using RunWithElevatedPrivileges as user doesn't have any rights on that library (not even READ rights). But when user tries to download a file then of course it doesn't work.

Is it possible to somehow let user download file using RunWithElevatedPrivileges?

EDIT

Code

SPSecurity.RunWithElevatedPrivileges(delegate()
{
    using (SPSite site = new SPSite("http://siteURL"))
    {
         using (SPWeb web = site.OpenWeb())
         {
            list = web.Lists["MyLibrary"];
            //Run a loop to display all files in library
         }
    }
});
  • 1
    Please share the code you have so far – Robert Lindgren Dec 17 '16 at 16:15
  • 1
    The simple answer here is that you should give the users read permission, the minimum permissions necessary for them to do their work. – Eric Alexander Dec 17 '16 at 18:33
  • @RobertLindgren Code updated. Not complete code because I am not on that PC but it will give you an idea. – Frank Martin Dec 17 '16 at 18:45
3

If users don't have access to the file, they don't have access to the file, no matter what.
So, if you display real links to the file, as far as SharePoint is concerned, they cannot get the files content; when they click the link, they get an "access denied" message.

Your only option here is to build an applicative (_layouts) page; that page would take the file URL/Id+ListId/what-so-ever as a parameter.
The links to the files you inject from your Web part would be replaced by links to that _layouts page, including the file-identification parameter.
In that page, you would:

  1. Manually check if the incoming user is allowed to download the file, as per your business rules.
  2. Open an elevated section (RunWithElevatedPrivileges)
  3. Get the file content
  4. Inject the file content into the output stream

    // TODO: check if user is allowed to get the file content, as per business rules (since we're by-passing SP permissions)
    
    SPSecurity.RunWithElevatedPrivileges(() =>
    {
        using (SPSite elevatedSite = new SPSite(Request.Url.ToString()))
        {
            using (SPWeb elevatedWeb = elevatedSite.OpenWeb())
            {
                // TODO: Get the SPDocumentLibrary (myDocLib) object + file Id (fileId)
    
                SPListItem item = myDocLib.GetItemById(fileId);
                SPFile file = item.File;
    
                // Open the file content
                using (Stream fileStream = file.OpenBinaryStream())
                {
                    // Prepare to send the file to the output
                    Response.Clear();
                    Response.ContentType = "application/octet-stream";
                    Response.AddHeader("Content-Disposition", "attachment; filename=\"" + file.Name + "\""); // TODO: escape the file name, if needed
                    Response.AddHeader("Content-Length", file.TotalLength.ToString());
    
                    // Send the file by chunks
                    int bytesToRead = 4092;
                    byte[] buffer = new Byte[bytesToRead];
                    int length;
                    do
                    {
                        if (Response.IsClientConnected)
                        {
                            length = fileStream.Read(buffer, 0, bytesToRead);
                            Response.OutputStream.Write(buffer, 0, length);
                            Response.Flush();
                            buffer = new Byte[bytesToRead];
                        }
                        else
                            length = -1;
                    } while (length > 0);
    
                    Response.End();
                }
            }
        }
    });
    

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.