web-dev-qa-db-fra.com

Post Back ne fonctionne pas après l'écriture de fichiers dans une réponse dans ASP.NET.

Ce que j'ai?

J'ai une page ASP.NET qui permet à l'utilisateur de télécharger le fichier a sur un clic de bouton. L'utilisateur peut sélectionner le fichier qu'il souhaite dans une liste de fichiers disponibles (RadioButtonList) et cliquer sur le bouton de téléchargement pour le télécharger. (Je ne devrais pas fournir de lien pour chaque fichier pouvant être téléchargé - c'est l'exigence).

Ce que je veux?

Je veux que l'utilisateur télécharge plusieurs fichiers un par un en sélectionnant le bouton radio requis et en cliquant sur le bouton.

À quel problème suis-je confronté?

Je peux télécharger le fichier pour la première fois correctement. Mais, après le téléchargement, si je sélectionne un autre fichier et clique sur le bouton pour le télécharger, cliquez sur l'événement du bouton ne s'affiche pas et le second fichier ne sera pas téléchargé.

J'utilise le code suivant sur l'événement de clic de bouton:

protected void btnDownload_Click(object sender, EventArgs e)
{
    string viewXml = exporter.Export();
    Response.Clear();
    Response.AddHeader("Content-Disposition", "attachment; filename=views.cov");
    Response.AddHeader("Content-Length", viewXml.Length.ToString());
    Response.ContentType = "text/plain";
    Response.Write(viewXml);
    Response.End();
}

Est-ce que je fais quelque chose de mal ici?

Le même problème peut être répliqué dans IE6, IE7 et Chrome. Je pense que ce problème est indépendant du navigateur.

44
Vijay

J'ai eu le même problème avec SharePoint. J'ai un bouton sur la page qui envoie un fichier et après avoir cliqué sur le bouton, le reste du formulaire ne répondait plus. Il s'avère que c'est un point de partage qui définit la variable _spFormOnSubmitCalled sur true pour empêcher toute soumission ultérieure Lorsque nous envoyons un fichier, la page n'est pas actualisée, nous devons donc redéfinir manuellement cette variable sur false. 

Sur votre bouton dans la Webpart, définissez OnClientClick sur une fonction de votre javascript pour la page.

 <asp:Button ID="generateExcel" runat="server" Text="Export Excel" 
OnClick="generateExcel_Click" CssClass="rptSubmitButton"
OnClientClick="javascript:setFormSubmitToFalse()" />

Ensuite, dans le javascript, j'ai cette fonction.

function setFormSubmitToFalse() {
    setTimeout(function () { _spFormOnSubmitCalled = false; }, 3000);
    return true;
}

La pause de 3 secondes que j'ai trouvée était nécessaire car sinon, je définissais la variable avant que sharepoint ne la définisse. De cette façon, je laisse sharepoint le régler normalement, puis je le remets à False juste après. 

58
RobbZ

Un moyen simple de le faire sans supprimer Response.End consiste à ajouter un js côté client pour actualiser la page. Ajoutez le js à la propriété onclientclick de votre bouton. 

par exemple. 

    onclientclick="timedRefresh(2000)"

then in your html..

    <script type="text/JavaScript">
    <!--
    function timedRefresh(timeoutPeriod) {
        setTimeout("location.reload(true);",timeoutPeriod);
    }
    //   -->

4
Digitz

De prime abord, ce que vous faites devrait fonctionner. J'ai réussi à faire la même chose dans le passé, bien que j'aie utilisé un répéteur et des LinkButtons.

La seule chose qui me distingue, c'est que vous utilisez Response.Write() plutôt que Response.OutputStream.Write() et que vous écrivez du texte plutôt que du binaire, mais étant donné la ContentType que vous avez spécifiée, cela ne devrait pas poser de problème. De plus, j'appelle Response.ClearHeaders() avant d'envoyer des informations et Response.Flush() après (avant mon appel à Response.End()). 

Si cela peut vous aider, voici une version assainie de ce qui fonctionne bien pour moi:

// called by click handler after obtaining the correct MyFileInfo class.
private void DownloadFile(MyFileInfo file) 
{
    Response.Clear();
    Response.ClearHeaders();
    Response.ContentType = "application/file";
    Response.AddHeader("Content-Disposition", "attachment; filename=\"" + file.FileName + "\"");
    Response.AddHeader("Content-Length", file.FileSize.ToString());
    Response.OutputStream.Write(file.Bytes, 0, file.Bytes.Length);
    Response.Flush();
    Response.End();        
}

Vous voudrez peut-être envisager de transférer le fichier de manière binaire, par exemple en appelant System.Text.Encoding.ASCII.GetBytes(viewXml); et en transmettant le résultat de celui-ci à Response.OutputStream.Write().

Modifier légèrement votre code:

protected void btnDownload_Click(object sender, EventArgs e)
{
    string viewXml = exporter.Export();
    byte [] bytes = System.Text.Encoding.ASCII.GetBytes(viewXml); 
    // NOTE: you should use whatever encoding your XML file is set for.
    // Alternatives:
    // byte [] bytes = System.Text.Encoding.UTF7.GetBytes(viewXml);
    // byte [] bytes = System.Text.Encoding.UTF8.GetBytes(viewXml);

    Response.Clear();
    Response.ClearHeaders();
    Response.AddHeader("Content-Disposition", "attachment; filename=views.cov");
    Response.AddHeader("Content-Length", bytes.Length.ToString());
    Response.ContentType = "application/file";
    Response.OutputStream.Write(bytes, 0, bytes.Length);
    Response.Flush();
    Response.End();
}
4
Randolpho

J'ai eu le même problème. Fonction permettant d’exécuter Response.Writer ("") simple lorsqu’un clic sur un bouton de la page aspx ne s’est jamais déclenché.

Méthode en classe:

public test_class()
{
    public test_class() { }

    public static void test_response_write(string test_string) 
    {
        HttpContext context = HttpContext.Current;
        context.Response.Clear();
        context.Response.Write(test_string);
        context.Response.End();                   
    }
}

Page ASPX:

protected void btn_test_Click(object sender, EventArgs e)
{
    test_class.test_response_write("testing....");
}

Pendant que j'essayais de trouver la raison, je venais d'appeler la même fonction sur l'événement Page_Load qui fonctionnait.

protected void Page_Load(object sender, EventArgs e)
{
    if (!IsPostBack)
    {
        test_class.test_response_write("testing....");
    }
}

En examinant le problème, j'ai découvert que Master Page du corps de cette page aspx était placé sous <asp:UpdatePanel>

Je l'ai enlevé, et cela a fonctionné sur Button_Click Event. Je vous recommanderais de vérifier cela aussi.

3
AhsanRazaUK

Supprimez Response.End() et laissez la réponse se terminer naturellement dans l'écosystème ASP.NET.

Si cela ne fonctionne pas, je vous recommande de placer le bouton dans un <form> séparé et d'envoyer les données requises dans un gestionnaire HTTP distinct. Configurez le gestionnaire HTTP pour exporter le XML au lieu d’une page Web.

3
Josh Stodola

Vérifiez sur https://multilingualdev.wordpress.com/2014/08/19/asp-net-postback-after-response-write-work-around-solution/

Lors de l'envoi d'un fichier au client et de l'utilisation de response.write dans ASP.Net, le développeur ne peut plus rien faire après l'envoi du fichier. Il existe d’autres solutions telles que l’ajout d’une fonction javascript onclick qui appelle une fonction après que le client a récupéré le fichier. Actualiser ”,“ 5; URL = ”& HttpContext.Current.Request.Url.AbsoluteUri))

Mais ceux-ci ne me donnaient pas le regard que je voulais. J'ai donc utilisé une combinaison de ces solutions pour proposer cette solution:

Protected Sub Page_Load(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.Load

checkSendFile() ‘each time page loads it will check to see if it needs to send the file

If (Not IsPostBack) Then

‘this spot is not be executed after a form submit (postback); which means you can put 

‘ the checkSendFile() in here if you want

end If

End Sub

Private Sub checkSendFile()

Dim sendFile As String = Session(“SENDFILE”) ‘ first we get the session file to see if its time 

‘ to send a file

If Not sendFile Is Nothing Then

If sendFile = “YES” Then

Session(“SENDFILE”) = “” ‘here we clear the session file so it doesn’t send again if

‘ refreshed

sendClientFile() ‘ function to send the file to client

End If

End If

End Sub

Protected Sub btnGetFile_Click(sender As Object, e As EventArgs) Handles btnGetFile.Click

‘this is where the client clicks on a button or link or something that submits the form and 

‘ request a file to be sent to them

Session(“SENDFILE”) = “YES” ‘ we set a session variable flag 

‘then we update the GUI, or run any other method that we wanted to do after client gets file

me.lblMsgToClient.text = “Thank you for downloading file.”

RefreshPage() ‘ then we refresh the page instantly (this is where post back will update values

‘ and interface, then send file)

End Sub

Private Sub RefreshPage()

‘ here we instantly add a refresh meta tag to the header with zero seconds to refresh to the

‘ same url we are currently at

Response.AppendHeader(“Refresh”, “0;URL=” & HttpContext.Current.Request.Url.AbsoluteUri)

End Sub

Private Sub sendClientFile()

‘here you will have your file and bytes to send to browser from either file system or database

‘then you can call sendToBrowser(…)

End Sub

Private Sub sendToBrowser(ByVal fileName As String, ByVal contentType As String, ByRef fileBytes As Byte())

‘this function is just the normal send file to client

Response.AddHeader(“Content-type”, contentType)
Response.AddHeader(“Content-Disposition”, “attachment; filename=” & fileName)
Response.BinaryWrite(fileBytes)
Response.Flush()
Response.End()

End Sub
0
user10147660