• home
  • forum
  • my
  • kt
  • download
  • Download multiple files in one http request

    Author: 2007-06-30 18:40:20 From:

        HTTP protocol was designed to send one file per one request. Sometimes you will need to send more files - usually when a client selects several files for download and the files have to be delivered to the client. I created ASP sample which will do such task - the sample is located at http://www.motobit.com/help.
         The sample uses command line compression (zip/arj) to pack more files to one file and then sends the zip/arj archive to client. Client must have some software to uncompress the data package (unzip, pkunzip, winzip ...).

          Zip/Arj is great for download of files. But there are some tasks which require send more files in one request, for example HTML page with many small images as a preview.
         This task is usually completted as one request to HTML page and many (ten or more) requests to external images. Client-server communication for tenth of http request takes additional overhead on server, additional communication time, consumes line bandwith. The situation is even worse if you need authentication for each image preview - you must do tenth of authentication requests against user database, separated for each http request.

         This article shows another way - you can send HTML document and images (or applets, javascripts, iframes, frames and other external tags with SRC=...) as one multipart/related document, in one response to client request, with one authentication against user database. (see more about multipart/related at Google)

         Prepare multipart/related document

         There are several steps to create and send multipart document from server. This sample is an ASP/VBS code, but you can simply create similar code for another environment.
    I tried to use multipart/related directly in http header, but unforunatelly, it does not work in IE. So I must use anothe content-type - message/rfc822. The outgoing document contains complette multipart/related header and data then.

    	Response.ContentType =	"message/rfc822"

    Boundary is a unique string which separates file fields in multipart document. Encoded document files must not contain the string.
    	Const Boundary = "----=_NextPart_000_0000_01C31FDD.14FE27E0"

    Mime header contains at least MIME-Version and Content-Type headers. The header has two CrLf at the end.
    Function MimeHeader(Boundary)
    	Dim HTML
    	HTML = "MIME-Version: 1.0" & vbCrLf
    	HTML = HTML & "Content-Type: multipart/related;" & vbCrLf
    	HTML = HTML & vbTab & "type=""text/html"";" & vbCrLf
    	HTML = HTML & vbTab & "boundary=""" & Boundary & """" & vbCrLf
    	HTML = HTML & vbCrLf & "This is a multi-part message In MIME format." & vbCrLf
    	MimeHeader = HTML
    End Function 
    

         One file field consists from Boundary preceeded by two hypens ("--"). Next are multipart headers (Content-Type, Content-Location at least, you can add Content-Disposition, Content-ID, ...). Content-Location is a parameter for file location - SRC parameter of file, referred by first document.
         I'm using base-64 encoding for binary files, but the encoding is not required.
    Sub WriteFilePart(FileName)
    	Dim CT
    	CT = GetContentType(FileName)
    
    	'Write boundary with file multipart header.
    	Response.Write vbCrLf & "--" & Boundary & vbCrLf
    	Response.Write "Content-Type: " & GetContentType(FileName) & "" & vbCrLf
    	Response.Write "Content-Location: " & GetFileName(FileName) & "" & vbCrLf 
    	Response.Write "Content-Disposition: attachment; filename=""" & _
    		GetFileName(FileName) & """" & vbCrLf 
    	Response.Write "Content-ID: " & GetFileName(FileName) & "" & vbCrLf 
    
    	'Write contents of the file
    	If Left(CT, 4) = "text" Then
    		Response.Write vbCrLf
    		Response.BinaryWrite ReadBinaryFile(FileName)
    	Else
    		'Use Base64 For binary files.
    		Response.Write "Content-Transfer-Encoding: base64" & vbCrLf 
    		Response.Write vbCrLf
    		Response.BinaryWrite GetFileAsBase64(FileName)
    	End If
    	Response.Write vbCrLf
    End Sub
    

         First file in the multipart document should be main (start) HTML file, next fields are other data - images, scripts, etc.
         The first file field contains HTML document. The document has standard formatting, including text, references, etc. There is a change in URL interpretting - local URLs (without http://) poinst to multipart document, to multipart fields, with Content-Location header as address. Next is a sample of the HTML - op.gif means multipart field with Content-Location: op.gif, A Href="cl.gif" means reference to cl.gif file field.
    <!DOCTYPE HTML PUBLIC 
    	"-//W3C//DTD HTML 4.0 Transitional//EN">
    <HTML>
     <HEAD>
      <TITLE>Tips</TITLE>
    
      <BASEFONT face="Arial, Verdana, Helvetica">
     </HEAD>
    
    <Body TOPMARGIN=0 BGPROPERTIES=FIXED BGCOLOR=WHITE>
     <IMG src="op.gif" border=0>
    <br>
     <A Href="cl.gif"><IMG src="cl.gif" border=0></A>
    
    </BODY>
    </BASEFONT>
    </HTML>