Failed to load PDF but can see the data - javascript

I am getting this error that Chrome failed to load the PDF document. I can see the content of the data is the console window so I have the data being returned I just not sure why it will not display? If I File.WriteAllBytes to disk it will open fine so it maybe something with the creating the new Blob
Failed to load PDF document.
ts code
printItems(versionKeys: string[]): JQueryPromise<any> {
console.log('printItems');
$.ajax({
type: "post",
contentType: "application/json",
data: JSON.stringify(versionKeys),
url: this.apiUrls.PrintTemplates,
success: function (data, status, xhr) {
console.log('printItems');
console.log(data);
let blob = new Blob([data.Content], { type: data.ContentType });
var url = URL.createObjectURL(blob);
console.log(url);
window.open(url);
console.log('success');
}
});
return;
}
Error

I converted the base64 string to a bytes
var binary_string = window.atob(data.Content)
var len = data.Content.length;
var bytes = new Uint8Array(len);
for (var i = 0; i < len; i++) {
bytes[i] = binary_string.charCodeAt(i);
}
let blob = new Blob([bytes.buffer], { type: data.ContentType })
var url = URL.createObjectURL(blob);
window.open(url);

Related

Failed to load pdf document after downloading the document from IE11

I have an ajax call where I am calling JSReport and downloading the pdf document. In chrome and other browsers, it works correctly. The document is downloaded and I can open it. But in IE11, the document is downloaded but if I want to open the pdf file, it always shows failed to load pdf document. I debugged the code in IE11 console, but it did not give any error.
Here is my code,
$.ajax({
url: 'my api url',
headers: { 'Accept': 'application/json', 'Content-Type': 'application/json' },
type: 'POST',
data: JSON.stringify(selectedIds),
success: function (data) {
var a = document.createElement('a');
var isIE = false || !!document.documentMode;
if (!isIE) {
// This part is working properly
for (var i = 0; i < data.length; i++) {
a.href = "data:application/octet-stream;base64," + data[i];
a.target = '_blank';
a.download = 'report.pdf';
a.click();
}
} else {
// This part is for IE11 browser where I have problem to load the document after download
for (var i = 0; i < data.length; i++) {
var file = new Blob([data[i]], {
type: 'application/octet-stream'
});
window.navigator.msSaveOrOpenBlob(file, 'report.pdf');
}
}
},
fail: function (jqXHR, textStatus) {
alert("Request failed: " + textStatus);
}
});
Finally, I found the solution! I actually needed to convert base64 string data to Blob. Then we can download it. Previously, it was not converted correctly. This was why the file was downloaded but failed to load since it was damaged. Here is my code is given below,
$.ajax({
url: 'my api url',
headers: { 'Accept': 'application/json', 'Content-Type': 'application/json' },
type: 'POST',
data: JSON.stringify(selectedIds),
success: function (data) {
var a = document.createElement('a');
var isIE = false || !!document.documentMode;
if (!isIE) {
// This part is working properly
for (var i = 0; i < data.length; i++) {
a.href = "data:application/octet-stream;base64," + data[i];
a.target = '_blank';
a.download = 'report.pdf';
a.click();
}
} else {
for (var i = 0; i < data.length; i++) {
var base64Data = data[i];
var fileName = 'report.pdf';
var byteCharacters = atob(base64Data);
var byteNumbers = new Array(byteCharacters.length);
for (var j = 0; j < byteCharacters.length; j++) {
byteNumbers[j] = byteCharacters.charCodeAt(j);
}
var byteArray = new Uint8Array(byteNumbers);
var blob = new Blob([byteArray], { type: 'application/pdf' });
window.navigator.msSaveOrOpenBlob(blob, fileName);
}
}
},
fail: function (jqXHR, textStatus) {
alert("Request failed: " + textStatus);
}
});

Api from Asp core controller not receive all the value that FormData.append(key,value) appended

I want to upload files(image, setup file) and some other text string together.
This is my ajax code:
function uploadFiles(inputId) {
var input = document.getElementById(inputId);
var files = input.files;
formData = new FormData();
for (var i = 0; i !== files.length; i++) {
var temp1 = files[i];
}
formData.append('temp', 1);
formData.append('temp', "ksjhdfksdjf");
$.ajax({
type: "POST",
url: "/Admin/FileUploadView/SaveEntity",
data: formData,
contentType: false,
processData: false,
beforeSend: function () {
tedu.startLoading();
},
success: function () {
},
error: function () {
}
});
}
This is my controller:
When I log all the files that formData object contain, everything is ok:
But I only receive 2 image's objects in the controller:
Now I want that I can receive all the files that I appended. Do you have any ideas, please help me.
You do not receive your temp in your controller.
js:
function uploadFiles(inputId) {
var input = document.getElementById(inputId);
var files = input.files;
var formData = new FormData();
for (var i = 0; i != files.length; i++) {
formData.append("files", files[i]);
}
formData.append('temp', 1);
formData.append('temp', "ksjhdfksdjf");
//ajax
controller:
[HttpPost]
public async Task<IActionResult> SaveEntity(IList<IFormFile> files,List<string> temp)

Uploading JavaScript Blob Issue

I'm trying to record a video (already working) using HTML5 video tag, "getUserMedia" to access the device camera and MediaRecorder API to capture the frames and Angular1 to handle the file uploading. Now I'm having trouble uploading the Blob to my PHP server which is running on Laravel, I currently have 2 ways to upload the video, first is by "ng-click" this works fine but when I programmatically upload the Blob using the same function which "ng-click" run it seems to break the mimeType of my Blob here's how my code looks.
$scope.uploader = function() {
let fData = new FormData();
let blob = new Blob($scope.chunk, { type: 'video/webm' });
fData.append('vid', blob)
$http.post(url, fData, {
transformRequest: angular.identity,
headers: {'Content-Type': undefined},
}, success, error)
})
$timeout(function() {
$scope.uploader();
}, 10000)
This issue here is when the "$scope.uploader()" is called using "ng-click" it works fine but when calling the "uploader" method using the "$timeout" it seems to change the mimeType to "application/octet-stream" which causes the issue.
Hello Try this code,
function base64ToBlob(base64Data, contentType) {
contentType = contentType || '';
var sliceSize = 1024;
var byteCharacters = atob(base64Data);
var bytesLength = byteCharacters.length;
var slicesCount = Math.ceil(bytesLength / sliceSize);
var byteArrays = new Array(slicesCount);
for (var sliceIndex = 0;sliceIndex <slicesCount;++sliceIndex) {
var begin = sliceIndex * sliceSize;
var end = Math.min(begin + sliceSize, bytesLength);
var bytes = new Array(end - begin);
for (var offset = begin, i = 0;offset <end;++i, ++offset) {
bytes[i] = byteCharacters[offset].charCodeAt(0);
}
byteArrays[sliceIndex] = new Uint8Array(bytes);
}
return new Blob(byteArrays, {
type: contentType});
}
Define scope
$scope.onFile = function(blob) {
Cropper.encode((file = blob)).then(function(dataUrl) {
$scope.dataUrl = dataUrl;
$scope.odataUrl = dataUrl;
$timeout(showCropper); // wait for $digest to set image's src
});
};
Submit method
$scope.uploadImage = function () {
if ($scope.myCroppedImage === '')
{
}
$scope.msgtype = "";
$scope.msgtxt = "";
var fd = new FormData();
var imgBlob = dataURItoBlob($scope.myCroppedImage);
fd.append('clogo', imgBlob);
fd.append('actionfile', 'editimage');
$http.post(
'../user/user_EditCompany.php',
fd, {
transformRequest: angular.identity,
headers: {
'Content-Type': undefined
}
}
)
.success(function (response) {
// console.log(response);
if (response.status == 'success')
{
//your code
}else{
//your code
}
})
.error(function (response) {
console.log('error', response);
});
};
function dataURItoBlob(dataURI) {
var binary = atob(dataURI.split(',')[1]);
var mimeString = dataURI.split(',')[0].split(':')[1].split(';')[0];
var array = [];
for (var i = 0; i < binary.length; i++) {
array.push(binary.charCodeAt(i));
}
return new Blob([new Uint8Array(array)], {
type: mimeString
});
}
Thanks, the issue was caused by upload and post limit in my php.ini.

Error when printing PDF file in AngularJS

I am trying to print a PDF file generated through reportViewer in my Web API, but the browser shows an error when tries to open the PDF file.
This is the code inside the controller in my Web API:
// ...generate candidatosDataSet
LocalReport relatorio = new LocalReport();
string rootPath = HttpRuntime.AppDomainAppPath;
relatorio.ReportPath = rootPath + #"\Reports\Report.rdlc";
relatorio.DataSources.Add(new ReportDataSource("Candidatos", candidatosDataSet));
relatorio.Refresh();
byte[] relatorioBytes = ExportUtils.GerarArquivoPDF(relatorio);
response = Request.CreateResponse(HttpStatusCode.OK, relatorioBytes);
response.Content.Headers.ContentDisposition = System.Net.Http.Headers.ContentDispositionHeaderValue.Parse("attachment; filename=relatorio.pdf");
response.Content.Headers.ContentType = new System.Net.Http.Headers.MediaTypeHeaderValue("application/pdf");
This is how I am generating PDF File through reportViewer
public static byte[] GerarArquivoPDF(LocalReport relatorio)
{
String reportType = "PDF";
String mimeType;
String encoding;
String fileNameExtension;
String deviceInfo;
Warning[] warnings;
string[] streams;
byte[] renderedBytes;
deviceInfo = "<DeviceInfo>" + " <OutputFormat>" + reportType + "</OutputFormat>" + "</DeviceInfo>";
renderedBytes = relatorio.Render(
reportType,
deviceInfo,
out mimeType,
out encoding,
out fileNameExtension,
out streams,
out warnings);
return renderedBytes;
}
Here is my AngularJS service method:
function obterTermoConfirmacaoCandidatura(candidatoId) {
return $http.get(configValues.baseUrl + 'candidato/GetRelatorio',
{
params: { candidatoId: candidatoId },
responseType: 'arraybuffer'
});
}
And this is the code that I am using to print the file on the AngularJS controller:
function imprimirTermoConfirmacaoCandidatura(id) {
CandidatoAPIService.obterTermoConfirmacaoCandidatura(id)
.then(function (response) {
var contentType = response.headers('Content-Type') || "application/octet-stream";
var file = new Blob([response.data], {
type: contentType
});
var fileUrl = URL.createObjectURL(file);
var printWindow = $window.open(fileUrl);
printWindow.print();
}, function (error) {
alert(error.data);
});
}
The response from Web API was comming as string, with double quotes in beginning and in the end of the response, so the PDF File could not be rendered correctly. Also I converted the response from server to base64, by this method:
function b64toBlob(b64Data, contentType) {
var sliceSize = 512;
b64Data = b64Data.replace(/"/g, '');
b64Data = b64Data.replace(/^[^,]+,/, '');
b64Data = b64Data.replace(/\s/g, '');
var byteCharacters = window.atob(b64Data);
var byteArrays = [];
for (var offset = 0; offset < byteCharacters.length; offset += sliceSize) {
var slice = byteCharacters.slice(offset, offset + sliceSize);
var byteNumbers = new Array(slice.length);
for (var i = 0; i < slice.length; i++) {
byteNumbers[i] = slice.charCodeAt(i);
}
var byteArray = new Uint8Array(byteNumbers);
byteArrays.push(byteArray);
}
var blob = new Blob(byteArrays, { type: contentType });
return blob;
}
And changed the method on AngularJS controller to convert the response do base64:
function imprimirTermoAutorizacaoUsoImagem() {
CandidatoAPIService.obterTermoAutorizacaoUsoImagem()
.then(function (response) {
var contentType = response.headers('Content-Type') || "application/octet-stream";
var file = UtilsService.b64toBlob(response.data, "application/pdf");
var fileUrl = URL.createObjectURL(file);
var printWindow = $window.open(fileUrl);
printWindow.print();
}, function (error) {
alert(error.data);
});
}
And removed the responseType on the AngularJS service:
function obterTermoConfirmacaoCandidatura(candidatoId) {
return $http.get(configValues.baseUrl + 'candidato/GetObterTermoConfirmacaoCandidatura',
{
params: { candidatoId: candidatoId }
});
}

Safari browsers sends blob/datauri as string in Node.js

I am trying to receive the file sent through AJAX. What's happening is that when the file sent using Chrome/Firefox the file goes to req.files but when it was sent using Safari, the file goes to req.params. The application treat the file as a string "[Object blob]". Thanks.
Sending userdata through ajax.
updatePartnerProfile: function(obj){
var parentObj = this;
var target = $(obj.target);
var parent = target.closest('#editPartnerDetailsForm');
var logoImg = parent.find('.cropped');
var companyLogoBase64 = logoImg.find('.croppedImage').attr('src');
var companyLogo = util.dataURItoBlob(companyLogoBase64);
var userData = new FormData();
userData.append('token', parentObj.token);
userData.append('companyLogo', companyLogo);
$.ajax({
type: 'POST',
url: parentObj.serverUrl + 'api/admin/update/organization/' + parentObj.partnerId,
processData: false,
contentType: false,
cache: false,
data: userData,
success: function(data){
//todo
}
},
error: function(err){
console.log(err);
}
});
},
dataURItoBlob : function(dataURI) {
// convert base64/URLEncoded data component to raw binary data held in a string
if (!_.isUndefined(dataURI)){
var byteString;
if (dataURI.split(',')[0].indexOf('base64') >= 0)
byteString = atob(dataURI.split(',')[1]);
else
byteString = unescape(dataURI.split(',')[1]);
// separate out the mime component
var mimeString = dataURI.split(',')[0].split(':')[1].split(';')[0]
// write the bytes of the string to a typed array
var ia = new Uint8Array(byteString.length);
for (var i = 0; i < byteString.length; i++) {
ia[i] = byteString.charCodeAt(i);
}
return new Blob([ia], {type:mimeString});
} else {
return null;
}
}
Am I missing something in the code?
Well, as per this question, you need to be using the buffer property of ia, not just [ia]. Instead of
return new Blob([ia], {type:mimeString});
try
return new Blob([ia.buffer], {type:mimeString});

Categories