简体   繁体   中英

ASP.NET Core download from a Network Share (sometimes works?)

I have a pretty standard ASP.NET Core 2.2 web app. I'm running into an issue with downloading files that are stored on a Network Share. We are using a method of impersonation in code (client requirements) to access the file share. Uploading to the share with the provided credentials works fine, so we know that (a) the impersonation is working and (b) the files ARE at the destination. The issue I am having comes from Downloading the file. It's a pretty standard download link that points to an action in a controller that gets the file information from the database and uses two of the database values (PathToFile and Filename) to get the location of the file and pull it back to the controller, followed by returning a file:

        var fileRecord = //Get the record from the database.

        byte[] bytes = null;
        if(fileRecord != null)
        {
            try
            {
                string fullPath = $"{fileRecord.PathToFile}\\{fileRecord.Filename}";

                await ImpersonationHelper.Impersonate(async () => { bytes = await System.IO.File.ReadAllBytesAsync(fullPath); }, _settings);

            }
            catch (Exception e)
            {
                return NotFound();
            }
        }

        return File(bytes, System.Net.Mime.MediaTypeNames.Application.Octet, fileRecord.Filename);

For reference:

    public static async Task Impersonate(Action actionToExecute, ApplicationSettings settings)
    {
        IntPtr tokenHandle = new IntPtr(0);

        SafeAccessTokenHandle safeAccessTokenHandle = null;

        ImpersonateLogin login = new ImpersonateLogin(settings);

        Task<bool> returnValue = Task.Run(() => LogonUser(login.username, login.domain, login.password, 2, 0, out safeAccessTokenHandle));

        if (false == returnValue.Result)
        {
            int ret = Marshal.GetLastWin32Error();
            throw new System.ComponentModel.Win32Exception(ret);
        }

        if(safeAccessTokenHandle != null)
        await returnValue.ContinueWith(antecedent => WindowsIdentity.RunImpersonated(safeAccessTokenHandle, () =>
        {
            actionToExecute();
        }));
    }
}

Locally, it works fine (we skip the impersonation with an appsetting) and the file comes back and set up as a download in the browser.

On the server, however, it doesn't work, but it also does work. It's strange: Clicking on the link will lead to an error page:

错误页面信息

but refreshing this error page (ie. re-requesting that file) over and over again will make it work (usually every 2-4 refreshes will return the file correctly).

Has anyone encountered this, or something like this that can offer some insight?

As it turns out, it (seemingly?) had something to do with the method(s) being async. Once I removed the (forced) async call to the impersonation, and all async calls right to the "Download" action, it all lined up and works 100% of the time now. From what I could find online, it looks like it was a "timing" issue with async/sync calls. The impersonation would happen AFTER the download file, so the user wouldn't have permission to actually fetch the file to download, but in some cases, the impersonation would happen first, so the file would come back. Making everything "non-async" fixed the issues I was having.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM