18

Requirements

I am trying to upload a file, as soon as a user selects it. I have to fulfill the following requirements:

  1. The button looks like other buttons in the application.
  2. The file is uploaded as soon as the user selects it.
  3. I need it to be in an UpdatePanel as I have to make conditional updates to the page. I CAN do a full postback on the file selected (a.k.a onchange) event.

Current code

Following is how my view file looks:

<asp:UpdatePanel ID="upData" UpdateMode="Conditional" runat="server">
    <ContentTemplate>

    <div style="width: auto; float: right;">

    <asp:Button ID="btnFileImportSkin" CssClass="ButtonSkin AddButton" Text="Import" Style="position: absolute; z-index: 2;" runat="server" OnClientClick="Javascript:onImport(); return false;" />
    <asp:FileUpload ID="fileImport" Visible="false" Style="position:relative; opacity:0;" runat="server" onchange="Javascript:onFileSelected();"  /> 
           <%-- onchange="Javascript:this.form.submit();" /> --%>
           <%-- <asp:Button ID="btnUpload" runat="server" OnClientClick="Javascript:alert('Uploading...'); __doPostBack('<%= btnUpload.ID %>', ''); return false;" /> --%>
    <asp:Button ID="btnUpload" OnClick="btnUpload_Click" runat="server" />
    </div>

    </ContentTemplate>
    <Triggers>
        <asp:PostBackTrigger ControlID="btnUpload" />
    </Triggers>
</asp:UpdatePanel>

Relevant Javascript:

<script type="text/javascript">
    function onImport() {
        var fileImportClientId = '<%= fileImport.ClientID %>';
        document.getElementById(fileImportClientId).click();
    }

    function onFileSelected() {
        alert("File Selected");
        // I have tried calling the function directly and with a timeout
        setTimeout(onUpload, 20);
    }

    function onUpload() {
        var btnUploadClientId = '<%= btnUpload.ClientID %>';
        document.getElementById(btnUploadClientId).click();
    }
</script>

Code behind:

protected void btnUpload_Click(object sender, EventArgs e)
{
    // PostedFile is null first time code gets here on user selecting a file
    if (fileImport.PostedFile != null)
    {
        if (fileImport.PostedFile.FileName.Length > 0)
        {
            ImportFromFile();
        }
    }
}

Explanation/Flow

  1. User clicks on btnFileImportSkin button.
  2. The function onImport is called, which programmatically clicks on the fileimport button.
  3. User selects a file, and presses Open.
  4. onFileSelected is called.
  5. onUpload is called successfully.
  6. btnUpload_Click is called successfully every time.

However the Problem is that

fileImport.PostedFile is null the first time user selects a file. Everything works fine the second time and from there on.

Related

This question is closely related to my problem, but the OP probably wanted an Async upload solution as in Gmail. I have already tried doing the following as in the answers to this question:

  1. __doPostBack() in OnClientClick event of btnUpload
  2. this.form.submit() onchange event of my FileUpload control.
  3. Setting the onchange attribute of FileUpload control in Page_PreRender

Additional Notes

  1. This thing worked perfectly when I did not have update panels. I was doing this.form.submit() directly in onchange event of FileUpload control.
  2. Target framework is .NET 4.0

NOTE: Added a Visible="false" in FileUpload control above. It was the problem but I had ignored it while asking question.

Ozair Kafray
  • 13,351
  • 8
  • 59
  • 84

2 Answers2

3

This code works for me, when targeting both the .Net 4.5 and 4.0 framework versions. I copy / pasted your code into a new Web Forms application, and in both cases fileImport.PostedFile was not null, but contained the Stream of the image I selected.

Is there an issue in any of the other markup on your page? Or perhaps your page lifecycle? Is the html / javascript you posted on a User Control or a Web Form Page?

BeeTee2
  • 777
  • 4
  • 13
  • Both html and javascript are in a User Control. – Ozair Kafray Dec 18 '15 at 04:52
  • Are you sure that it works the first time? It works for me too when I click on `btnFileImportSkin` the second time. – Ozair Kafray Dec 18 '15 at 11:44
  • Yes I am, 110%. :) I click the button only once and the code hits the breakpoint the first time, every time. – BeeTee2 Dec 20 '15 at 04:17
  • Do you then think that having it in a User Control has something to do with my problem? – Ozair Kafray Dec 21 '15 at 06:03
  • 1
    Yes, I think your problem is most likely somewhere in the asp.net page lifecycle. The fact that it's in a User Control isn't necessarily a problem, it's just that there are now more moving parts in the beast that is the web forms page lifecycle. However, this is hard to diagnose without seeing the master page, the web form, and the user control. Both the .aspx and the code-behinds. I just moved the code you posted from a web form to a user control in a new web forms application, and it worked for me, still posting the file on the first click. – BeeTee2 Dec 21 '15 at 15:20
  • Please note my edit (NOTE). I have already solved the problem, but if you can edit your answer for this, I will accept it too :), otherwise I will answer it myself. The bounty will still remain with you. – Ozair Kafray Jan 12 '16 at 12:48
0

With a hint from BeeTee's answer, another SO post and this thread on another forum, I found out that the FileUpload control must be visible during prerendering. This is probably true for any parent UpdatePanels this control lies in. So, basically I removed Visible=false from my control definition below:

<asp:FileUpload ID="fileImport" Visible="false" Style="position:relative; opacity:0;" runat="server" onchange="Javascript:onFileSelected();"  />

In my case I could hide it by setting the css opacity property to 0. However, there are two other ways around it:

  1. Set the css property display:none
  2. Make the asp control's Visible property temporarily to true during prerendering. This is detailed in the thread linked above from another forum.

Please note that the Visible should also be true for parents of this FileUpload control as mentioned in the other SO thread.

Community
  • 1
  • 1
Ozair Kafray
  • 13,351
  • 8
  • 59
  • 84