Download file with Content-Type: multipart / mixed content type

I am making an angular application where I need to hit the resting endpoint and upload a file that is sent as an answer, but I don't understand how to do this. I have a response header as shown below.

Content-Disposition: mounts; file name = "Config.zip" Content-Type: multi-part / mixed; border = Boundary_25_1816124633_1519993185650 MIME-Version: 1.0 Transfer-Encoding: chunked

and the answer looks like

- Boundary_25_1816124633_1519993185650 Content-Type: application / json

{"configurations": [{}, {}, {}]} --Boundary_25_1816124633_1519993185650 Content-Type: application / octet-stream

PKMÛJAä;% RecurrenceEvent_CreateContract_1.jsoníYKoãF¾ÈxÝ0è ÷ Ã7Mb L & ÝÝK0Í | CD¬1ðß (J¤HÙ²¼yV '"ÙU¬®úªú" â · ö "åºv ~ \ ~ ùöýw³ù,

EDIT

this is my http call that references the backend

return this.http.get(url).map(response => {
// TODO
});

How to download the attached zip file? Please help. I am stuck.

+6
source share
3 answers
const executeSaveAs = (content) => {
    let blob = new Blob([content], {'type': "application/octet-stream"});
    saveAs(blob, "downloaded_zip.zip"); // This is from https://github.com/eligrey/FileSaver.js
};

return this.http.get(url, {responseType: 'arraybuffer'}).pipe(executeSaveAs);

We need to set the expected type of response we want to be "arraybuffer". Then we make the usual material for FileSaver, which creates a blob and passes it to a batch function saveAs.

Edit

In accordance with the commentary, it turned out that to parse the various parts of the multi-part answer, it was clarified.

Multipage Content Type Information

, , .

--boundaryThatIsInTheHeader

. . RegEx :

let boundaryRegex = new RegExp(/boundary=(\S+)/g);
const header = `Content-Disposition:attachment; filename="Config.zip" Content-Type:multipart/mixed;boundary=Boundary_25_1816124633_1519993185650 MIME-Version:1.0 Transfer-Encoding:chunked`; // As in the question

const boundary = '--' + boundaryRegex.exec(header)[1]; // We obtain the boundary here

.

response.split(boundary);

, ,

[ "", " Content-Type: application/json\n\n {\"config\":[{},{},{}]} ", " Content-Type: application/octet-stream\n\n PKMÛJAä;%RecurrenceEvent_CreateContract_1.jsoníYKoãF¾ÈxÝ0è÷Ã7Mb L&íÝK0ͦCD¬1ðß(J¤HÙ²¼yV'»ÙU¬®úªú«â· ö«åºv~Í~ùöýw³Ù,È«ù"]

, JSON. , ! , .. , RegEx. , . zip .

+6

, multipart/mixed multipart/form-data .
( , .)

form-data , .

fetch api . formData()

. , , , , formData(), , , ( ).

, content-type multipart/form-data, apetch fetch .

getExampleResponse(async res => {
  // replace the content-type to multipart/form-data so fetch api can parse it
  const type = res.headers.get('content-type')
  res.headers.set('content-type', type.replace('mixed', 'form-data'))

  // return the response as a formData
  const fd = await res.formData()

  // console.log(...fd)
  console.log(JSON.parse(fd.get('json')))
  console.log(fd.get('image'))

  const file = fd.get('image')
  const link = document.createElement('a')
  const image = new Image
  link.href = image.src = URL.createObjectURL(file)
  link.innerText = 'download ' + (link.download = file.name)
  
  // saveAs(file); // This is from https://github.com/eligrey/FileSaver.js

  document.body.appendChild(image)
  document.body.appendChild(link)  
})




/* 
Don't mind this, it just an example response you are getting...
What you actually want is something like 

function getExampleResponse(cb) {
  fetch(url).then(cb)
}
*/
function getExampleResponse(e){var a=document.createElement("canvas"),d=a.getContext("2d");d.fillStyle="blue";d.fillRect(0,0,a.width,a.height);a.toBlob(function(b){var a={a:123};var c='--Boundary_25_1816124633_1519993185650\r\nContent-Disposition: form-data; name="json"\r\nContent-Type: application/json\r\n'+("Content-Length: "+JSON.stringify(a).length+"\r\n\r\n");c+=JSON.stringify(a)+"\r\n";c=c+'--Boundary_25_1816124633_1519993185650\r\nContent-Disposition: form-data; name="image"; filename="image.png"\r\nContent-Transfer-Encoding: binary\r\n'+
("Content-Type: "+b.type+"\r\n");c+="Content-Length: "+b.size+"\r\n\r\n";b=new Blob([c,b,"\r\n--Boundary_25_1816124633_1519993185650--\r\n"]);e(new Response(b,{headers:{"Content-Type":"multipart/mixed; boundary=Boundary_25_1816124633_1519993185650"}}))})};
Hide result
+1

You can use the file-saver package to make it more understandable in code. Then a maintenance method to extract data from the source code:

getFile(fileName: string): Observable<Blob> {
    return this.http.get(`${environment.apiServerUrl}/` + fileName, {responseType: 'blob'})
    .catch(error => this.handleErrorResponse() // catch http error);
  }

Then the call function in the browers event

 this.service.getFile('filenameInServer.zip')
     .subscribe(fileData => FileSaver.saveAs(fileData, 'sugestedFileNameInDownloadDialog.zip'));
-1
source

All Articles