Displaying binary file (pdf) in IE 11 - javascript

I am trying to display a binary file using the method suggested in this post AngularJS: Display blob (.pdf) in an angular app. This is working nicely in Chrome and FF, but IE 11 is giving me "Error: Access Denied".
Does anyone know if it has something to do with the Blob object and can point me in the right direction?
Here is my js code:
$http.get(baseUrl + apiUrl, { responseType: 'arraybuffer' })
.success(function (response) {
var file = new Blob([response], { type: 'application/pdf' });
var fileURL = URL.createObjectURL(file);
$scope.pdfContent = $sce.trustAsResourceUrl(fileURL);
})
.error(function () {
});
and my html:
<div ng-controller="PDFController" class="modal fade" id="pdfModal" tabindex="-1" role="dialog" aria-hidden="true">
<div class="modal-dialog modal-lg">
<div class="modal-content" onloadstart="">
<object data="{{pdfContent}}" type="application/pdf" style="width:100%; height:1000px" />
</div>
</div>

IE 11 blocks display of blob, you need to use the following:
var byteArray = new Uint8Array(someByteArray);
var blob = new Blob([byteArray], { type: 'application/pdf' });
if (window.navigator && window.navigator.msSaveOrOpenBlob) {
window.navigator.msSaveOrOpenBlob(blob);
}
else {
var objectUrl = URL.createObjectURL(blob);
window.open(objectUrl);
}

Related

How to send a cropped image in formData to PHP

I have a form with several inputs. One input is a file uploader. I'm using Cropperjs. That is working fine. It produces a base64 img. I want to be able to pass this cropped preview image to a php page for processing along with other post variables as ajax formData. I'm able to pass the other $_POST variables via the submit button in php. How do I get the image to pass it?
To me it seems to not be appending to the formData or I am not asking for the right FILES var...
https://jsfiddle.net/nick1572/c6027thL/6/
HTML
<div class="modal fade" id="modal" tabindex="-1" role="dialog" aria-labelledby="modalLabel" aria-hidden="true">
<div class="modal-dialog" role="document">
<div class="modal-content">
<div class="modal-header">
<h5 class="modal-title" id="modalLabel">Crop the image</h5>
<button type="button" class="close" data-dismiss="modal" aria-label="Close">
<span aria-hidden="true">×</span>
</button>
</div>
<div class="modal-body">
<div class="img-container">
<img id="image" src="https://avatars0.githubusercontent.com/u/3456749">
</div>
</div>
<div class="modal-footer">
<button type="button" class="btn btn-secondary" data-dismiss="modal">Cancel</button>
<button type="button" class="btn btn-primary" id="crop">Crop</button>
</div>
</div>
</div>
</div>
<!--end modal-->
<div class="file_drop_zone">
<div class="preview">
<img id="preview_image" accept="image/*"><!-- this is the image that needs to be passed.-->
</div><!--end preview-->
<div class="file__controls">
<label for="file_input">
<i class="fa fa-upload download_icon"></i><br>
<span class="drag__files_or">Drag File in or</span>
<span class="choose__file_btn">Choose File</span>
<input type="file" name="file" id="file_input">
</label>
</div>
</div><!--End file_uploader-->
JS
// Set the vars
var drop_zone = document.querySelector('.file_drop_zone');
var input = document.getElementById('file_input');
var image = document.getElementById('image');
var preview_image = document.getElementById('preview_image');
var preview_wrapper = document.querySelector('.preview');
var $modal = $('#modal');
var cropper;
var $submit = $('.seminar_form_submit');
var $event_form = $('.seminar_event_form');
// Create a function to read the file upload
// provided by the user.
function readFile(event) {
var url;
// File passed to FileList
var file = event.target;
// create a variable to pass in the the url.
// In this case it is the reader result. Then
// show the bootstrap modal.
var done = function (url) {
input.value = '';
image.src = url;
$modal.modal('show');
};
// Create a new File Reader instance
// for getting the result
var reader = new FileReader();
reader.onload = function() {
done(reader.result);
};
// If the event type is a 'change' then grab the
// file otherwise if the file is a 'drop'
// we get the file through the dataTransfer
if (event.type === 'change') {
reader.readAsDataURL(file.files[0]);
console.log(file.files[0]);
} else if (event.type === 'drop') {
reader.readAsDataURL(event.dataTransfer.files[0]);
}
}
// Once the modal is shown, create a new cropper instance and
// assign it to the #image div. // Once the modal is hidden
// destroy the instance for resetting cropper.
$modal.on('shown.bs.modal', function () {
/* global Cropper */
cropper = new Cropper(image, {
aspectRatio: 1,
viewMode: 0,
zoomable: true,
cropBoxMovable: true,
minContainerWidth: 100,
minContainerHeight: 100,
autoCropArea: 0.5
});
}).on('hidden.bs.modal', function () {
cropper.destroy();
cropper = null;
});
// Add listener to the crop button on the modal. If there is a cropper
// instance then set the canvas to the getCroppedCanvas function
// provided by cropperjs. We can set the dims there. We want to set the initial
// preview image src to the canvas. This is now a string in the form of
// a base64. Then hide the modal.
var crop = document.getElementById('crop');
var canvas;
var initialPreviewURL;
crop.addEventListener('click', function (crop) {
canvas = cropper.getCroppedCanvas({
width: 180,
height: 180,
fillColor: '#fff',
imageSmoothingEnabled: false,
imageSmoothingQuality: 'high'
});
initialPreviewURL = preview_image.src;
preview_image.src = canvas.toDataURL();
preview_wrapper.style.display = 'block';
$modal.modal('hide');
});
$event_form.on('submit', function(e) {
e.stopPropagation();
e.preventDefault();
var form_data = new FormData(document.getElementById('my_form'));
canvas.toBlob(function(blob) {
form_data.append('preview_image', blob);
for (var key of form_data.entries()) {
console.log(key);
}
});
$.ajax({
url: 'create_event.php',
data: form_data,
cache: false,
processData: false,
contentType: false,
type: 'POST',
success: function() {
console.log('success');
},
error: function () {
preview_image.src = initialPreviewURL;
},
complete: function () {
console.log('completed');
}
});
});
I am able to see the output in the console. By using a for loop on the entries
["preview_image", File]
If I error_log on the php. The output only shows 'error here' it does not show the preview_image
error_log("error here");
error_log($_FILES['preview_image']);
Here is the output from the Network > Response tab on the php page.
var_dump($_POST); or var_dump($_FILES);
array(9) {
["subject"]=>
string(12) "Persons Name"
["details"]=>
string(39) "Designer and wanna be web developer...."
["event-title"]=>
string(21) "This is another title"
["location"]=>
string(58) "This place"
["aux"]=>
string(13) "George Carlin"
["start-date"]=>
string(10) "2019-10-18"
["start-time"]=>
string(5) "08:00"
["end-date"]=>
string(10) "2019-10-18"
["end-time"]=>
string(5) "09:00"
}
array(1) {
["file"]=>
array(5) {
["name"]=>
string(0) ""
["type"]=>
string(0) ""
["tmp_name"]=>
string(0) ""
["error"]=>
int(4)
["size"]=>
int(0)
}
thanks!!
Well after digging around for a few days I went with just adding a hidden field and setting that value as the base64 string. I already had a ton of PHP error handling scripts already so I removed the ajax call. Now, the base64 string gets passed along with the POST array.

Finding source of Image for PDF

so I am trying to figure out how I can change the image of this pdf template that was created for me on my Django App. I tried to change the img src to a direct link of the picture that I would like but the result turned out to be the same picture. What might be the best way to change the image?
Here is what appears in the template:
<td width="33%" style="margin-left: 20px;">
<img src="/site_media/css/output/images/logo1.jpg" width="100" style="display:inline; margin-right: 20px">
</td>
The JS file:
$scope.dw_receiving_receipt = function(elem, user, harvest_date) {
var data = {};
data.receiving_action_id = 'DASHBOARD';
data.seller_id = user;
data.harvest_date = moment(harvest_date, 'MM-DD-YYYY').format("YYYY-MM-DD");
data.plu_code = elem.plu_code.id;
data.seller_inventory = elem.selected_seller_inventory.seller_inventory;
$http.post('/inventories/print_receipt/', data, {
data: JSON
}).success(function(data, status, headers, config) {
$scope.success = true;
$scope.save_message = "Receiving receipt fetched successfully.";
var blob = new Blob([data], {
type: "application/pdf;"
});
saveAs(blob, 'receiving_receipt.pdf');
}).error(function(data, status, headers, config) {
$scope.error = true;
$scope.save_message = "Could not fetch receiving receipt.";
alert("Could not fetch receiving receipt.");
});
};
And the views.py:
def fetch_resources(uri, rel):
if uri == '/site_media/css/output/images/logo.jpg':
path = os.path.join(settings.BASE_DIR ,"accounts", "static", "accounts", "img","aggri_logo.jpg")
else:
path = os.path.join(settings.BASE_DIR ,"accounts", "static", "accounts", "img","Logo ALBA Organics.jpg")
return path
I have tried many different ways to changing the img src myself but its not budging.

How to display PDF (Blob) on iOS sent from my angularjs app

My Angular 1.5 application connect to a Java/Tomcat/Spring backend server via REST.
One REST service generates PDF and send it to the client. It works fine on DEsktop browsers (FF, Chrome at least) but I cannot see the PDF content on iOS (ipad for instance) whatever the browser I am using (Chrome, Safari..)
Here is the Angular Code :
$http.get("/displayPdf", {responseType: 'arraybuffer', params: {id: 1}}).
success(function(data) {
var blob = new Blob([data], {type 'application/pdf'});
var objectUrl = window.URL.createObjectURL(blob);
window.open(objectUrl);
}
);
The Spring/Jax-RS code is :
#GET
#Path("displayPdf")
#Produces("application/pdf")
Response displayPdf(#QueryParam("id") Long id) {
byte[] bytes = service.generatePdf();
return javax.ws.rs.core.Response.ok().
entity(bytes).
header("Content-Type", "pdf").
header("Content-Disposition", "attachment; filename='test.pdf'").
build();
}
I have done my research here for instance(AngularJS: Display blob (.pdf) in an angular app) but could not find an appropriate solution.
So please, do you know what should I do to display the generated PDF to my iPad/iPhone end-users ?
Thanks a lot
None of the solutions proposed above did work for me.
The main issue comes from URL that wasn't retrieved correctly in iOS. The following code do the correct work :
window.URL = window.URL || window.webkitURL;
Also even with this, it did not work on Chrome iOS, neither Opera iOS...so after digging the internet and inspired with the following questions :
Blob createObjectURL download not working in Firefox (but works when debugging)
How to open Blob URL on Chrome iOS
Display blob (.pdf) in an angular app
... I finally ended up with the following code (working on all iOS browsers except FF on iOS) :
if (window.navigator.msSaveOrOpenBlob) { //IE 11+
window.navigator.msSaveOrOpenBlob(blob, "my.pdf");
} else if (userAgent.match('FxiOS')) { //FF iOS
alert("Cannot display on FF iOS");
}
} else if (userAgent.match('CriOS')) { //Chrome iOS
var reader = new FileReader();
reader.onloadend = function () { $window.open(reader.result);};
reader.readAsDataURL(blob);
} else if (userAgent.match(/iPad/i) || userAgent.match(/iPhone/i)) { //Safari & Opera iOS
var url = $window.URL.createObjectURL(blob);
window.location.href = url;
}
Just add the below code as your $http call.I've handled for other browsers as well.
$http.get("/displayPdf", {responseType: 'arraybuffer', params: {id: 1}}).success(function(data) {
var blob = new Blob([data], {type 'application/pdf'});
var anchor = document.createElement("a");
if(navigator.userAgent.indexOf("Chrome") != -1||navigator.userAgent.indexOf("Opera") != -1){
$window.open(URL.createObjectURL(file,{oneTimeOnly:true}));
}else if(navigator.userAgent.indexOf("iPad") != -1){
var fileURL = URL.createObjectURL(file);
//var anchor = document.createElement("a");
anchor.download="myPDF.pdf";
anchor.href = fileURL;
anchor.click();
}else if(navigator.userAgent.indexOf("Firefox") != -1 || navigator.userAgent.indexOf("Safari") != -1){
var url = window.URL.createObjectURL(file);
anchor.href = url;
anchor.download = "myPDF.pdf";
document.body.appendChild(anchor);
anchor.click();
setTimeout(function(){
document.body.removeChild(anchor);
window.URL.revokeObjectURL(url);
}, 1000);
}
});
i use basically your same setup but i build my pdf differently using, unable to test with iOS but i hope this helps some
$http({ url: $scope.url,
method: "GET",
headers: { 'Accept': 'application/pdf' },
responseType: 'arraybuffer' })
.then(function (response) {
var file = new Blob([response.data], {type: 'application/pdf'});
var fileURL = URL.createObjectURL(file);
$scope.pdfContent = $sce.trustAsResourceUrl(fileURL);
});//end http

base64 code send to server by java script, ajax

I am using Html5, Java script, ajax and java. I am uploading a image from desktop to the crop and after the crop it is showing in bootstrap modal in same page. But i am not getting URL for this Image, I am getting some Base64 code and when i am sending this base64 code than it is not working.
I seen this post but i did not get any solution from this link:
https://stackoverflow.com/
This code for static image, Showing first time.
My code:
HTML:
<div class="img-container">
<img src="../assets/img/picture.jpg" alt="Picture">
</div>
<div class="modal fade docs-cropped" id="getCroppedCanvasModal" aria-hidden="true" aria-labelledby="getCroppedCanvasTitle" role="dialog" tabindex="-1">
<div class="modal-footer">
<button type="button" class="btn btn-default" data-dismiss="modal">Close</button>
<a class="btn btn-primary" id="download" download="cropped.png" href="javascript:void(0);">Upload</a>
</div>
</div>
Java script Code:
(function () {
var $image = $('.img-container > img');
var $download = $('#download');
$('#getCroppedCanvasModal').modal().find('.modal-body').html(result);
if (!$download.hasClass('disabled')) {
$download.attr('href', result.toDataURL());
//console.log("*****************"+result.toDataURL());
var swapUrl = result.toDataURL();
console.log("*******" + swapUrl);
// document.getElementById('replaceMe').src = swapUrl;
$('#download').click(function () {
var b = result.toDataURL();
$.ajax({
url: "/sf/p/customizeText",
type: 'GET',
data: b,
success: function (response) {
console.log("999999999999999999999999999999999----------------" + b)
},
complete: function (response) {
},
error: function (response) {
}
});
});
}
}
I am assign result.toDataURL() into variable b. But it is showing some base64 code.
How i am send this image to server.
I am giving one snippet.
Please give me some idea achieve to this solution.
Hi you can check this solution also
Javascript code
var base64before = document.querySelector('img').src;
var base64 = base64before.replace(/^data:image\/(png|jpg);base64,/, "");
var httpPost = new XMLHttpRequest();
var path = "your url";
var data = JSON.stringify(base64);
httpPost.open("POST", path, false);
// Set the content type of the request to json since that's what's being sent
httpPost.setRequestHeader('Content-Type', 'application/json');
httpPost.send(data);
This is my Java code.
public void saveImage(InputStream imageStream){
InputStream inStream = imageStream;
try {
String dataString = convertStreamToString(inStream);
byte[] imageBytes = javax.xml.bind.DatatypeConverter.parseBase64Binary(dataString);
BufferedImage image = ImageIO.read(new ByteArrayInputStream(imageBytes));
// write the image to a file
File outputfile = new File("/Users/paul/Desktop/testkey/myImage.png");
ImageIO.write(image, "png", outputfile);
}catch(Exception e) {
System.out.println(e.getStackTrace());
}
}
static String convertStreamToString(java.io.InputStream is) {
java.util.Scanner s = new java.util.Scanner(is).useDelimiter("\\A");
return s.hasNext() ? s.next() : "";
}

Prevent blank page on bad file download

In our Angular JS application, I am downloading a file by simply calling window.location.
HTML:
<div class="row">
<div class="col-md-3 col-sm-4 col-xs-6" ng-repeat="file in files">
<div class="well well-sm truncate">
<a href="" title="Download {{file.FileName}}" ng-click="download(file)" ><b>{{file.FileName}}</b></a><br />
<small>{{(file.FileSize/1024)|number:2}} KB</small><br />
<i class="fa fa-trash CP text-danger pull-right" ng-show="mUser.Role>=20" title="Delete file" ng-click="deletefiles(file.AttID)"></i>
<small>Uploaded by {{file.AddedByName}} on {{file.Created|date:'dd MMM yyyy'}}</small>
</div>
</div>
</div>
Angular method:
$scope.download = function (ff) {
if (confirm('Download this file?')) window.location = "api/files/download?token=" + $rootScope.token + "&IDKey=" + ff.IDKey;
}
Web API Controller Method:
[HttpGet]
public HttpResponseMessage download(string Token, string IDKey)
{
HttpResponseMessage lResponse = new HttpResponseMessage(HttpStatusCode.OK);
// Validate request
Result lRes = UserClass.GetUserByToken(Token);
if (!lRes.IsSuccess)
{
lResponse.Content = new StringContent("User Token is invalid");
lResponse.StatusCode = HttpStatusCode.Forbidden;
return lResponse;
}
// Get File object
AttClass lAtt = AttClass.GetFile(IDKey);
if (!lAtt.IsOk)
{
lResponse.Content = new StringContent("Attachment ID Key is invalid");
lResponse.StatusCode = HttpStatusCode.NotFound;
return lResponse;
}
// Return file
lResponse.Content = new StreamContent(new FileStream(lAtt.GetFullPath(), FileMode.Open, FileAccess.Read));
lResponse.Content.Headers.ContentDisposition = new ContentDispositionHeaderValue("attachment") { FileName = lAtt.FileName };
lResponse.Content.Headers.ContentType = new MediaTypeHeaderValue("application/octet-stream");
return lResponse;
}
The file download works very well when Token and IDKey is valid. However, in other cases, the user is shown a blank page with a simple error message. Can I prevent this and just display an alert on the original page with the reason why the download failed?
PS: I do not want to use the HTML5 SaveAs functionality or filesaver.js.
you can try this
1- Did you try downloading file using iframe instead of the using
window.location
document.getElementById("myiframe").src="api/files/download?token=" + $rootScope.token + "&IDKey=" + ff.IDKey;
and the check the iframe body
document.getElementById('myiframe').contentDocument.body.innerHTML
Re EDIT
document.getElementById("myiframe").src="your url";
document.getElementById("myiframe").addEventListener("load",
function(){
console.log(this.contentDocument.contentType);
if(!(document.getElementById("myiframe").contentDocument.contentType=="application/octet-stream"))
alert("Downlaod Failed");
else
alert("Thank you for downloading");
});
Its very dificult to handle server response when you are using window.location.
You can use ajax call in angularJs to download or you can check your response too.
$http({
url: 'server/url',
method: "POST",
responseType: 'arraybuffer'
}).success(function (data, status, headers, config) {
//check your response here
//smaple code for excel download
var blob = new Blob([data], {type: "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet"});
var objectUrl = URL.createObjectURL(blob);
var anchor = angular.element('<a/>');
anchor.attr({
href: objectUrl,
target: '_blank',
download: fileName + '_' + new Date().getTime() + '.xlsx'
})[0].click();
}).error(function (data, status, headers, config) {
});
`

Categories