【问题标题】:PDF file fails upload on asp.net application在 asp.net 应用程序上上传 PDF 文件失败
【发布时间】:2022-01-14 21:46:46
【问题描述】:

我有一个 ASP.NET 应用程序运行在:

Windows Server 2019 标准版

IIS 版本 10.0.17763.1

应用程序设置为使用 HTTPS

应用程序正在使用库 System.Web.UI.WebControls.FileUpload 进行文件上传

应用程序正在使用 QuickPDFDLL0811.dll 读取 PDF 文件并计算页数

用户一直报告某些 PDF 文件无法上传。 chrome 浏览器选项卡显示一个微调器,好像应用程序正在做某事,然后用户会看到“无法访问该站点”页面(附加)。但是,同样的用户表示他们已经通过我在 google here 上找到的步骤获取了错误的相同 PDF 文件,然后他们能够成功上传文件。

另外,我拿了在生产中上传失败的同一个文件:

  1. 通过 HTTP 和 chrome 上传到 PROD 应用运行的服务器中,并成功。
  2. 在我们的测试环境中使用 chrome 并通过 HTTP 和 HTTPS 上传并成功。

我无法共享这些文件,因为它们包含敏感数据。

有没有人遇到过类似的问题?或者有人可以提供任何指导吗?我从公司 docusign.com 中找到了一个 URL,这一事实向我表明这是一个常见问题。

编辑: 我正在添加触发问题时执行的代码(BtnUploadClick)。我忘了提及我还查看了 IIS 日志文件,但没有记录任何响应不成功的内容。

(我为奇怪的格式道歉,当我从 VSCode 复制/粘贴时,Stackoverflow 搞砸了)

protected void BtnUploadClick(object sender, EventArgs e)
{
try
{
    if (FileUpload.HasFiles)
    {
        
        foreach (var FileUpload in FileUpload.PostedFiles)
        {
            var uploadResult = Uploadfile(lstPrn, FileUpload);
            if (uploadResult.ReturnResponse == 
                             Enumerators.ResponseEnum.Success)
            {
                var objPrintFile = uploadResult.ReturnObject;
                lstPrn.Add(objPrintFile.FileName.ToUpper(), 
                           objPrintFile);
            }
        } 
    }
    else
    {
        lblFileCheck.Text = "You have not specified a file.";
        lblFileCheck.ForeColor = Color.Red;
    }
}
catch (Exception exception)
{
    //Log exception
}
}

private Response<PrintFile> Uploadfile(Hashtable lstPrn, 
HttpPostedFile FileUpload)
{
var result = new Response<PrintFile>();
var msg = "";
try
{
    if (Path.GetExtension(fileToWork).ToLower() == ".pdf")
    {
        PdfUtil myPdfUtil = new PdfUtil();

        objPrintFile.FileName = fileToWork;
        objPrintFile.ExpectedDocs = 
                myPdfUtil.GetNumberOfPdfPages(path + fileToWork);
        if (objPrintFile.ExpectedDocs > 0)
        {
            //Map object here
            try
            {
                Session.Add("NewRequestPrintFiles", lstPrn);

                result.ReturnResponse = 
                 Enumerators.ResponseEnum.Success;
                result.ReturnObject = objPrintFile;

                btnNextUpload.Enabled = true;
            }
            catch
            {
                //log message here
            }
        }
    }
}
catch (Exception ex)
{
    //Log error
}

return result;
}

public int GetNumberOfPdfPages(string fileName)
{
int totPages = 0;

if (!string.IsNullOrEmpty(fileName))
{
    using (StreamReader sr = new 
    StreamReader(File.OpenRead(fileName)))
    {
        Regex regex = new Regex(@"/Type\s*/Page[^s]");

        int bufSize = 10 * 1024;
        int lastPorSize = 20;
        char[] myBuffer = new char[bufSize + 1];
        char[] lastPortion = new char[lastPorSize];

        for (int c = 0; c < lastPorSize; c++)
            lastPortion[c] = '*';

        try
        {
            //read it by chunks!!
            while (!sr.EndOfStream)
            {
                int nBytes = sr.ReadBlock(myBuffer, 0, bufSize);
                string strToSerach = new string(lastPortion, 0, 
                lastPorSize) + new string(myBuffer, 0, nBytes);

                MatchCollection matches = 
                regex.Matches(strToSerach);
                foreach (Match match in matches)
                {
                    if (match.Index >= nBytes)
                    {
                        // I have to clean up if there is a match
                        // at the end of strToSerach because I 
                        //don't want that to be copied over
                        // lastPortion and count again on the 
                        //next iteration.
                        for (int c = 0; c < match.Length; c++)
                        {
                            if (match.Index + c > lastPorSize)
                                myBuffer[match.Index + c - 
                                lastPorSize] = '*';
                        }
                    }
                }

                for (int c = 0; c < lastPorSize; c++)
                {
                    if ((nBytes - lastPorSize + c) >= 0)
                    {
                        lastPortion[c] = myBuffer[nBytes - 
                                         lastPorSize + c];    
                    }
                }

                totPages += matches.Count;
            }
        }
        catch (Exception ex)
        {
            totPages = 0;
        }
    }
}
else
    totPages = 0;

return totPages;
}

编辑

我附上文件的屏幕截图。 File1 与 File2 相同,但请注意 File1 通过“打印为 PDF”的过程获取然后保存到本地时存在大小差异。 File1 上传失败,而 File2 上传成功。

【问题讨论】:

  • @Austin 我想我的意思是说 ASP.NET,因为文件扩展名以 .aspx 结尾,所以我附上了代码
  • @Austin 没有任何块触发,似乎调用甚至没有到达服务器,因为我无法在 IIS 日志中找到它。

标签: c# asp.net pdf


【解决方案1】:

您的问题与经验有关,您希望遇到同样错误的人回答您。但是你的问题需要一些细节。虽然我会尽力回答你。

你描述的场景可能来自三件事......

  1. 使用编辑器或 Visual Studio 等 IDE 部署某些应用程序时,您会注意到并非所有文件夹/目录都已发布。当您部署到生产环境或机器上时,有些不存在。因此,这意味着当您最终部署应用程序时,它不会包含您尝试将数据上传到的文件夹,并且如果您的代码不包含检查目录是否存在并在它时创建它的块没有找到,代码失败。 (此过程是使用 Visual Studio IDE 发布的)。

所以确保你的代码检查目录是否存在,否则创建它。

  1. 当目录的安全设置不允许写入时。可以是只读的,不能读/写。

您需要授予对您尝试将数据上传到的目录的写入权限。

  1. 资源的绝对路径。有时,在代码中,您正在写入或上传到的文件夹的路径在生产环境中可能会有所不同。

确保生产机器与您的开发环境具有相同的部署资源路径。

注意:以上三种情况都可以使代码在测试机器上运行,但不能在生产环境中运行,因为如果您在本地机器上进行测试,它可能会包含您正在写入或上传到的目录。并且大多数时候不需要在开发人员机器上授予读/写访问权限,但在生产中,你肯定会这样做。当我未能检查目录是否存在并且我直接从我的 Visual Studio IDE 发布到 Microsoft Azure 时,它​​发生在我身上。当我尝试上传图片时,由于找不到目录而失败。虽然没有出现错误信息。

【讨论】:

  • 感谢您的回复。如果所有 pdf 文件都失败,您描述的场景将是准确的。就我而言,有时 PDF 文件会上传,有时不会。如果上传失败的PDF文件被带到Docusign url中描述的转换过程,那么文件将成功上传。所以我认为这与目录或权限无关。
  • 好的。那你的问题解决了吗?如果没有,那么您应该检查您的应用程序的表单身份验证/验证配置。
  • 不,问题还没有解决。我正在寻找不同的替代方案,看看会是什么
【解决方案2】:

我冒昧地猜测上传失败的 PDF 文件大于 4MB。如果是这样,您遇到的是经典 asp.NET 应用程序的默认请求限制。

请参阅此问题的答案以了解如何解决此问题: How to increase the max upload file size in ASP.NET?

您看到的“连接已重置”的行为是因为服务器在达到限制时关闭了连接。它必须这样做,因为在完全接收到请求之前它无法发送响应,因此它除了终止连接之外别无选择,这会导致您在浏览器中看到错误。存在此限制的原因是出于安全原因:恶意客户端可能会以极慢的速度发送极大的请求,从而使您的服务器资源不堪重负。出于类似的原因,Web 服务器通常也要求客户端以合理的速率传输数据。

显然,在 ASP.NET 核心中,请求限制默认值被提高到了 30MB,可能是因为 4MB 限制在现代网络上过于严格。

【讨论】:

  • 感谢您的回复,这是我对文件的了解(我将在问题中添加屏幕截图)。名为“File1-FailsToUpload.pdf”的文件是用户报告的上传失败的文件。它只有 402KB。我们通过“Microsoft print to PDF”的过程将同一个文件保存到本地(“File2-Microsoft Print to PDF-UploadsSuccesfully.pdf”),大小为897KB,上传成功。所以我相信在这种情况下文件的大小不是问题。
  • @jorgeAChacon 另一种可能性是 ASP.NET 请求验证导致问题,您可以尝试为上传页面禁用该功能并查看是否可以解决问题。 docs.microsoft.com/en-us/previous-versions/aspnet/…
【解决方案3】:

我不得不让网络团队参与进来,因为 IIS 甚至没有记录该请求。他们提到他们已经应用了一些安全规则,我们的应用程序受到了影响。在对他们应用的规则进行例外处理后,我们能够成功上传之前失败的文件。我无法准确说出应用了哪些类型的规则,因为我不与那个团队合作,但他们使用名为“F5”的工具管理我们的流量路由和负载平衡。 谢谢你们的时间和指导。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-12-08
    • 2022-11-17
    • 1970-01-01
    • 2011-05-02
    • 1970-01-01
    • 2012-05-30
    相关资源
    最近更新 更多