FileUpload size limited by requestLengthDiskThreshold

P

Phil Z.

After migrating an ASP.NET 1.1 application to 2.0 we were getting "Cannot
access a closed file" errors when uploading. I found a number of post on
the subject and have since moved from using an Html File Input control to
using the new FileUpload control.

Previously, I had set the maxRequestLength attribute in the machine.config
file to allow 100MB uploads with success. In the v2.0 application I have
added an httpRuntime node to the web.config and have set
maxRequestLength=102400 as before. I also set the
requestLengthDiskThreshold value to 8192.

After doing this, files up to 8192KB in size were uploadable. I have now
found that the requestLengthDiskThreshold is the limiting value. By this I
mean that files that are smaller than the requestLengthDiskThreshold will
upload, while files larger than the requestLengthDiskThreshold setting
throw the "Cannot access a closed file" exception. This has proved true
with a number of different values entered for the threshold.

My understanding is that the requestLengthDiskThreshold value sets the
amount of the request that is cached in memory, and data beyond this value
is temporarily written to disk. Is this correct? Why am I finding that my
file upload size is limited by the requestLengthDiskThreshold setting?

Thanks much -- phil
 
J

John Timney \(MVP\)

Your understanding of requestLengthDiskThreshold is correct, which suggests
that the underlying stream is being closed prematurely.

Out of interest try setting your maxrequestlength to be significantly larger
than your max file size expected and see if the problem goes away.

Regards

John Timney (MVP)
 
P

Phil Z.

Thanks for the response. I have the maxRequestLength set to 100MB (102400)
and have experienced this behavior with 3 different files, one at about 6MB,
one at about 10MB, and one at about 45MB, all well less than the 100MB
maxRequestLength. In each case if the requestLengthDiskThreshold is set to
less than the file size it fails, and if it's more than the file size it
succeeds.

It makes me wonder if the worker process is unable to save to disk for some
reason... I ran filemon during one test and it did not reveal any problems.
 
W

Walter Wang [MSFT]

Hi Phil,

I'm using following web form to test the FileUpload:

----8<----

<%@ Page Language="C#" %>

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">

<script runat="server">

protected void UploadButton_Click(object sender, EventArgs e)
{
// Specify the path on the server to
// save the uploaded file to.
String savePath = @"c:\temp\uploads\";

// Before attempting to perform operations
// on the file, verify that the FileUpload
// control contains a file.
if (FileUpload1.HasFile)
{
// Get the name of the file to upload.
String fileName = FileUpload1.FileName;

// Append the name of the file to upload to the path.
savePath += fileName;


// Call the SaveAs method to save the
// uploaded file to the specified path.
// This example does not perform all
// the necessary error checking.
// If a file with the same name
// already exists in the specified path,
// the uploaded file overwrites it.
FileUpload1.SaveAs(savePath);

// Notify the user of the name of the file
// was saved under.
UploadStatusLabel.Text = "Your file was saved as " + fileName;
}
else
{
// Notify the user that a file was not uploaded.
UploadStatusLabel.Text = "You did not specify a file to upload.";
}

}
</script>

<html xmlns="http://www.w3.org/1999/xhtml" >
<head id="Head1" runat="server">
<title>FileUpload Example</title>
</head>
<body>
<form id="form1" runat="server">
<div>
<h4>Select a file to upload:</h4>

<asp:FileUpload id="FileUpload1"
runat="server">
</asp:FileUpload>

<br /><br />

<asp:Button id="UploadButton"
Text="Upload file"
OnClick="UploadButton_Click"
runat="server">
</asp:Button>

<hr />

<asp:Label id="UploadStatusLabel"
runat="server">
</asp:Label>
</div>
</form>
</body>
</html>

---->8----

With following settings in web.config:

<httpRuntime maxRequestLength="102400" />

I was able to upload files up to 60MB without problem.

I also have read some similar problems here:
http://channel9.msdn.com/ShowPost.aspx?PostID=106570

I guess you're reading directly from the stream? Could you please post your
code listing here? Thanks.

MaxRequestLength: limits the size of incoming requests, which limits the
size of the uploaded file.

RequestLengthDiskThreshold: controls whether the request is temporarily
stored in memory or on disk while being processed.

If you use FileMon to monitor the asp.net worker process, you will notice
when the uploaded file's size exceeds requestLengthDiskThreshold, a
temporary file gets created at such as:
C:\WINDOWS\Microsoft.NET\Framework\v2.0.50727\Temporary ASP.NET
Files\fileuploadsizelimit\ccca1291\f22cc828, if the file is smaller than
the RequestLengthDiskThreshold, the temporary file is not created.

So I guess your problem is asp.net was unable to create the temporary file
during uploads. But since you mentioned that you've already run FileMon and
it did not reveal any problems, the problem may exist somewhere before
asp.net trying to create the temporary file.

I want to take a look at your code before doing more research.

Sincerely,
Walter Wang ([email protected], remove 'online.')
Microsoft Online Community Support

==================================================
Get notification to my posts through email? Please refer to
http://msdn.microsoft.com/subscriptions/managednewsgroups/default.aspx#notif
ications.

Note: The MSDN Managed Newsgroup support offering is for non-urgent issues
where an initial response from the community or a Microsoft Support
Engineer within 1 business day is acceptable. Please note that each follow
up response may take approximately 2 business days as the support
professional working with you may need further investigation to reach the
most efficient resolution. The offering is not appropriate for situations
that require urgent, real-time or phone-based interactions or complex
project analysis and dump analysis issues. Issues of this nature are best
handled working with a dedicated Microsoft Support Engineer by contacting
Microsoft Customer Support Services (CSS) at
http://msdn.microsoft.com/subscriptions/support/default.aspx.
==================================================

This posting is provided "AS IS" with no warranties, and confers no rights.
 
P

Phil Z.

Thanks Walter.

The code is distributed through our app a bit, but we retrieve the
HttpPostedFile from the FileUpload control and then send the HttpPostedFile
to another function that performs the save:

HttpPostedFile newPostedFile = FileUpload1.PostedFile;

string tempFile = @"\\CSCSRVWDC2DB4\data\SWIFT File Vault Temp\" +
docFileFullName;
newPostedFile.SaveAs(tempFile);


Note that a UNC path is used for the save as the web server is saving the
files to the database server. The exception is thrown on the SaveAs() line.

More information: I examined CREATEs using FileMon and the temp files are
being created as described when the requestLengthDiskThreshold setting is
less than the uploaded file size. Actually, a file is also being created in
the final UNC destination, but the file has no size, and the exception is
thrown.

I have attached the FileMon output filtered for file CREATEs for a file
upload that failed.

If the file size is less than the requestLengthDiskThreshold setting the
upload is successful, and no temp files are created. If the uploaded file
size is greater than the requestLengthDiskThreshold setting, a temp file is
created as expected, and then a file with the correct name and no size is
created in the final UNC destination before the "Cannot access a closed
file" exception is thrown.

-phil
 
P

Phil Z.

Thanks Walter.

The code is distributed through our app a bit, but we retrieve the
HttpPostedFile from the FileUpload control and then send the HttpPostedFile
to another function that performs the save:

HttpPostedFile newPostedFile = FileUpload1.PostedFile;

string tempFile = @"\\CSCSRVWDC2DB4\data\SWIFT File Vault Temp\" +
docFileFullName;
newPostedFile.SaveAs(tempFile);

Note that a UNC path is used for the save as the web server is saving the
files to the database server. The exception is thrown on the SaveAs() line.

More information: I examined CREATEs using FileMon and the temp files are
being created as described when the uploaded file size is greater than the
requestLengthDiskThreshold setting. Actually, a file is also being created
in the final UNC destination, but the file has no size, and the error is
thrown.

I have attached the FileMon output filtered for file CREATEs for a file
upload that failed.

If the file size is less than the requestLengthDiskThreshold setting the
upload is successful, and no temp files are created. If the uploaded file
size is greater than the requestLengthDiskThreshold setting a temp file is
created as expected, and then a file with the correct name and no size is
created in the final UNC destination before the "Cannot access a closed
file" exception is thrown.

-phil
 
W

Walter Wang [MSFT]

Hi Phil,

Since you're saving the file to a network path, I guess you must be using
impersonating, right?

Again I've changed my test like yours to save to UNC path:

web.config:

<authentication mode="Windows"/>
<identity impersonate="true"/>

default.aspx:

private void SaveFile(HttpPostedFile file)
{
String savePath = @"\\server\temp$\uploads\";
String fileName = file.FileName;
int i = fileName.LastIndexOf(@"\");
if (i >= 0) fileName = fileName.Substring(i + 1);

savePath += fileName;

file.SaveAs(savePath);

UploadStatusLabel.Text = "Your file was saved as " + fileName;
}

protected void UploadButton_Click(object sender, EventArgs e)
{
if (FileUpload1.HasFile)
{
SaveFile(FileUpload1.PostedFile);
}
else
{
UploadStatusLabel.Text = "You did not specify a file to
upload.";
}
}

And it still works correctly.

Have you tried to save to local path?

From your attached filemon log, you're using IIS5 instead of IIS6, right?

Is it possible for you to create a simpler repro project and send it to me?
Thanks.


Regards,
Walter Wang ([email protected], remove 'online.')
Microsoft Online Community Support

==================================================
When responding to posts, please "Reply to Group" via your newsreader so
that others may learn and benefit from your issue.
==================================================

This posting is provided "AS IS" with no warranties, and confers no rights.
 
G

Guest

Since you're saving the file to a network path, I guess you must be using
impersonating, right?

Yes, and we're using setreg:
<identity impersonate="true"
userName="registry:HKLM\SOFTWARE\SWIFT\identity\ASPNET_SETREG,userName"
password="registry:HKLM\SOFTWARE\SWIFT\identity\ASPNET_SETREG,password"/>

Have you tried to save to local path?
I have, and the the behavior is the same. We still get the exception and
save a file with no size.
From your attached filemon log, you're using IIS5 instead of IIS6, right?

I'm currently working on my development workstation which is running Windows
XP, so it's got IIS5.1. The app will be deployed under Windows 2003 server
and IIS6. You still can't run IIS6 under XP right?
Is it possible for you to create a simpler repro project and send it to me?
Thanks.

I will work on this right away.
 
W

Walter Wang [MSFT]

Hi Phil,

Thanks for your repro code. This behavior is expected because:

When the uploaded file's content is bigger than RequestLengthDiskThreshold,
a temporary file is created which is associated with current Request. When
you do a redirect, current Request is disposed and the file is closed.
Although you kept the HttpPostedFile in session, when you call SaveAs, it
tries to read from a closed file object, thus throws the exception.

Hope this helps. Please feel free to post here if anything is unclear.

Regards,
Walter Wang ([email protected], remove 'online.')
Microsoft Online Community Support

==================================================
When responding to posts, please "Reply to Group" via your newsreader so
that others may learn and benefit from your issue.
==================================================

This posting is provided "AS IS" with no warranties, and confers no rights.
 
P

Phil Z.

Once I found that the redirect was causing the behavior, I figured that this
was the case. I guess that the simple asnwer would be to set the
RequestLengthDiskThreshold to be the same value as the MaxRequestLength and
then the entire uploaded file is kept in memory and no data is lost with the
redirect. This would mimic the behavior of ASP.NET 1.1, correct?

I'd rather figure out a way to take advantage of the new capability, but
we're using the redirect for user confirmations that are required...

-phil
 
S

Steven Cheng[MSFT]

Hello Phil,

Sorry for the late response since Walter has been absent due to some urgent
issue.

Yes, you're right. For ASP.NET 2.0 web application, if you set the
"RequestLengthDiskThreshold" the same value as "MaxRequestLengh", it will
behave like ASP.NET 1.1. Actually, the "RequestLengthDiskThreshold"
feature added in 2.0 is to address some potential memory issue when
uploading large files in ASP.NET application.

For your scenario, since you want to keep a reference to the uploaded file
content in session state, is this a frequent operation in your web
application? Even though we can set "RequestLengthDiskThreshold" ==
"MaxRequestLengh" to workaround the issue, I would not recommend this
because this will cause memory issue when there're large number of
fileupload requests and the file size is not very small.

Do you think it possible that we put a temp sub folder in our web
application and always explicitly save the HttpPostedFiles into that
folder as a temp file(adding some identity and timestamp into the temp
file's name). Thus, we can simply store he temp file name into SessionState
for late reference. Also, for this temp file folder, we can create a
background thread to closely monitoring it and delete those long idled
files(according the timestamp in file name).

Please feel free to let me know if there is any other information you
wonder.

Sincerely,

Steven Cheng

Microsoft MSDN Online Support Lead


This posting is provided "AS IS" with no warranties, and confers no rights.
 
P

Phil Z.

The application works as you suggest -- we create a unique name and save the
file to a temp folder. The reason that we save the posted file to the
session is so that we can redirect the user to a confirmation page that
allows them to cancel and therefore not save the file (SaveAs() won't get
called).

I understand the possible memory problems that might ensue without limiting
each user's memory for the request. I expect that the posting of the file
to the web server is where most of the time is spent rather in the save, so
we'll likely change the application to save all files to the temp folder
before redirecting the user for any possible confirmations. This will allow
us to make use of the new memory management capabilities provided with the
RequestLengthDiskThreshold.

I'll run some tests to evaluate where best to set the threshold, but agree
that something significantly less than the 102400 that we're allowing for
the maximum request length should be used for the threshold.

Thank you --phil
 
S

Steven Cheng[MSFT]

Thanks for your followup and let me know your progress on this.

Yes, uploading large file is both memory and time consuming at ASP.NET
layer, that's also why there are some ones who will use RAW ISAPI filter
for file uploading.

Anyway, if you meet any further problem later or any other information we
can provide, please feel free to let me know.

Good luck!

Sincerely,

Steven Cheng

Microsoft MSDN Online Support Lead


This posting is provided "AS IS" with no warranties, and confers no rights.
 
Joined
Oct 3, 2007
Messages
1
Reaction score
0
I am having the same issue

I have the same issue with large files. I also have the webconfig set up with the following.
<httpRuntime requestLengthDiskThreshold="8192"/>


This is the function I call it is an arraylist of filepaths so they can upload multiple files.


Public Function UploadFiles(ByVal FileInputList As ArrayList, ByVal TaskActivityID As String) As Boolean


Dim strUpLoadLoc As String
Dim ErrorUpload As Boolean
Dim intFilesUploaded As Integer
Dim strOrigFileName As String
Dim strAttFileName As String
Dim strExtension As String
Dim strContentType As String
Dim AttachID As String

intFilesUploaded = 0
strUpLoadLoc = ""
ErrorUpload = False

If (FileInputList.Count > 0) Then

'INSTANCIATING A NEW fileUpload FOR EACH ITEM IN THE FILEINPUTLIST ARRAY.
For Each FileInput As FileUpload In FileInputList

Try
strOrigFileName = System.IO.Path.GetFileName(FileInput.PostedFile.FileName)
strExtension = System.IO.Path.GetExtension(strOrigFileName)
strContentType = FileInput.PostedFile.ContentType
'INSERTING INTO THE ATTACHMENT TABLE
AttachID = clsData.InsertRecord(clsSQL.InsertAttachmentCommand(TaskActivityID, strOrigFileName, strContentType, strExtension, SessionManager.UserName, DateTime.Now.ToShortDateString), "CN_STR_TASK")
strAttFileName = AttachID + strExtension 'InsertAttachment(TaskActivityID, strOrigFileName, strContentType, strExtension, SessionManager.UserName, DateTime.Now.ToShortDateString)
clsData.UpdateRecord(clsSQL.UpdateAttachmentFileNameCommand(strAttFileName, AttachID), "CN_STR_TASKMASTER")
strUpLoadLoc = System.Configuration.ConfigurationManager.AppSettings.Get("AttachmentDir") & strAttFileName


FileInput.PostedFile.SaveAs(strUpLoadLoc) 'SAVING FILE TO SERVER
intFilesUploaded += 1 'INCREMENTING COUNT
ErrorUpload = False

Catch ex As Exception
clsCommon.LogError("wfTaskActivity", "UploadFiles", ex)
System.Diagnostics.Trace.Write(ex)
ErrorUpload = True
Response.Redirect("errorPage.aspx", False)
End Try
Next

FileInputList.Clear() 'CLEARING THE ARRAY

End If

Return ErrorUpload

End Function
 
Joined
Jul 22, 2008
Messages
1
Reaction score
0
Hi guys, I've been reading this thread which was very helpful. I'm currently setting "RequestLengthDiskThreshold" == "MaxRequestLengh" as temporary work around for user to upload files larger than 80K. The problem I'm encountering is that everything works fine when I run the application from VS on my development machine, I can see temporary files are been created. But when I deployed to the test web server, the uploading process stops at 80K, and no temproary files or 'upload' directory were created.
Can somebody help me with this problem please?

Thank you
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
473,769
Messages
2,569,578
Members
45,052
Latest member
LucyCarper

Latest Threads

Top