base64 from API call to Adobe PDF Embed API - ajax

I'm trying to embed a PDF on a web page. The native PDF viewer in Chrome has a size limit of around 2mb, so I'm trying to use Adobe's API (https://www.adobe.io/apis/documentcloud/dcsdk/pdf-embed.html)
Because of the way that a CMS that I'm using stored files, I have a Base64 string to work with.
Using code from https://gist.github.com/kiritodeveloper/06186343e41e21a94411b3987e84c5de, I was able to pass my base64 string to Adobe's API and embed the PDF about 60% of the time in Chrome, but now it doesn't work in Firefox.
I'm using ajax to get to my CMS's API to retrieve the data, but I think that the adobe listener is running before the data is returned; when it does work, it's just chance. How can I get the order right so that this will work? Can I use an asynchronous call to get this data?
const clientID = "ADOBE API KEY HERE";
var queryPath = "$/PDFBase64"
jQuery( document).ready(function() {
var pdfData = '';
getPDF();
function base64ToArrayBuffer(base64) {
var bin = window.atob(base64);
var len = bin.length;
var uInt8Array = new Uint8Array(len);
for (var i = 0; i < len; i++) {
uInt8Array[i] = bin.charCodeAt(i);
}
return uInt8Array.buffer;
}
document.addEventListener("adobe_dc_view_sdk.ready", function () {
var adobeDCView = new AdobeDC.View({
clientId: clientID,
divId: "adobe-dc-view"
});
adobeDCView.previewFile(
{
// convert the Base64 encoded PDF and convert it to an ArrayBuffer
// and pass it as a Promise
content: { promise: Promise.resolve(base64ToArrayBuffer(pdfData)) },
// The filename name to display in the View SDK UI
// and also used as the filename of the PDF when downloaded
metaData: { fileName: "Download.pdf" }
}, {})
});
function getPDF() {
jQuery.ajax("/api/Query?queryname=" + queryPath ,
{
type : "get",
"async":false,
contentType: "application/json",
headers: {"RequestVerificationToken":
document.getElementById("__RequestVerificationToken").value},
success: function(data){
iqa = data.Items.$values;
if(iqa.length>0){
for (var i = 0; i < iqa.length; i++) {
filt = iqa[i].Properties.$values;
pdfData = filt.filter(x => x.Name == "PDF")[0].Value;
};
}
return pdfData;
}, error : function(xhr, textStatus, errorThrown ) {
if (textStatus == 'timeout') {
this.tryCount++;
if (this.tryCount <= this.retryLimit) {
//try again
$.ajax(this);
return;
}
return;
}
if (xhr.status == 500) {
console.log(errorThrown);
} else {
//handle error
}
}
});
};
});

Related

How to upload outlook email attachments on my cloud server using Outlook Js Add-in

I am developing outlook javascript add-in using vs2017. I have created a sample application to find attachments from outlook mail item. Here, While getting attachments from Exchange Server, It returns 200 OK.
I have my own cloud application looks like google drive. I want to upload outlook mail attachments on my cloud server using POST API call. API call was running successfully. But I am not able to get file content from the exchange server.
I have added some sample code over here.
Creating a service request
/// <reference path="../App.js" />
var xhr;
var serviceRequest;
(function () {
"use strict";
// The Office initialize function must be run each time a new page is loaded
Office.initialize = function (reason) {
$(document).ready(function () {
app.initialize();
initApp();
});
};
function initApp() {
$("#footer").hide();
if (Office.context.mailbox.item.attachments == undefined) {
var testButton = document.getElementById("testButton");
testButton.onclick = "";
showToast("Not supported", "Attachments are not supported by your Exchange server.");
} else if (Office.context.mailbox.item.attachments.length == 0) {
var testButton = document.getElementById("testButton");
testButton.onclick = "";
showToast("No attachments", "There are no attachments on this item.");
} else {
// Initalize a context object for the app.
// Set the fields that are used on the request
// object to default values.
serviceRequest = new Object();
serviceRequest.attachmentToken = "";
serviceRequest.ewsUrl = Office.context.mailbox.ewsUrl;
serviceRequest.attachments = new Array();
}
};
})();
function testAttachments() {
Office.context.mailbox.getCallbackTokenAsync(attachmentTokenCallback);
};
function attachmentTokenCallback(asyncResult, userContext) {
if (asyncResult.status == "succeeded") {
serviceRequest.attachmentToken = asyncResult.value;
makeServiceRequest();
}
else {
showToast("Error", "Could not get callback token: " + asyncResult.error.message);
}
}
function makeServiceRequest() {
var attachment;
xhr = new XMLHttpRequest();
// Update the URL to point to your service location.
xhr.open("POST", "https://localhost:8080/GetOutlookAttachments/AttachmentExampleService/api/AttachmentService", true);
xhr.setRequestHeader("Content-Type", "application/json; charset=utf-8");
xhr.onreadystatechange = requestReadyStateChange;
// Translate the attachment details into a form easily understood by WCF.
for (i = 0; i < Office.context.mailbox.item.attachments.length; i++) {
attachment = Office.context.mailbox.item.attachments[i];
attachment = attachment._data$p$0 || attachment.$0_0;
if (attachment !== undefined) {
serviceRequest.attachments[i] = JSON.parse(JSON.stringify(attachment));
}
}
// Send the request. The response is handled in the
// requestReadyStateChange function.
xhr.send(JSON.stringify(serviceRequest));
};
// Handles the response from the JSON web service.
function requestReadyStateChange() {
if (xhr.readyState == 4) {
if (xhr.status == 200) {
var response = JSON.parse(xhr.responseText);
if (!response.isError) {
// The response indicates that the server recognized
// the client identity and processed the request.
// Show the response.
var names = "<h2>Attachments processed: " + response.attachmentsProcessed + "</h2>";
document.getElementById("names").innerHTML = names;
} else {
showToast("Runtime error", response.message);
}
} else {
if (xhr.status == 404) {
showToast("Service not found", "The app server could not be found.");
} else {
showToast("Unknown error", "There was an unexpected error: " + xhr.status + " -- " + xhr.statusText);
}
}
}
};
// Shows the service response.
function showResponse(response) {
showToast("Service Response", "Attachments processed: " + response.attachmentsProcessed);
}
// Displays a message for 10 seconds.
function showToast(title, message) {
var notice = document.getElementById("notice");
var output = document.getElementById('output');
notice.innerHTML = title;
output.innerHTML = message;
$("#footer").show("slow");
window.setTimeout(function () { $("#footer").hide("slow") }, 10000);
};
Please help me to get attachments from outlook mail and upload on my cloud server.
attachment._data$p$0 gives to attachment metadata. Get id from there and use getAttachmentContentAsync API to get the attachment content Documentation

React/Redux download file

I need to download a file from the server when a button is clicked.
I created a MaterialUI button and on its onclick callback i call an action of the container component connected.
The action is asynchronous and does an ajax POST:
export const onXlsxClick = () => dispatch => {
const urlParams = {
filters: {
aggregation: 'macro_area',
chart_resolution: '1_hour',
chart_from: '1478080363',
chart_to: '1477993963'
},
labels: ['PROVA1', 'PROVA2'],
series: [
{
label: null,
timestamp: 1478080363,
values: [123, 345]
},
{
label: null,
timestamp: 1477993963,
values: [153, 3435]
}
]
};
return $.ajax({
url:'/rest/export/chart/xlsx',
type: 'POST',
dataType: 'application/json',
contentType: 'application/json',
data: JSON.stringify(urlParams)
})
.done(data => {
console.log('success');
})
.fail(error => {
console.log(error);
});
};
The server receive the request and handle it correctly through this REST service:
#POST
#Path("xlsx")
#Produces("application/vnd.ms-excel")
public Response getXlsx(ChartExportRequest request) {
ResponseBuilder responseBuilder;
ChartExportRequestDTO reqDto = null;
try {
reqDto = parseDTO(request);
checkRequestDTO(reqDto);
ExportDTO dto = getXlsxProvider().create(reqDto);
responseBuilder = Response.ok(dto.getFile())
.header("Content-disposition", "attachment;filename=" + dto.getFileName());
}
catch(Exception e) {
logger.error("Error providing export xlsx for tab RIGEDI with request [" + (reqDto != null ? reqDto.toString() : null) + "]", e);
responseBuilder = Response.serverError().entity(e.getMessage());
}
return responseBuilder.build();
}
The problem is that the response arrives correctly to the client but then nothing happens: I am expecting that the browser shows the download dialog (example: in chrome I expect the bottom bar of downloads to appear with my file).
What am I doing wrong?
AS per Nate's answer here, the response of Ajax request is not recognised by a browser as a file. It will behave in the same way for all Ajax responses.
You need to trigger the download popup manually.
In my implementation, I used filesaverjs to trigger the download popup, once I have received the API response in reducer.
Since FileSaver uses blob for saving the file, I am sending the response from server as a blob, converting it into string array buffer and then using it to save my file. This approach was described in
Please find the sample code below for the reducer :
(using reducer for state modification, as per Redux)
reducer.js
let fileSaver = require("file-saver");
export default function projectReducer(state = {}, action)
{
let project;
switch (action.type) {
case GET_PROJECT_SUCCESS :
project = Object.assign(action.response.data);
return project;
case EXPORT_AND_DOWNLOAD_DATA_SUCCESS :
let data = s2ab(action.response.data);
fileSaver.saveAs(new Blob([data], {type: "application/octet-stream"}), "test.xlsx");
return state;
}
return state;
}
function s2ab(s) {
var buf = new ArrayBuffer(s.length);
var view = new Uint8Array(buf);
for (var i = 0; i != s.length; ++i) {
view[i] = s.charCodeAt(i) & 0xFF;
}
return buf;
}

How to upload a Cordova picture to a Laravel 4 project by using an API

I'm making a hybrid app with AngularJS and Cordova, using a Laravel 4 API & Backoffice.
I can make a picture with the application, but it does not upload. I don't really know how to upload the picture, and i don't really know how i can troubleshoot all of it.
I upload the image to the API-route i wrote, using the same upload-method as i use to do with the backoffice. This is what i have in the AngularJS-Controller, which uses Cordova to do the stuff.
var pictureSource; // picture source
var destinationType; // sets the format of returned value
pictureSource = navigator.camera.PictureSourceType;
destinationType = navigator.camera.DestinationType;
function clearCache() {
navigator.camera.cleanup();
}
var retries = 0;
function onPhotoDataSuccess(fileURI) {
var win = function (r) {
clearCache();
retries = 0;
alert('Done!');
}
var fail = function (error) {
if (retries == 0) {
retries ++
setTimeout(function() {
onPhotoDataSuccess(fileURI)
alert("kgoa ne keer opnief beginne");
}, 1000)
} else {
retries = 0;
clearCache();
alert('Ups. Something wrong happens!');
}
}
var options = new FileUploadOptions();
options.fileKey = "image";
options.fileName = fileURI.substr(fileURI.lastIndexOf('/') + 1);
options.mimeType = "image/jpeg";
options.params = {};
params.value1 = "test";
params.value2 = "param";
// if we need to send parameters to the server request
var ft = new FileTransfer();
ft.upload(fileURI, encodeURI("http://10.0.1.13/ClimbrBackoffice/public/api/routes/new/create"), win, fail, options);
}
// Called when a photo is successfully retrieved
//
function onPhotoURISuccess(imageURI) {
// Uncomment to view the image file URI
// console.log(imageURI);
// Get image handle
//
var largeImage = document.getElementById('largeImage');
// Unhide image elements
//
largeImage.style.display = 'block';
// Show the captured photo
// The inline CSS rules are used to resize the image
//
largeImage.src = imageURI;
}
// A button will call this function
//
$scope.capturePhoto = function(){
// Take picture using device camera and retrieve image as base64-encoded string
navigator.camera.getPicture(onPhotoDataSuccess, onFail, {
quality : 100,
destinationType : Camera.DestinationType.FILE_URI,
sourceType : Camera.PictureSourceType.CAMERA,
allowEdit : true,
encodingType: Camera.EncodingType.JPEG,
targetWidth: 250,
targetHeight: 400,
saveToPhotoAlbum: true,
correctOrientation: true
});
}
// A button will call this function
//
$scope.getPhoto = function(source) {
// Retrieve image file location from specified source
navigator.camera.getPicture(onPhotoURISuccess, onFail, { quality: 100,
destinationType: destinationType.FILE_URI,
sourceType: source });
}
I searched the web for good tutorials or explanations, but they drove me crazy.
Can someone please help me out?
Thanks!
Thomas
Your Angular controller should have the following function
$scope.upload = function() {
var options = {
fileKey: "file",
fileName: "image.png",
chunkedMode: false,
mimeType: "image/png"
};
$cordovaFileTransfer.upload("http://yourdomain.com/image_handler", "/android_asset/www/img/ionic.png", options).then(function(result) {
console.log("SUCCESS: " + JSON.stringify(result.response));
$scope.showAlert('Done', 'File Uploaded');
}, function(err) {
console.log("ERROR: " + JSON.stringify(err));
$scope.showAlert('Error', err);
}, function (progress) {
// constant progress updates
});}
And on your server, Laravel function could simply handle the image as:
public function getImageFromDevice(){
$destinationPath = 'uploads/';
$newImageName='MyImage.jpg';
Input::file('file')->move($destinationPath,$newImageName);
}
Do not forget to inject $cordovaFileTransfer in your controller.
That's it, this is a simple example you can extend it.
Credits to: Phonegap + Laravel 4 How to upload file

Winjs get request failing to return data

I encountered a strange problem. In my app I have the following code
WinJS.xhr({
url: 'http://bdzservice.apphb.com/api/Route?fromStation=София&toStation=Варна&date=30/08/2013&startTime=00:00&endTime=24:00'
}).then(function (success)
{
console.log(success);
},
function (error)
{
console.log(error);
}
);
The problem is I get an empty response text (with status 200). The Url I provided returns data through the browser and other rest clients, but in the app I get no data. Where might be the problem?
You need to encode query string parameters via encodeURIComponent (browser does this for you automatically when pasting url).
Following code will do the trick:
function serialize (obj) {
var str = [];
for (var p in obj) {
if (obj.hasOwnProperty(p)) {
str.push(encodeURIComponent(p) + "=" + encodeURIComponent(obj[p]));
}
}
return str.join("&");
};
var request = {
fromStation: 'София',
toStation: 'Варна',
date: '30/08/2013',
startTime: '00:00',
endTime: '24:00'
};
WinJS.xhr({
url: 'http://bdzservice.apphb.com/api/Route?' + serialize(request)
}).then(function(success) {
console.log(success);
},
function(error) {
console.log(error);
}
);

How to check file size when uploading photo using ajaxupload3.5

I'm using ajaxuploader to upload and change user photo using the solution from here:http://www.c-sharpcorner.com/blogs/4183/upload-image-by-ajax-uploader-with-jquery.aspx
The code below works fine but I don't know how to check file size in client side or (if it's not possible in client side) how to get the response from server side. In mycode below the response id the HTML of the whole page.
<script src="../js/jquery-ui-1.8.18.custom.min.js" type="text/javascript"></script>
<script src="../js/ajaxupload.3.5.js" type="text/javascript"></script>
<script type="text/javascript" language="javascript">
$(function () {
$('#<%=status_message.ClientID%>').html('');
var btnUpload = $('#upload_button');
var status = $('#status_message');
new AjaxUpload(btnUpload, {
action: 'test_photoUpload.aspx/uploadPhoto',
name: 'uploadfile',
onSubmit: function (file, ext) {
$('#<%=status_message.ClientID%>').html('');
$('#imgLoad').show();
if (!(ext && /^(jpg|png|jpeg|gif)$/.test(ext))) {
// extension is not allowed
$('#imgLoad').hide();
$('#<%=status_message.ClientID%>').html('Only JPG, PNG or GIF files are allowed');
alert("submitted");
return false;
}
// if (file.ContentLength > 1024 * 1024 * 2) {
// $('#<%=status_message.ClientID%>').html('Please upload photo less than 2MB size.');
// alert("submitted");
// return false;
// }
},
onComplete: function (file, response) {
alert(response);
status.text('');
$('#<%=hdPhoto.ClientID%>').val(file);
$('#<%=imgPhoto.ClientID%>').attr('src', 'UserImages/' + file);
// $('#<%=status_message.ClientID%>').html(file.toString());
$('#imgLoad').hide();
return false;
}
});
});
</script>
private string uploadPhoto()
{
string chkResult = "false";
//upload photo code
string i = Request.Files.ToString();
string ext = Path.GetExtension(Request.Files[0].FileName.ToString().ToLower());
if (ext == ".png" || ext == ".jpg" || ext == ".gif" || ext == ".jpeg")
{
if (Request.Files[0].ContentLength <= 1024 * 1024 * 2)
{
if (File.Exists(Server.MapPath("UserImages") + "\\" + System.IO.Path.GetFileName(Request.Files[0].FileName)))
File.Delete(Server.MapPath("UserImages") + "\\" + System.IO.Path.GetFileName(Request.Files[0].FileName));
Request.Files[0].SaveAs(Server.MapPath("UserImages") + "\\" + System.IO.Path.GetFileName(Request.Files[0].FileName));
chkResult = "true";
}
else
{
status_message.InnerHtml = "Please upload less than 2MB size.";
chkResult = "false";
}
}
else
{
status_message.InnerHtml = "Please upload only png, jpg, jpeg or gif file.";
chkResult = "false";
}
// Response.Close();
// Response.End();
return chkResult;
}
I've tried to serialize the response to Json and return but the response is the same HTML converted to string. I tried like this:
$(function () {
$('#<%=status_message.ClientID%>').html('');
var btnUpload = $('#upload_button');
var status = $('#status_message');
new AjaxUpload(btnUpload, {
action: 'test_photoUpload.aspx/uploadPhoto',
name: 'uploadfile',
dataType: 'json',
contentType: "application/json; charset=utf-8",
onSubmit: function (file, ext) {
$('#<%=status_message.ClientID%>').html('');
$('#imgLoad').show();
if (!(ext && /^(jpg|png|jpeg|gif)$/.test(ext))) {
// extension is not allowed
$('#imgLoad').hide();
$('#<%=status_message.ClientID%>').html('Only JPG, PNG or GIF files are allowed');
alert("submitted");
return false;
}
// if (file.ContentLength > 1024 * 1024 * 2) {
// $('#<%=status_message.ClientID%>').html('Please upload photo less than 2MB size.');
// alert("submitted");
// return false;
// }
},
onComplete: function (file, response) {
var obj = JSON.stringify(response);
//var obj = jQuery.parseJSON(response);
alert(obj);
alert(response);
status.text('');
$('#<%=hdPhoto.ClientID%>').val(file);
$('#<%=imgPhoto.ClientID%>').attr('src', 'UserImages/' + file);
// $('#<%=status_message.ClientID%>').html(file.toString());
$('#imgLoad').hide();
return false;
}
});
});
using System.Web.Script.Serialization;
using System.Web.Script.Services;
[ScriptMethod(ResponseFormat = ResponseFormat.Json)]
private string uploadPhoto()
{
string chkResult = "false";
//upload photo code
string i = Request.Files.ToString();
string ext = Path.GetExtension(Request.Files[0].FileName.ToString().ToLower());
if (ext == ".png" || ext == ".jpg" || ext == ".gif" || ext == ".jpeg")
{
if (Request.Files[0].ContentLength <= 1024 * 1024 * 2)
{
if (File.Exists(Server.MapPath("UserImages") + "\\" + System.IO.Path.GetFileName(Request.Files[0].FileName)))
File.Delete(Server.MapPath("UserImages") + "\\" + System.IO.Path.GetFileName(Request.Files[0].FileName));
Request.Files[0].SaveAs(Server.MapPath("UserImages") + "\\" + System.IO.Path.GetFileName(Request.Files[0].FileName));
chkResult = "true";
}
else
{
status_message.InnerHtml = "Please upload less than 2MB size.";
chkResult = "false";
}
}
else
{
status_message.InnerHtml = "Please upload only png, jpg, jpeg or gif file.";
chkResult = "false";
}
// Response.Close();
// Response.End();
//return chkResult;
var keyValues = new Dictionary<string, string>
{
{ "success", "success" },
{ "error", "error" }
};
JavaScriptSerializer js = new JavaScriptSerializer();
string json = js.Serialize(keyValues);
//Response.Write(json);
return json;
}
I've also tried to use webmethod and static uploadPhoto method but the response is the same.
Any help is appreciated.
It works for me. I instantiate the AjaxUpload in a variable, then I use the variable itself to call an outside script, which submits the file. After that, I get the input information from inside the AjaxUpload script.
var btnUpload = $("#upload");
up_archive = new AjaxUpload(btnUpload, {
action: 'FileUpload.php',
name: 'upload_archive',
responseType: 'json', //get the server response as JSON
autoSubmit: false, //I'll set some informations about the archive outside this script
onChange: function(file, ext){
//check the file size
if (up_archive._input.files[0].size > 2097152){ //2MB
//show alert message
alert('Selected file is bigger than 2MB.');
return;
}
},
onSubmit: function(file, ext){
desc_archive = $("#desc_archive").val();
this.setData( {desc_archive: desc_archive} ); //set a description for the archive to be uploaded
},
onComplete: function(file, response){
$("#desc_archive").val('');
$("#div_response").html(response.message);
}
});

Resources