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
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.
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.
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
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() : "";
}
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) {
});
`