38

I would like to create a HTTP response, using multipart/mixed, but I'm not sure which browsers support it; and if it's as convenient as it sounds, from the client's point of view. To be honest, I do not need specifically that content type. I just want to transmit more than one file in the same response; maybe there's another content-type more used.

Diego Jancic
  • 7,280
  • 7
  • 52
  • 80
  • I can't find any good information on Google, so you'll have to test it - Build a simple page which is sent as multipart - Test in various browsers - Post results here :) (This page is the second result in Google when searching for this) – Bart van Heukelom Nov 27 '09 at 20:32
  • If the files are related to each other, such as resources of a root document, try `multipart/related`. – Remy Lebeau Nov 26 '14 at 10:27

4 Answers4

33

I've tested it, with a home-made server and a simple response. Not sure if the response is well-formed because no browser understands it 100% OK. But here are the results:

  • Firefox 67.0.1 (64-bit): Renders only the last part, others are ignored.
  • IE 11.503: Saves all the content in a single file (including the boundaries), nothing is rendered.
  • Chrome May 2019: Saves all the content in a single file, nothing is rendered.
  • Safari 4: Saves all the content in a single file, nothing is rendered.
  • Opera 10.10: Something weird. Starts rendering the first part as plain/text, and then clears everything. The loading progress bar hangs on 31%.

Here's the complete response, if anyone finds any error, please tell me and I'll try again:

HTTP/1.1 200 OK
Date: Tue, 01 Dec 2009 23:27:30 GMT
Vary: Accept-Encoding,User-Agent
Content-Length: 681
Content-Type: Multipart/mixed; boundary="sample_boundary";

Multipart not supported :(
--sample_boundary
Content-Type: text/css; charset=utf-8
Content-Location: http://localhost:2080/file.css

body
{
 background-color: yellow;
}
--sample_boundary
Content-Type: application/x-javascript; charset=utf-8
Content-Location: http://localhost:2080/file.js

alert("Hello from a javascript!!!");

--sample_boundary
Content-Type: text/html; charset=utf-8
Content-Base: http://localhost:2080/

<html>
<head>
    <link rel="stylesheet" href="http://localhost:2080/file.css">
</head>
<body>
 Hello from a html
    <script type="text/javascript" src="http://localhost:2080/file.js"></script>
</body>
</html>
--sample_boundary--
Sandra Rossi
  • 11,934
  • 5
  • 22
  • 48
Diego Jancic
  • 7,280
  • 7
  • 52
  • 80
  • 1
    I'm not sure where you went wrong, but I implemented it in firefox in 2006 and it worked nicely. – kybernetikos Jun 14 '12 at 11:11
  • 2
    If you have any example, please submit it :) Thanks! – Diego Jancic Jun 14 '12 at 14:27
  • for node: ff works nicely, chrome seems to be one frame behind: ```var boundary="XXMIMEBOUNDARY"; var section=0; function writeSection(res){var a=(section++); console.log("writing",a); res.write("Content-type: text/plain\n\n"); res.write("Section "+a);res.write("--"+boundary+"\n");}; require('http').createServer(function(req, res){console.log('received request'); res.writeHead(200,{"Content-type":'multipart/x-mixed-replace;boundary="'+boundary+'"'}); writeSection(res); setInterval(function(){writeSection(res);},2500);}).listen(8080);``` – kybernetikos Jun 22 '12 at 08:51
  • I just did a test for more recent versions (Chrome, Edge, IE, Firefox), with a multipart response containing 2 PNG files, nothing changed (I updated the answer with the tested browser versions) – Sandra Rossi Jun 11 '19 at 12:59
4

In my experience, multipart responses work in Firefox but not in Internet Explorer. This was 2 years ago, using the browsers of the time.

I have had HTTP multipart responses working for a stream of JPEG images. For example, Axis IP cameras use for their motion JPEG stream for Firefox. For Internet explorer, Axis require the use of a plugin.

If Firefox-only support meets your requirements, then I recommend setting the content-length header in each part of the multi-part response. It might help to make the boundary string identical in the original HTTP header and the multi-part response (the '--' is missing in the HTTP header).

Thomas Bratt
  • 48,038
  • 36
  • 121
  • 139
3

Two ideas:

  1. Formatting: I think "multipart" should be in lower case, and I don't think a semicolon is expected at the end of the Content-type header (although it's doubtful that it will make a difference, it's possible that it might).
  2. Have you tried replace mode? Just use: Content-type: multipart/x-mixed-replace -- everything else should stay the same.
RickNZ
  • 18,448
  • 3
  • 51
  • 66
  • There is a big semantic difference between `multipart/mixed` and `multipart/x-mixed-replace`. It is not likely that any browser would support `multipart/mixed` as it is just not something used by real servers. `multipart/x-mixed-replaced` has some support, because some servers do use it for server-side pushing, like for streaming media. The only other `multipart/...` types commonly used with HTTP are `multipart/form-data` and `multipart/byteranges`. – Remy Lebeau Nov 26 '14 at 10:27
0

 Multi part it yourself

(A good option)

A multipart response can be made manually!

So one can write a no multipart response! Let's say in chunked mode! There it make sense!

So you are streaming the data!

Send all as blunt text!

Make your own separators! Between each part!

In the browser! Extract and parse the data! Split to get each part separately!
And parse each appart! Depending on what type of data it hold!

So if a part is json! You parse it as so!

Quick illustration! Let say we want to send a csv file! Or some other type of file! Along that we want to send too a json object!

And that by streaming it by chunk

Here a code that illustrate that in express:

const data = {
    initCapital: fileState.mappingObj.initialCapital
};

res.write(JSON.stringify(data, undefined, 0));
res.write('>>>>'); // parts separator
fileState.readStream.pipe(res); // continue streaming the file (chunk by chunk)

And in the client

export function parseBackTestFetchedData(data: string) {
    const [_data, csvData] = data.split('>>>>');
    return {
        data: JSON.parse(_data),
        backTestStatesData: parseCsv(csvData)
    };
}

enter image description here

That way! it doesn't matter who the client is!

Mohamed Allal
  • 17,920
  • 5
  • 94
  • 97
  • 1
    Interesting answer. In my case, I wanted multipart to reduce requests and improve browser loading time. If done in js though, parsing it manually would increase the time and probably makes no sense to compensate the roundtrip. – Diego Jancic May 30 '20 at 13:57
  • Well! I didn't look well on the details of how the multi part response work exactly! And how it can be better on matter of parsing and extraction! But in all cases it gonna get parsed at the browser level too! The difference between it getting parsed internally and in js may not be that of a big deal! Of course one need to benchmark! Otherwise i'll ask why not just a normal answer with json that contain all (internal parse Also for better loading you can start reading and processing the data as it come in! Listening to the body stream! And treat it in the fly! Incrementally loading the data! – Mohamed Allal May 30 '20 at 22:03
  • Also send the parts on the right order that make sense! For that loading! – Mohamed Allal May 30 '20 at 22:03
  • Also for parsing json data! It use the same internal mechanism! And so the only mattering element is the separation! If the data is small it should not matters! If it's big! As like with small parts at first! Then a last big part! Treating by streaming! is nice! And also parsing by one pass! And extraction! So precising how many parts there is can help! To optimize the extraction! One can even set the bounds position with the request! First line hold that meta data! And the rest of the extraction will be direct! One can make a tool to make that for general use! And optimize it! – Mohamed Allal May 30 '20 at 22:11
  • And before any we need to measure! To know well what matters! And what take time and for what conditions and elements – Mohamed Allal May 30 '20 at 22:12
  • I'd like to have some insight and profit from your experience – Mohamed Allal May 30 '20 at 22:15
  • 1
    it's hard to say, but the idea is that if send a css file and image and then html the image is available for rendering even before the html finishes downloaded because the browser parses progressively. Also it happens before JS code is parsed and executed – Diego Jancic May 31 '20 at 16:32
  • Well i more thought about something like in here https://stackoverflow.com/questions/47067312/multipart-http-response ! Ajax call! page already loaded! Is it possible for what you said! i searched a bit i couldn't see it make any sense! (I mean possible) ! Did you manage it! How it does work! Like for such a thing the browser need to be aware of all! And manage the parts! But i can't see that anywhere! Except for http2.0 and parallel serving or download https://stackoverflow.com/questions/25138666/minimizing-http-connections-vs-parallel-downloads – Mohamed Allal Jun 01 '20 at 07:28