私が持っているもの
ユーザーがボタンクリックでファイルa
をダウンロードできるASP.NETページがあります。ユーザーは利用可能なファイルのリスト(RadioButtonList)から必要なファイルを選択し、ダウンロードボタンをクリックしてダウンロードできます。 (ダウンロードできるファイルごとにリンクを提供するべきではありません-これが要件です)。
何が欲しい?
必要なラジオボタンを選択してボタンをクリックすることにより、ユーザーが複数のファイルを1つずつダウンロードするようにします。
私はどのような問題に直面していますか?
初めてファイルを適切にダウンロードできます。しかし、ダウンロード後、他のファイルを選択してボタンをクリックしてダウンロードすると、ボタンのクリックイベントはポストバックせず、2番目のファイルはダウンロードされません。
ボタンクリックイベントで次のコードを使用します。
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();
}
ここで何か間違ったことをしていますか?
同じ問題は、IE6、IE7、Chromeでも再現できます。この問題はブラウザに依存しないと思います。
SharePointでも同じ問題が発生しました。ページにファイルを送信するボタンがあり、ボタンをクリックした後、フォームの残りの部分が応答しませんでした。それは、それ以上の送信を防ぐために変数_spFormOnSubmitCalledをtrueに設定するのが共有ポイントであることが判明しました。ファイルを送信してもページは更新されないため、この変数を手動でfalseに設定し直す必要があります。
Webパーツのボタンで、OnClientClickをページのjavascriptの関数に設定します。
<asp:Button ID="generateExcel" runat="server" Text="Export Excel"
OnClick="generateExcel_Click" CssClass="rptSubmitButton"
OnClientClick="javascript:setFormSubmitToFalse()" />
次に、javascriptにこの関数があります。
function setFormSubmitToFalse() {
setTimeout(function () { _spFormOnSubmitCalled = false; }, 3000);
return true;
}
そうしないと、sharepointが設定する前に変数を設定していたため、3秒間の一時停止が必要でした。このようにして、sharepointに通常の設定を行わせ、その後すぐにfalseに戻します。
Response.End
を削除せずにこれを行う簡単な方法は、クライアント側のjsを追加してページの更新を行うことです。 jsをボタンのonclientclickプロパティに追加します。
例えば.
onclientclick="timedRefresh(2000)"
then in your html..
<script type="text/JavaScript">
<!--
function timedRefresh(timeoutPeriod) {
setTimeout("location.reload(true);",timeoutPeriod);
}
// -->
オフハンド、あなたがやっていることは動作するはずです。リピーターとLinkButtonsを使用しましたが、過去にも同様に成功しました。
異なるのは、Response.Write()
ではなくResponse.OutputStream.Write()
を使用していることと、バイナリではなくテキストを記述しているが、ContentType
あなたが指定した、それは問題ではないはずです。さらに、情報を送信する前にResponse.ClearHeaders()
を呼び出し、その後(Response.Flush()
を呼び出す前に)Response.End()
を呼び出します。
それが役立つ場合、私にとってうまくいくもののサニタイズされたバージョンがあります:
_// 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();
}
_
おそらくSystem.Text.Encoding.ASCII.GetBytes(viewXml);
を呼び出し、その結果をResponse.OutputStream.Write()
に渡すことにより、バイナリ形式でファイルを転送することを検討する必要があります。
コードをわずかに変更します。
_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();
}
_
同じ問題がありました。 aspxページのボタンクリックイベントで単純なResponse.Writer( "")を実行する関数が起動しなかった。
クラスのメソッド:
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();
}
}
ASPXページ:
protected void btn_test_Click(object sender, EventArgs e)
{
test_class.test_response_write("testing....");
}
理由を見つけようとしていたとき、Page_Load
イベントで同じ関数を呼び出しました。
protected void Page_Load(object sender, EventArgs e)
{
if (!IsPostBack)
{
test_class.test_response_write("testing....");
}
}
問題を調査すると、そのaspxページの本文のマスターページが<asp:UpdatePanel>
の下にあることがわかりました。
削除し、Button_Click
イベントで機能しました。私もそれを確認することをお勧めします。
Response.End()
を削除し、ASP.NETエコシステム内で応答を自然に終了させます。
それでもうまくいかない場合は、ボタンを別の<form>
必要なデータを別のHTTPハンドラーに送信します。 Webページの代わりにXMLをエクスポートするようにHTTPハンドラーをセットアップします。
クライアントにファイルを送信し、ASP.Netでresponse.writeを使用する場合、開発者はファイルの送信後に他に何もできません。クライアントがファイルを取得した後に関数を呼び出すjavascript onclick関数を追加するなど、他の回避策があります。これは、ファイルを送信する関数が呼び出されるときにメタリフレッシュを追加するのに似ています(Response.AppendHeader(“更新」、「5; URL =」およびHttpContext.Current.Request.Url.AbsoluteUri))
しかし、それらは私が望んでいた外観を私に与えていませんでした。そこで、これらの回避策を組み合わせてこのソリューションを考え出しました。
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