Лучший способ сохранить поток в файл в asp.net 3.5?


3

У меня есть объект поток, который заполняется содержимым файла XSD у меня есть, как внедренный ресурс на проекте я работаю, как так:

using (Stream xsdStream = assembly.GetManifestResourceStream(xsdFile)) 
{ 
    // Save the contents of the xsdStream here... 
} 

В этом используя блок я хотел бы побудить пользователь с диалоговым окном «Сохранить файл» в Интернете, где они могут выбрать сохранение этого файла XSD, содержащегося в потоке.

Каков наилучший способ для этого? Я полностью потерян и не могу представить Google правильные условия для получения соответствующего ответа.

Спасибо!

2

Если вы не используете AJAX, вы можете использовать Response.WriteFile. Еще я бы использовал MemoryStream. Вот как я это сделал here. Извините, что в VB.NET я не перекодировал его. Обратите внимание, что это также позволяет загружать файл ЧЕРЕЗ веб-сервер, т. Е. Если ваш файл находится на сервере приложений без открытого доступа.

Imports System.Data 
Imports System.Data.SqlClient 
Imports System.Data.Sql 
Imports System.Net 
Imports System.IO 

Partial Class DownloadFile 
Inherits System.Web.UI.Page 

Protected Sub page_load(ByVal sender As Object, ByVal e As EventArgs) Handles Me.Load 
Dim url As String = Request.QueryString("DownloadUrl") 
If url Is Nothing Or url.Length = 0 Then Exit Sub 

'Initialize the input stream 
Dim req As HttpWebRequest = WebRequest.Create(url) 
Dim resp As HttpWebResponse = req.GetResponse() 
Dim bufferSize As Integer = 1 

'Initialize the output stream 
Response.Clear() 
Response.AppendHeader("Content-Disposition:", "attachment; filename=download.zip") 
Response.AppendHeader("Content-Length", resp.ContentLength.ToString) 
Response.ContentType = "application/download" 

'Populate the output stream 
Dim ByteBuffer As Byte() = New Byte(bufferSize) {} 
Dim ms As MemoryStream = New MemoryStream(ByteBuffer, True) 
Dim rs As Stream = req.GetResponse.GetResponseStream() 
Dim bytes() As Byte = New Byte(bufferSize) {} 
While rs.Read(ByteBuffer, 0, ByteBuffer.Length) > 0 
Response.BinaryWrite(ms.ToArray()) 
Response.Flush() 
End While 

'Cleanup 
Response.End() 
ms.Close() 
ms.Dispose() 
rs.Dispose() 
ByteBuffer = Nothing 
End Sub 
End Class 

0

Мне кажется, что вы должны взглянуть на обработчик WebResource.axd.

Microsoft имеет отличный article по этому вопросу.

Edit:

Кажется, что tsilb бил мой ответ на минуту или около того. Тем не менее, AssemblyResourceLoader (aka. WebResource.axd) уже реализован, чтобы сделать это для вас и сделать это правильно, и не забывайте, что этот щенок поддерживает выходное кэширование. Так что продолжайте использовать это вместо этого и избавьте себя от неприятностей. ;)


1

Вы хотите установить контент-расположение:

Response.AddHeader "Content-Disposition","attachment; filename=" & xsdFile 

Вы также хотите установить Content-Type в текст/простой и Content-Length до размера файла. Затем вы пишете содержимое файла.

  0

Хотя этот ответ действительно содержит ценную информацию, то есть, если Роб хочет свернуть свою собственную поточную передачу, он не отвечает на вопрос о том, как передать файл в первую очередь. Если бы Роб хотел пойти таким образом, я думаю, что у тильба есть лучший ответ. Однако я все еще думаю, что мой путь намного проще ...;) 22 фев. 092009-02-22 06:30:17


1
private void DownloadEmbeddedResource( 
    string resourceName, Assembly resourceAssembly, string downloadFileName) 
{ 
    using (Stream stream = resourceAssembly.GetManifestResourceStream(resourceName)) 
    { 
    if (stream != null) 
    { 
     Response.Clear(); 
     string headerValue = string.Format("attachment; filename={0}", downloadFileName); 
     Response.AppendHeader("Content-Disposition:", headerValue); 
     Response.AppendHeader("Content-Length", stream.Length.ToString()); 
     Response.ContentType = "text/xml"; 

     var byteBuffer = new Byte[1]; 

     using (var memoryStream = new MemoryStream(byteBuffer, true)) 
     { 
     while (stream.Read(byteBuffer, 0, byteBuffer.Length) > 0) 
     { 
      Response.BinaryWrite(memoryStream.ToArray()); 
      Response.Flush(); 
     } 
     } 

     Response.End(); 
    } 
    } 
} 

В итоге я использовал этот метод выше. Спасибо, что помогли мне с синтаксисом tsilb. JohannesH, я бы воспользовался вашей рекомендацией, если ресурс уже не пришел из другой сборки (извините, я должен был очистить это в моем исходном вопросе).

Код выше работает, но я столкнулся с довольно странной проблемой ... После завершения метода и завершения загрузки страница все еще никогда не возвращается к жизни, и мышь все еще находится в режиме песочных часов, думает, что работа делается. Любая идея о том, как исправить это?

Еще раз спасибо за вашу помощь!