C# 多用户的Memorystream性能问题
我的应用程序中有一个向用户显示PDF的部分。我正在使用memorystream获取此文档。每当我有超过几个用户同时请求文档时,我的应用程序的性能就会降低。如果我有30多个用户,那就是爬网。我的大多数用户说,当他们到达文档时,它开始变慢。以下是我如何称呼该文档的C# 多用户的Memorystream性能问题,c#,asp.net-mvc,pdf,C#,Asp.net Mvc,Pdf,我的应用程序中有一个向用户显示PDF的部分。我正在使用memorystream获取此文档。每当我有超过几个用户同时请求文档时,我的应用程序的性能就会降低。如果我有30多个用户,那就是爬网。我的大多数用户说,当他们到达文档时,它开始变慢。以下是我如何称呼该文档的 public FileStreamResult GetDocument(bool useDefault) { string contentType = string.Empty; short ver
public FileStreamResult GetDocument(bool useDefault)
{
string contentType = string.Empty;
short verificationType = VerificationType();
MemoryStream ms = DocumentToStream(useDefault, out contentType);
if (contentType == string.Empty) contentType = "application/pdf";
HttpContext.Current.Response.Clear();
HttpContext.Current.Response.ClearContent();
HttpContext.Current.Response.ClearHeaders();
HttpContext.Current.Response.ContentType = contentType;
HttpContext.Current.Response.AppendHeader("Content-Disposition", "inline;" + FormFileName());
HttpContext.Current.Response.Buffer = true;
HttpContext.Current.Response.OutputStream.Write(ms.GetBuffer(), 0, ms.GetBuffer().Length);
HttpContext.Current.Response.OutputStream.Flush();
HttpContext.Current.Response.OutputStream.Close();
HttpContext.Current.Response.End();
ms.Close();
if (verificationType == OBDocVerification.Presentation) SetVerified(verificationType);
return new FileStreamResult(HttpContext.Current.Response.OutputStream, contentType);
}
要获取实际文件,它会执行以下操作
private MemoryStream CreatePdfStream(PdfReader pdfDoc, List<MappedField> pdfFields, bool useVerifyButton, bool isLocked, bool isI9, bool isManualUpdate, string state) // 04/26/2018 DS TFS # 3161
{
using (MemoryStream stream = new MemoryStream())
{
PdfStamper stamper = new PdfStamper(pdfDoc, stream);
if (!isLocked)
{
foreach (MappedField mappedFld in pdfFields)
{
if (!string.IsNullOrEmpty(mappedFld.DB_Table))
{
//string v = PDFformFieldValue(mappedFld, this.docLevel);
string v = PDFformFieldValue(mappedFld, this.docLevel, isI9, state); // 10/04/2017 DS TFS # 2768 (added isI9)
if (!string.IsNullOrEmpty(v))
{
stamper.AcroFields.SetField(mappedFld.FormName, v);
}
else
{
stamper.AcroFields.SetField(mappedFld.FormName, string.Empty);
}
if (useVerifyButton)
{
if (!IsPDFformFieldEditable(mappedFld) || !GlobalVariables.IsIE) stamper.AcroFields.SetFieldProperty(mappedFld.FormName, "setfflags", PdfFormField.FF_READ_ONLY, null);
}
}
}
if (isI9) ValidateI9NAFields(ref stamper, pdfFields);
if (!isManualUpdate && GlobalVariables.IsIE) stamper.FormFlattening = true; // 04/26/2018 DS TFS # 3161
}
//else
// stamper.FormFlattening = true;
if (useVerifyButton && GlobalVariables.IsIE)
{
// Add "Verify" button
string alignmentType;
int numberOfPages = pdfDoc.NumberOfPages;
int stampPage = GetVerifyButtonLocation(out alignmentType);
if (stampPage <= 1) stampPage = numberOfPages;
if (stampPage > numberOfPages) stampPage = numberOfPages;
if (alignmentType == string.Empty) alignmentType = "bottom_right";
Rectangle thePage = pdfDoc.GetCropBox(stampPage);
float buttonWidth = 100;
float buttonHeight = 40;
Rectangle ButtonRect = CreateVerifyButtonLocation(thePage, alignmentType, buttonWidth, buttonHeight);
PushbuttonField button = new PushbuttonField(stamper.Writer, ButtonRect, "postSubmit");
button.BackgroundColor = ButtonColor();
button.BorderColor = GrayColor.BLACK;
button.BorderWidth = 1f;
button.BorderStyle = PdfBorderDictionary.STYLE_INSET;
button.TextColor = BaseColor.WHITE;
button.FontSize = 12f;
button.Text = VerifyButtonTitle();
button.Visibility = PushbuttonField.VISIBLE_BUT_DOES_NOT_PRINT;
button.Rotation = pdfDoc.GetPageRotation(stampPage);
PdfFormField field = button.Field;
//field.Put(PdfName.TU, new PdfString("Save changes and return to the folder."));
field.Action = PdfAction.CreateSubmitForm(this.submitUrl, null, PdfAction.SUBMIT_HTML_FORMAT | PdfAction.SUBMIT_INCLUDE_NO_VALUE_FIELDS);
stamper.AddAnnotation(field, stampPage);
}
//else
// stamper.FormFlattening = true;
stamper.Close();
return stream;
}
}
private MemoryStream CreatePdfStream(PDF阅读器pdfDoc,列表PDF字段,布尔useVerifyButton,布尔isLocked,布尔isI9,布尔isManualUpdate,字符串状态)//2018年4月26日DS TFS#3161
{
使用(MemoryStream stream=new MemoryStream())
{
PdfStamper压模=新的PdfStamper(pdfDoc,流);
如果(!已锁定)
{
foreach(pdfFields中的MappedField mappedFld)
{
if(!string.IsNullOrEmpty(mappedFld.DB_Table))
{
//字符串v=PDFformFieldValue(mappedFld,this.docLevel);
字符串v=PDFformFieldValue(mappedFld,this.docLevel,isI9,state);//2017年4月10日DS TFS#2768(添加了isI9)
如果(!string.IsNullOrEmpty(v))
{
stamper.AcroFields.SetField(mappedFld.FormName,v);
}
其他的
{
stamper.AcroFields.SetField(mappedFld.FormName,string.Empty);
}
如果(使用验证按钮)
{
如果(!IsPDFformFieldEditable(mappedFld)| | |!GlobalVariables.IsIE)stamper.AcroFields.SetFieldProperty(mappedFld.FormName,“setfflags”,PdfFormField.FF只读,null);
}
}
}
如果(isI9)验证9NAFIELDS(参考母版、pdfFields);
如果(!isManualUpdate&&GlobalVariables.IsIE)stamper.formflatting=true;//2018年4月26日DS TFS#3161
}
//否则
//stamper.FormFlatting=真;
如果(使用VerifyButton&&GlobalVariables.IsIE)
{
//添加“验证”按钮
字符串对齐类型;
int numberOfPages=pdfDoc.numberOfPages;
int stampPage=GetVerifyButtonLocation(out-alignmentType);
如果(stampPage numberOfPages)stampPage=numberOfPages;
如果(alignmentType==string.Empty)alignmentType=“右下”;
矩形页面=pdfDoc.GetCropBox(stampPage);
浮动按钮宽度=100;
浮动按钮高度=40;
矩形按钮Rect=CreateVerifyButtonLocation(页面、对齐类型、按钮宽度、按钮右侧);
PushbuttonField button=新的PushbuttonField(stamper.Writer、ButtonRect、“postSubmit”);
button.BackgroundColor=ButtonColor();
button.BorderColor=GrayColor.BLACK;
button.BorderWidth=1f;
button.BorderStyle=PdfBorderDictionary.STYLE\u插图;
button.TextColor=BaseColor.WHITE;
button.FontSize=12f;
button.Text=VerifyButtonTitle();
button.Visibility=PushbuttonField.Visibility但不打印;
button.Rotation=pdfDoc.GetPageRotation(stampPage);
PdfFormField字段=按钮字段;
//Put(PdfName.TU,新的PdfString(“保存更改并返回文件夹”);
field.Action=pdpartion.CreateSubmitForm(this.submitur,null,pdpartion.SUBMIT|HTML|FORMAT|pdpartion.SUBMIT|包括|NO|值|字段);
母版添加注释(字段,母版页);
}
//否则
//stamper.FormFlatting=真;
压模关闭();
回流;
}
}
我觉得我在这里可能做了一些低效的事情 这根本不是内存流问题。考虑存储生成的流,然后直接服务它。如果您有一个大的pdf文件和多个用户
您的代码将执行多次,结果相同。我打赌这不是
MemoryStream
错误,而是pdf库。。。无论如何,如果PdfStamper
(不管它是什么)不需要Stream.Seek/设置Stream.Position
,那么使用HttpContext.Current.Response.OutputStream
直接清除MemoryStream
应该很容易。在任何其他情况下,都会出现异常,因为CreatePdfStream
在返回流之前调用流上的Dispose()
。在任何情况下,MemoryStream只不过是字节[]缓冲区上的适配器。它的性能与访问任何字节数组的性能相同。任何性能问题都是由PDF库本身引起的,或者是因为代码在将PDF文档的内容发送到输出流之前,基本上会将其复制到内存中。这使所用RAM的大小增加了一倍。代码应该直接写入Response.OutputStream
,以避免这种双重缓冲