jquery ajax open file in browser - ajax

I have the following code that allows me to download a file and save it:
jQuery.ajax({
url: file['url'],
method: 'GET',
xhrFields: {
responseType: 'blob'
},
success: function (data) {
const a = document.createElement('a');
const url = window.URL.createObjectURL(data);
a.href = url;
a.download = file['label'];
a.click();
window.URL.revokeObjectURL(url);
}
});
If the file is a PDF or text I would like to open it in the browser rather than save it. Is it possible? i know how to detect the type (PDF, text) but I do not know how to force the browser to open the file in a net tab or window. I am using Chrome.
Thank you

Related

csrf-token mismatch error in laravel on server

I'm using this code to submit data through ajax in laravel
$('#submit').submit(function (e) {
e.preventDefault();
let formData = new FormData(this);
$.ajaxSetup({
headers: {
'X-CSRF-TOKEN': $('meta[name="csrf-token"]').attr('content')
}
});
$.ajax({
xhr: function() {
var xhr = new window.XMLHttpRequest();
xhr.upload.addEventListener("progress", function(evt) {
if (evt.lengthComputable) {
var percentComplete = evt.loaded / evt.total;
percentComplete = parseInt(percentComplete * 100);
if (percentComplete === 100) {
}
}
}, false);
return xhr;
},
url: $(this).attr('action'),
type: "POST",
data: formData,
dataType:'JSON',
contentType:false,
cache: false,
processData: false,
but getting csrf token mismatch when i upload my code on live server.
Any solution is highly appreciated Thanks
I see you are fetching the token from the HTML page metatag, make sure your HTML page is not being cached by an intermediate/browser between accesses (try opening with two different browsers and checking the token, refreshing with f5 and force reloading too).
Another common issue is multiple HTML pages being loaded simultaneously (frames? maybe a 404 file that returns your default page, refreshing the token for your session). This is hard to find, check the network tab of your browser dev tools and inspect each response.
I don't think it's the case, but sometimes the case makes difference X-CSRF-Token if a proxy is "cleaning up non whitelisted headers".

Safari downloads blob file as example.com

I am using an Ajax POST request to generate a PDF document and send it to the user. Everything works normally in Chrome, Edge, Firefox but Safari on Mac and IPhone downloads the file as example.com.
I am using this function that I found SO:
function downloadFile(data, filename, mime) {
// It is necessary to create a new blob object with mime-type explicitly set
// otherwise only Chrome works like it should
const blob = new Blob([data], {type: mime || 'application/octet-stream'});
if (typeof window.navigator.msSaveBlob !== 'undefined') {
// IE doesn't allow using a blob object directly as link href.
// Workaround for "HTML7007: One or more blob URLs were
// revoked by closing the blob for which they were created.
// These URLs will no longer resolve as the data backing
// the URL has been freed."
window.navigator.msSaveBlob(blob, filename);
return;
}
// Other browsers
// Create a link pointing to the ObjectURL containing the blob
const blobURL = window.URL.createObjectURL(blob);
const tempLink = document.createElement('a');
tempLink.setAttribute('download', filename);
tempLink.style.display = 'none';
tempLink.href = blobURL;
// Safari thinks _blank anchor are pop ups. We only want to set _blank
// target if the browser does not support the HTML5 download attribute.
// This allows you to download files in desktop safari if pop up blocking
// is enabled.
if (typeof tempLink.download === 'undefined') {
tempLink.setAttribute('target', '_blank');
}
document.body.appendChild(tempLink);
tempLink.click();
document.body.removeChild(tempLink);
setTimeout(() => {
// For Firefox it is necessary to delay revoking the ObjectURL
window.URL.revokeObjectURL(blobURL);
}, 500);
}
this is the ajax request:
$.ajax({
url: '{{ path('create_list') }}',
data: data,
processData: false,
contentType: false,
cache: false,
type: 'post',
enctype: 'multipart/form-data',
xhrFields: {
responseType: 'blob'
},
success: function(data, status, xhr) {
model.isCreating(false);
let date = new Date();
let name = `${model.wineList.companyName() }
_${date.getHours()}
_${date.getMinutes()}
_${date.getSeconds()}.pdf`;
downloadFile(data, name, 'application/pdf')
Swal.close();
{% if app.debug %}
console.log(data);
{% endif %}
-----------
I checked that Safari supports the a.download attribute but for some reason ignores it.
Any idea what might be the problem?
The problem was at this line:
let name = `${model.wineList.companyName() }
_${date.getHours()}
_${date.getMinutes()}
_${date.getSeconds()}.pdf`;
for some reason, the line breaks made Safari to revert to example.com ignoring the name.

Converting ZIP to a Blob

In our Ruby on Rails application we have a controller action that sends a ZIP:
send_data File.read(zip_pathname), filename: zip_filename, type: 'application/zip'
We make this downloadable using the download attribute on a link like so:
<%= link_to zip_download_path(#object), download: zip_filename do %>
<i class="fas fa-download fa-fw"></i> Download ZIP
<% end %>
Which works fine, but can take up to 5-6 seconds before anything happens (due to the ZIP size)
To prevent the user clicking the link again and to show something is happening we have tried to retrieve the download using AJAX and then turn it into a Blob and use FileReader to download it:
const reader = new FileReader();
reader.onload = function(e) {
const anchor = document.createElement('a');
anchor.style.display = 'none';
anchor.href = e.target.result;
anchor.download = 'download';
anchor.click();
hideLoading();
}
$('[download]').on('click', function (e) {
e.preventDefault();
showLoading();
var download = $(this);
$.get(download.attr('href'), function (data) {
const blob = new Blob([data], { name: download.attr('download'), type: 'application/zip' });
reader.readAsDataURL(blob);
});
});
This successfully shows the loading screen and then downloads the ZIP and hides the loading screen again with the exception that the ZIP is returned as download error instead of the actual ZIP like before... it would seem the conversion of the ZIP to a Blob is where it fails...
Is it possible to convert a ZIP to a Blob? And is there anything wrong in the code above?
Looking at: e.target.result the content is:
data:application/zip;base64,...
So it looks like it has successfully created the data... however when I try and open up that in a browser window it doesn't show anything...
If you're downloading a non text file (like a zip file) via ajax, you have to specify a responseType, a binary one, in the example below I set it as blob so that the data you receive in the ajax response will be a blob.
A blob url is created and used in the anchor instead of a bulky data uri.
$.ajax({
url:download.attr('href'),
cache:false,
xhrFields:{
responseType: 'blob'
},
success: function(data){
var blobUrl = window.URL.createObjectURL(data);
const anchor = document.createElement('a');
anchor.style.display = 'none';
anchor.href = blobUrl;
anchor.download = 'download.zip';
anchor.click();
hideLoading();
},
error:function(){
}
});
jQuery 3+ needed for this to work.
Just wanted to share this for anyone who wants to do this without using jQuery3... based on the answer posted by Musa: https://stackoverflow.com/a/60510567/302533
$('[download]').on('click', function (e) {
e.preventDefault();
showFullScreenLoading();
var $this = $(this);
var request = new XMLHttpRequest();
request.open('GET', $this.attr('href'), true);
request.responseType = 'blob';
request.onload = function (e) {
var data = request.response;
var blobUrl = window.URL.createObjectURL(data);
var downloadLink = document.createElement('a');
downloadLink.href = blobUrl;
downloadLink.download = $this.attr('download') || 'download';
downloadLink.click();
hideFullscreenLoading();
};
request.send();
});

How to PUT a binary file with javascript/jQuery to webdav?

How can I PUT a binary file, say an image with an HTTP PUT request to webdav? I already tried base64 encoding, but the file is broken.
$.ajax({
url: url + file,
data:base64content,
type: 'PUT',
crossDomain: true,
headers:{'content-type':'image/png'},
xhrFields:{withCredentials: true}
});
I've found a solution on this site:
https://developer.mozilla.org/en-US/docs/Web/API/XMLHttpRequest/Sending_and_Receiving_Binary_Data
var oReq = new XMLHttpRequest();
oReq.open("POST", url, true);
oReq.onload = function (oEvent) {
// Uploaded.
};
var blob = new Blob(['abc123'], {type: 'text/plain'});
oReq.send(blob);

Call controller in Ajax to download a file in Grails

I'm new to Grails and I'm having troubles for downloading a document generated in my controller.
My jQuery
$("#exportAllSelectedData").click(function() {
var dataToExport = $("#dataToExport").val();
jQuery.ajax(
{type:'POST',
data:'dataToExport=' + dataToExport ,
dataType: 'json',
url:'/myapp/mycontroller/exportPreferences'});;
});
My Controller
def exportPreferences ()
{
File file = File.createTempFile("export",".xml");
String dataToWrite = params.dataToExport;
file.write(dataToWrite);
response.contentType = "application/octet-stream";
response.setHeader "Content-disposition", "attachment; filename=${file.name}";
response.outputStream << file.bytes;
response.outputStream.flush();
}
I was expecting to download the outputStream with my browser but nothing happened.
What am I doing wrong ?
Edit :
Thanks Rahul.
It worked fine with:
$("#exportAllSelectedData").click(function() {
var dataToExport = $("#dataToExport").val();
window.location="<g:createLink controller="mycontroller"
action="exportPreferences"/>"+"?dataToExport="+dataToExport
});
You do not required the Ajax to download a file.
You can simply use window.location to download your file.
Example:
$("#exportAllSelectedData").click(function() {
window.location="<g:createLink controller="mycontroller" action="exportPreferences" />"
});
If you try with Ajax, you will get(render) file text
Example:
$("#exportAllSelectedData").click(function() {
$.ajax({
type: "GET",
url: "<g:createLink controller="demo" action="exportPreferences" />",
success: function (data) {
console.log(data);
}
});
});
Hope this will helps you.

Resources