\\ Home Page : Articolo : Stampa
Sparare un file binario su http Response
Di Marco Tenuti (del 18/07/2013 @ 12:48:23, in web, linkato 1273 volte)

Se avete bisogno di sparare il contenuto di un intero file come output ad una richiesta HTTP, nel caso di vecchi script ASP è necessario tenere in considerazione alcune limitazioni:

  • Response non è disposto a ricevere stecche di byte troppo grandi (anche attraverso il metodo BinaryWrite)
  • Il buffer è acceso per default, quindi la risposta completa potrebbe non gradire "troppi" byte anche durante l'accumulo

Vi consiglio pertanto di procedere in questo modo, se i vostri parametri sono i seguenti:

  • outFileName è il nome del file che volete che compaia all'utente quando il browser gli chiederà di salvare da qualche parte sul suo disco locale
  • fileSize è la dimensione in byte del file da travasare
  • fullPath è il percorso completo nel web server che individua il file da mandare all'utente
  • Response.Clear()
    Response.Buffer = False
    Response.AddHeader "Content-Transfer-Encoding", "binary"
    Response.AddHeader "Content-Disposition", "attachment; Filename=" & outFileName
    Response.AddHeader "Content-Length", CStr(fileSize)
    Response.ContentType = "application/octet-stream; name=" & outFileName
    AttachFileContentToResponse fullPath
    Response.End()
    

    Ora il codice della funzione AttachFileContentToResponse, che non fa altro che attaccare il contenuto del file alla risposta HTTP:

    Sub AttachFileContentToResponse(FileName)
      
      Const adTypeBinary = 1
      Const clChunkSize = 1048576
      Dim oStream, i
    
      Set oStream = Server.CreateObject("ADODB.Stream")
      oStream.Type = adTypeBinary
      oStream.Open
      oStream.LoadFromFile FileName
      
      For i = 1 To oStream.Size \ clChunkSize
        Response.BinaryWrite oStream.Read(clChunkSize)
      Next
      
      If ((oStream.Size Mod clChunkSize) <> 0) Then
        Response.BinaryWrite oStream.Read(oStream.Size Mod clChunkSize)
      End If
    
      oStream.Close
    
    End Sub
    

    Sostanzialmente la funzione non fa altro che salvare il contenuto del file in byte "a pezzetti", semplicemente perché Response.BinaryWrite non è in grado di deglutire stecche troppo grosse. Ho letto in giro che IIS Server 6.0/7.0/7.5 ha un limite predefinito di 4 MB, anche se lo potete sapere interrogandolo attraverso la seguente linea di comando:

    cscript.exe adsutil.vbs GET w3svc/aspbufferinglimit 
    

    Potete comunque modificare tale limite attraverso la SET sullo stesso file adsutil.vbs, collocato generalmente nella cartella ROOTFOLDER/inetpub/AdminScript.

    cscript.exe adsutil.vbs SET w3svc/aspbufferinglimit LimitSize
    

    Una piccola finezza che ho curato nel mio script è quella di prendersi cura di specificare la dimensione totale del file in arrivo nell'header della risposta.

    Response.AddHeader "Content-Length", CStr(fileSize)
    

    Questa finezza consente al browser del visitatore di poter stimare e visualizzare la progressione del download, perché sa a priori quanti byte arriveranno in totale. Se non si specifica il campo Content-Length, il browser non riuscirà a fare tale stima e l'utente avrà una cattiva esperienza, perché non sa quanto aspettare se il file è di svariati MB.