views:

1531

answers:

2

I have a file upload page with an AsyncFileUpload control. When the user browses to the file the upload control pulls the file into memory. I then have an Upload button which fires the following code to save the file to a database.

I am finding that if files are over about 500KB then the FileBytes property of the control simply returns null. This happens on my server but when running the app locally it runs through fine.

I'm not handling the OnUploadCompleted event as I need to user to complete further information before committing the file to database.

I have this in my web.config: httpRuntime maxRequestLength="10000"/>

private void UploadDocument(int mietID)
{
    if (Page.IsValid)
    {
        if (mietID > 0)
        {
            if (File1.HasFile && File1.FileBytes != null)
            {
                string[] docFormats = MIETPConfig.Current.SupportedDocumentFormats;

                for (short i = 0; i < docFormats.Length; i++)
                    docFormats[i] = docFormats[i].ToUpper();

                if (docFormats.Contains(Path.GetExtension(File1.FileName).ToUpper()))
                {
                    try
                    {
                        byte[] uploadedBytes = File1.FileBytes;
                        DocumentController.CreateDocument(txtLinkText.Text, Path.GetFileName(File1.PostedFile.FileName), uploadedBytes, mietID, (User)Session["User"]);

                        MietpClientScripts.CloseWindow(Page);
                    }
                    catch (Exception)
                    {
                        lblUploadStatus.Text = "There was an error saving the document to the database.";
                    }
                }
                else
                {
                    System.Text.StringBuilder sb = new System.Text.StringBuilder();
                    foreach (string s in docFormats)
                        sb.Append(s + ", ");

                    sb.Remove(sb.Length - 2, 2);
                    lblUploadStatus.Text = "Invalid file format, only these formats are supported: " + sb.ToString();
                }
            }
            else
            {
                lblUploadStatus.Text = "There was an error saving the document, the document could not be read; it might be too large to upload.";
            }
        }
        else
            lblUploadStatus.Text = "No Mietp ID to associate document with.";
    }
}
+2  A: 

I am not totally sure, but I can imagine that the max bytes in FileBytes is limited due to the fact that alot of file uploads would take up a lot of RAM. Your hostingpartner might have limited this. Probably your hoster has set the <httpRuntime maxRequestLength="XXX" /> to 512 KB by default.

Try saving the file using SaveAs(path). This is basically what you are doing at this point, but you'll let the control figure out when to flush to the file, avoiding taking the whole file in memory, or grab the filestream using FileContent if you really need access to the raw content. Also change <httpRuntime maxRequestLength="XXX" /> to something like 102400 to override the default settings from your hoster.

Jan Jongboom
Sorry I missed that off of the post - I had the maxRequestLength set to 10000 but have tried it with 102400 now.I've tried using the stream from FileContent but the read method doesn't return anything, although the Length property does give the correct number of bytes.File.SaveAs gives an ObjectDisposedException (cannot access a closed file) whenever the FileBytes are null.
David Neale
If you just put: `void UploadDocument() { File1.SaveAs(Server.MapPath("~/myuploadedfile.tmp")); }`, instead of all the logic now; does this save the file correctly? If not, does it work when you are using a normal `FileUpload` instead of the AJAX one?
Jan Jongboom
No, the file won't save even when I've stripped the logic out.I've done a straight swap to a FileUpload control and it works fine with every document, even a 15MB one.
David Neale
My best guess is that you are firing the event too early: on your local machine the moment you fire the event the content is already uploaded, as uploading local is lightning fast. Remote the event is fired while the component isn't finished yet. What event is the `UploadDocument` bound to? It shouldn't be to a button or something, but to an event from the FileUpload component, and I don't see why you cannot use `OnUploadCompleted`?
Jan Jongboom
I don't think that's it. The server side event OnUploadCompleted is called before the client side scripts are called. I'm clicking the button and calling my UploadDocument method after this.
David Neale
+1  A: 

Hi!

I think I've found a fix for this problem : on the OnUploadComplete event, simply put in session the FileBytes, and retreive it in your Button_Click event. For some reason, your uploaded file bytes are erased from session after a second postback...

This works for me. Cheers Laurent

Laurent
Good suggestion - that sounds like it wouldaccomplish what I was trying to do. Although I've just scripted round the plain old FileUpload control now. I guess the danger is that the button could be clicked too soon, especially with a large file, and the value would still be null; it would also cause a postback so would never complete.
David Neale