How to download a file from SharePoint using Ajax from html


Recently I was able to help someone who was getting a corrupt file when trying to download from SharePoint Online through AJAX call.

He was able to download TEXT files successfully using the existing code, but it didn’t work for PDF or Word or Excel documents.

<script type="text/javascript">
	window.onload = () => {
		let code = '{!ACCESS_TOKEN}';   
		let extension = '{!extension}';

		//make a ajax callout
		$.ajax({
			url: "https://<YourSharePointSite>.sharepoint.com/_api/Web/GetFileByServerRelativePath(decodedurl='/DocLibrary/pdf_file.pdf')/$value", 
			type: 'get',  
			contentType: true, 
			processData: false, 
			headers: { accept: 'application/json',
					  "Authorization": "Bearer "+code,
					 },
			success: function(response){
				alert('success response'+response)
				var a = document.createElement('a');
				var binaryData = [];
				binaryData.push(response);
				var url = window.URL.createObjectURL(new Blob(binaryData),{type: "application/octet-stream"});
			   
				a.href = url;
				a.download = 'pdf_file.pdf';
				document.body.appendChild(a);
				a.click();
				a.remove();
				window.URL.revokeObjectURL(url);
			},
		});
	}
</script>

He did try to add responseType :’arraybuffer’ or responseType :’blob’, or use ‘binaryStringResponseBody : true’, but neither of them have helped to open the downloaded content as PDF successfully.

He was able to get the response back from SharePoint online, but it was not recognized as intended content type, i.e. PDF. In console it looked like above.

To fix this we had to force the stream to be treated and parsed as ‘text/plain’, and it worked beautifully!!

Here is the modified code, which has worked:

<script type="text/javascript">
window.onload = () => {
	let code = '{!ACCESS_TOKEN}';   

	$.ajax({
		url: "https://<YourSharePointSite>.sharepoint.com/_api/Web/GetFileByServerRelativePath(decodedurl='/DocLibrary/pdf_file.pdf')/$value", 
		type: 'get',  
		contentType: true, 
		processData: false,
		encoding: null,
		headers: { 
			accept: 'application/json',
			"Authorization": "Bearer " + code
			},
		beforeSend: function (request) {
			request.overrideMimeType('text/plain; charset=x-user-defined');
			},
		success: function(response){
			var binary = "";
			var responseTextLen = response.length;

			for ( i = 0; i < responseTextLen; i++ ) {
				binary += String.fromCharCode(response.charCodeAt(i) & 255)
			}

			var a = document.createElement('a');
			a.href = "data:application/pdf;base64," + btoa(binary);
			a.download = 'pdf_file.pdf';
			document.body.appendChild(a);
			a.click();
			a.remove();
		},
	});
}
</script>

Take a look at ‘beforeSend’, using this we are forcing the requested MIME type as ‘text/plain’, instead of the arraybuffer response.

Here is an alternate implementation of the ‘success’ method using JavaScript FileReader API.

success: function(response){                
                var i = 0,
                dataArray = new Uint8Array(response.length);
                for (; i < response.length; i++) {
                    dataArray[i] = response.charCodeAt(i)
                }

                var blob = new Blob([dataArray.buffer], {
                    type: "application/pdf"
                });
                let link = document.createElement('a');
                link.download = 'pdf_file.pdf';

                let reader = new FileReader();
                reader.readAsDataURL(blob); // converts the blob to base64 and calls onload

                reader.onload = function() {
                  link.href = reader.result;
                  link.click();
                };
            }

This code should work for any file types. We just have to change the file type (MIME type) properly.

Here is a list of Microsoft file types and MIME types:

File extensionFile typeMIME type
.docxMicrosoft Office Word 2007 documentapplication/vnd.openxmlformats-officedocument.wordprocessingml.document
.docmOffice Word 2007 macro-enabled documentapplication/vnd.ms-word.document.macroEnabled.12
.dotxOffice Word 2007 templateapplication/vnd.openxmlformats-officedocument.wordprocessingml.template
.dotmOffice Word 2007 macro-enabled document templateapplication/vnd.ms-word.template.macroEnabled.12
.xlsxMicrosoft Office Excel 2007 workbookapplication/vnd.openxmlformats-officedocument.spreadsheetml.sheet
.xlsmOffice Excel 2007 macro-enabled workbookapplication/vnd.ms-excel.sheet.macroEnabled.12
.xltxOffice Excel 2007 templateapplication/vnd.openxmlformats-officedocument.spreadsheetml.template
.xltmOffice Excel 2007 macro-enabled workbook templateapplication/vnd.ms-excel.template.macroEnabled.12
.xlsbOffice Excel 2007 binary workbookapplication/vnd.ms-excel.sheet.binary.macroEnabled.12
.xlamOffice Excel 2007 add-inapplication/vnd.ms-excel.addin.macroEnabled.12
.pptxMicrosoft Office PowerPoint 2007 presentationapplication/vnd.openxmlformats-officedocument.presentationml.presentation
.pptmOffice PowerPoint 2007 macro-enabled presentationapplication/vnd.ms-powerpoint.presentation.macroEnabled.12
.ppsxOffice PowerPoint 2007 slide showapplication/vnd.openxmlformats-officedocument.presentationml.slideshow
.ppsmOffice PowerPoint 2007 macro-enabled slide showapplication/vnd.ms-powerpoint.slideshow.macroEnabled.12
.potxOffice PowerPoint 2007 templateapplication/vnd.openxmlformats-officedocument.presentationml.template
.potmOffice PowerPoint 2007 macro-enabled presentation templateapplication/vnd.ms-powerpoint.template.macroEnabled.12
.ppamOffice PowerPoint 2007 add-inapplication/vnd.ms-powerpoint.addin.macroEnabled.12
.sldxOffice PowerPoint 2007 slideapplication/vnd.openxmlformats-officedocument.presentationml.slide
.sldmOffice PowerPoint 2007 macro-enabled slideapplication/vnd.ms-powerpoint.slide.macroEnabled.12
.oneMicrosoft Office OneNote 2007 sectionapplication/msonenote
.onetoc2Office OneNote 2007 TOCapplication/msonenote
.onetmpOffice OneNote 2007 temporary fileapplication/msonenote
.onepkgOffice OneNote 2007 packageapplication/msonenote
.thmx2007 Office system release themeapplication/vnd.ms-officetheme

You can also check the common MIME types list from Mozilla. https://developer.mozilla.org/en-US/docs/Web/HTTP/Basics_of_HTTP/MIME_types/Common_types

Hope this will help someone in need.

Reading and Writing files in Java


Reading a File:

/*
* FileInputDemo
* Demonstrates FileInputStream and
* DataInputStream
*/

import java.io.DataInputStream;
import java.io.FileInputStream;

public class FileInputDemo { public static void main(String args[]) {

// args.length is equivalent to argc in C

  if (args.length == 1) {       try {

         // Open the file that is the first
         // command line parameter

         FileInputStream fstream = new FileInputStream(args[0]);
         // Convert our input stream to a DataInputStream

        DataInputStream in = new DataInputStream(fstream);

        // Continue to read lines while there are still some left to read

        while (in.available() != 0) {
         
// Print file line to screen
         
System.out.println(in.readLine());
        }

          in.close();

      } catch (Exception e) {
         System.
err.println(“File input error”);
    }
  } else{
     
System.out.println(“Invalid parameters”);
  }

 }

}

Now we know that readLine method of DataInputStream is depricated. So we can use BufferedReader in this case,

     try {
       BufferedReader br = new BufferedReader(new FileReader(args[0]));
       while ((thisLine = br.readLine()) != null) { // while loop begins here
         System.out.println(thisLine);
       } // end while
     } // end try
     catch (IOException e) {
       System.err.println(“Error: ” + e);
     }

Wrinitg Files in Java:

/*
*
* FileOutputDemo
*
* Demonstration of FileOutputStream and
* PrintStream classes
*
*/

import java.io.*;

class FileOutputDemo
{

        public static void main(String args[])
        {             
                FileOutputStream out; // declare a file output object
                PrintStream p; // declare a print stream object

                try
                {
                        // Create a new file output stream
                        // connected to “myfile.txt”

                        out = new FileOutputStream(“myfile.txt”);

                        // Connect print stream to the output stream
                        p = new PrintStream( out );

                        p.println (“This is written to a file”);

                        p.close();
                }
                catch (Exception e)
                {
                        System.err.println (“Error writing to file”);
                }
        }
}

Now we can also use a relative path to input the file.

Like:

String filePath = System.getProperty(“user.dir”)+ \\log\\;
FileInputStream fstream =
new FileInputStream(filePath + “my-log.txt”);

This code will take the file as input which is in log directory under the main folder and whose name  is my-log.txt.