I am using Jsreport via API.
From the browser, a ajax call is made to jsreport server. The server answers with POST respond with data and a Header tag Permanent-Link which has the file locaton.
Copy paste it to the browser allow me to view the pdf file.
The problem it that I want to view it automatically in success handler of ajax call, but xhr.getRespondHeader() does not allow any other header than Content-Type. The respond header even have "Access-Control-Allow-Origin: *" already.
How can I get the pdf out for user?
You can use official jsreport browser client - http://jsreport.net/learn/browser-client
If it is loaded in the page, opening a report is as simple as this
jsreport.serverUrl = 'http://localhost:3000';
var request = {
template: {
content: 'foo', engine: 'none', recipe: 'phantom-pdf'
}
};
//display report in the new tab
jsreport.render('_blank', request);
You can also check its source code if you are curious how it is handling AJAX
https://github.com/jsreport/jsreport-browser-client-dist
Related
i am attempting to grab a pdf file for e-signature using pre-signed URLs. i use Amplify Storage to generate the URL. then i provide the URL to the HelloSign function to bring the file into the embedding window. i am able to open the document using window.open but this other method brings the SignatureDoesNotMatchThe request signature we calculated does not match the signature you provided. error.
The request signature we calculated does not match the signature you provided. Check your key and signing method.
key: string = 'bucketname/path/to/file.pdf'
expires: number = 60
const url = await Storage.get(key, {
level: 'public',
cacheControl: 'no-cache',
signatureVersion: 'v4',
ContentType: 'application/pdf',
expires: 60,
customPrefix: {
public: '',
protected: '',
private: '',
},
})
hellosign.open(url, {
clientId,
skipDomainVerification: true,
})
one fix i found on Github was to include the signatureVersion when initializing the S3 class instance using the SDK. i am not using the SDK however, so i tried providing it when configuring Amplify like so:
AWSS3: {
bucket,
region,
signatureVersion: 'v4',
},
needless to say it did not fix the issue. i could not find any references to this in the docs, as the Amplify.configure function takes any in their docs.
i tried clicking the pre-signed URL and was able to download the doc without issue. i inspected the request and saw the correct headers that match the outgoing request originating from hellosign.open. any ideas what i can try?
hellosign.open() is only expected to load embedded URLs. These would be URLs returned from requests to the following endpoints:
/embedded/sign_url/ (sign URL - embedded signing)
/template/create_embedded_draft (edit URL - embedded template creation)
/embedded/edit_url/ (edit URL - embedded template editing)
/unclaimed_draft/create_embedded (claim URL embedded requesting)
/unclaimed_draft/create_embedded_with_template (claim URL embedded requesting)
If you'd like to collect signatures on a document in an iframe on your site, embedded signing will likely be what you're looking for. In that case, you'd want to create your signature request with a request to:
/signature_request/create_embedded
and then use the URL you're creating via Amplify Storage as the value of the file_url[] request parameter.
Once you've created your request, locate the signature ID for your signer in the response object, and use that in a request to /embedded/sign_url/
This will return a sign URL that you can load using hellosign.open().
I'm developping an angular2 application (single page application). My page is never "reloaded", but it's content changes according to user interactions.
I'm having some cache problems especially with images.
Context :
My page contains an editable image list :
<ul>
<li><img src="myImageController/1">Edit</li>
<li><img src="myImageController/2">Edit</li>
<li><img src="myImageController/3">Edit</li>
</ul>
When i want to edit an image (Edit link), my dom content is completly changed to show another angular component with a fileupload component.
The myImageController returns the LastModified header, and cache-control : no-cache and must-revalidate.
After a refresh (hit F5), my page does a request to get all img src, which is correct : if image has been modified, it is downloaded, if not, i just get a 304 which is fine.
Note : my images are stored in database as blob fields.
Problem :
When my page content is dynamically reloaded with my single page app, containing img tags, the browser do not call a GET http request, but immediatly take image from cache. I assume this a browser optimization to avoid getting the same resource on the same page multiple times.
Wrong solutions :
The first solution is to add something like ?time=(new Date()).getTime() to generate unique urls and avoid browser cache. This won't send the If-Modified-Since header in the request, and i will download my image every time completly.
Do a "real" refresh : the first page load in angular apps is quite slow, and i don't to refresh all.
Tests
To simplify the problem, i trying to create a static html page containing 3 images with the exact same link to my controller : /myImageController/1. With the chrome developper tool, i can see that only one get request is called. If i manage to get mulitple server calls in this case, it would probably solve my problem.
Thank you for your help.
5th version of HTML specification describes this behavior. Browser may reuse images regardless of cache related HTTP headers. Check this answer for more information. You probably need to use XMLHttpRequest and blobs. In this case you also need to consider Same-origin policy.
You can use following function to make sure user agent performs every request:
var downloadImage = function ( imgNode, url ) {
var xhr = new XMLHttpRequest();
xhr.open("GET", url, true);
xhr.responseType = "blob";
xhr.onreadystatechange = function () {
if (xhr.readyState == 4) {
if (xhr.status == 200 || xhr.status == 304) {
var blobUrl = URL.createObjectURL(xhr.response);
imgNode.src = blobUrl;
// You can also use imgNode.onload callback to release blob resources.
setTimeout(function () {
URL.revokeObjectURL(blobUrl);
}, 1000);
}
}
};
xhr.send();
};
For more information check New Tricks in XMLHttpRequest2 article by Eric Bidelman, Working with files in JavaScript, Part 4: Object URLs article by Nicholas C. Zakas and URL.createObjectURL() MDN page and Same-origin policy MDN page.
You can use the random ID trick. This changes the URL so that the browser reloads the image. Not that this can be done in the query parameters to force a full cache break or in the hash to allow the browser to re-validate the image from the cache (and avoid re-downloading it if unchanged).
function reloadWithCache(img: HTMLImageElement, url: string) {
img.src = url.replace(/#.*/, "") + "#" + Math.random();
}
function reloadBypassCache(img: HTMLImageElement, url: string) {
let sep = img.indexOf("?") == -1? "?" : "&";
img.src = url + sep + "nocache=" + Math.random()
}
Note that if you are using reloadBypassCache regularly you are better off fixing your cache headers. This function will always hit your origin server leading to higher running costs and making CDNs ineffective.
My app uses OneDrive API feature to let unauthorized users get thumbnails for shared OneDrive files using old API request:
https:// apis.live.net/v5.0/skydrive/get_item_preview?type=normal&url=[shared_link_to_OneDrive_file]
This feature is broken now (any such links return XMLHttpRequest connection error 0x2eff).
And my Windows Store app can not longer provide this feature.
Anyone can try to check it, link to shared OneDrive file:
https://onedrive.live.com/redir?resid=AABF0E8064900F8D!27202&authkey=!AJTeSCuaHMc45eY&v=3&ithint=photo%2cjpg
links to a preview image for shared OneDrive file (according to old OneDrive API
"Displaying a preview of a OneDrive item" - https:// msdn.microsoft.com/en-us/library/jj680723.aspx):
https://apis.live.net/v5.0/skydrive/get_item_preview?type=normal&url=https%3A%2F%2Fonedrive.live.com%2Fredir%3Fresid%3DAABF0E8064900F8D!27202%26authkey%3D!AJTeSCuaHMc45eY%26v%3D3%26ithint%3Dphoto%252cjpg
generates error: SCRIPT7002: XMLHttpRequest: Network error 0x2eff
Сurrent OneDrive API thumbnail feature:
GET /drive/items/{item-id}/thumbnails/{thumb-id}/{size}
is just for authorized users and can not provide access to thumbnails for shared OneDrive files to unauthorized users
How can a Windows Store app let unauthorized users get thumbnails for shared OneDrive files (videos etc.) using the current OneDrive API?
Any ideas?
You need to make a call to the following API:
GET /drive/items/{item-id}/thumbnails/{thumb-id}/{size}/content
This call needs to use authorization and returns a redirect to a cache-safe thumbnail location. You can then use this new url to serve thumbnails to unauthenticated users.
e.g.
Request:
GET https://api.onedrive.com/v1.0/drive/items/D094522DE0B10F6D!152/thumbnails/0/small/content
Authorization: bearer <access token>
Response:
HTTP/1.1 302 Found
Location: https://qg3u2w.bn1302.livefilestore.com/y3m1LKnRaQvGEEhv_GU3mVsewg_-aizIXDaVczGwGFIqtNcVSCihLo7s2mNdUrKicuBnB2sGlSwMQTzQw7v34cHLkchKHL_5YC3IMx1SMcpndtdb9bmQ6y2iG4id0HHgCUlgctvYsDrE24XALwXv2KWRUwCCvDJC4hlkqYgnwGBUSQ
You can now use the link in the Location header to access the thumbnail without signing in. This url will change only if the contents of the file change.
You can read more in the documentation here.
I just figured it out. It is based on the information in this article from Microsoft...
https://learn.microsoft.com/en-ca/onedrive/developer/rest-api/api/driveitem_list_thumbnails?view=odsp-graph-online
... look at the section, "Getting thumbnails while listing DriveItems." It shows you the relevant JSON return structure from a call such as:
GET /me/drive/items/{item-id}/children?$expand=thumbnails
Basically, the JSON return structure gives you string URL's for each of the thumbnail formats. You then create URLSession's to upload these URL's (once you've converted them from String to URL)
Here is an excerpt of code using Swift (Apple):
////////////////////////////////////////////////////////////////////////////////
//
// Download a thumbnail with a URL and label the URLSession with an ID.
//
func downloadThumbnail(url: URL, id: String) {
// Create a URLSession. This is an object that controls the operation or flow
// control with respect to asynchronous operations. It sets the callback delegate
// when the operation is complete.
let urlSession: URLSession = {
//let config = URLSessionConfiguration.default
let config = URLSessionConfiguration.background(withIdentifier: id)
config.isDiscretionary = true
config.sessionSendsLaunchEvents = true
//config.identifier = "file download"
return URLSession(configuration: config, delegate: self as URLSessionDelegate, delegateQueue: OperationQueue.main)
}()
// Create the URLRequest. This is needed so that "Authorization" can be made, as well
// as the actual HTTP command. The url, on initialization, is the command... along
// with the "GET" setting of the httpMethod property.
var request = URLRequest(url: url)
// Set the Authorization header for the request. We use Bearer tokens, so we specify Bearer + the token we got from the result
request.setValue("Bearer \(self.accessToken)", forHTTPHeaderField: "Authorization")
request.httpMethod = "GET"
request.setValue("application/json", forHTTPHeaderField: "Content-Type")
// This initiates the asynchronous data task
let backgroundTask = urlSession.downloadTask(with: request)
//backgroundTask.earliestBeginDate = Date().addingTimeInterval(60 * 60)
backgroundTask.countOfBytesClientExpectsToSend = 60
backgroundTask.countOfBytesClientExpectsToReceive = 15 * 1024
backgroundTask.resume()
}
... of course you need to have the correct "accessToken," (shown above) but you also have to have written the generic callback function for URLSession, which is:
func urlSession(_ session: URLSession, downloadTask: URLSessionDownloadTask,
didFinishDownloadingTo location: URL) {
Swift.print("DEBUG: urlSession callback reached")
// This was the identifier that you setup URLSession with
let id = session.configuration.identifier
// "location" is the temporary URL that the thumbnail was downloaded to
let temp = location
// You can convert this URL into any kind of image object. Just Google it!
}
Cheers, Andreas
I'm trying to upload on Kinvey using REST API method.
I can successfully get the google storage URL link provided after sending a 'POST' request to https://baas.kinvey.com/blob/:myAppId
The problem is when I'm sending a 'PUT' request to the google storage URL, I'm getting this error:
XMLHttpRequest cannot load (my storage.google URL). Response to
preflight request doesn't pass access control check: No
'Access-Control-Allow-Origin' header is present on the requested
resource. Origin (my localhost) is therefore not allowed access.
This appears to be a fairly standard CORS error (which you can read a LOT more about over here: https://developer.mozilla.org/en-US/docs/Web/HTTP/Access_control_CORS ) , which takes place when you are making a cross-origin request. There's a lot of different ways that you can approach this issue, but the easiest would probably be to use one of our SDK's to help you. If you take a look over at http://devcenter.kinvey.com/html5/downloads you will find an SDK that you can include in your projects and guides / documentation for it in the top navigation.
File uploads using the HTML5 library are fairly trivial as well. Here's some sample code that I have whipped up:
HTML portion:
<input type="file" name="_file" id="_file" onchange="fileSelected();" />
<div id="fileinfo">
<div id="filename"></div>
<div id="filetype"></div>
</div>
Javascript portion:
function fileSelected(){
var oFile = document.getElementById('_file').files[0];
var oReader = new FileReader();
oReader.onload = function(e) {
document.getElementById('fileinfo').style.display = 'block';
document.getElementById('filename').innerHTML = 'Name: ' + oFile.name;
document.getElementById('filetype').innerHTML = 'Type: ' + oFile.type;
};
oReader.readAsDataURL(oFile);
fileUpload(oFile);
}
function fileUpload(file) {
var file = document.getElementById('_file').files[0];
var promise = Kinvey.File.upload(file,{
filename: document.getElementById('fileinfo').toString(),
mimetype: document.getElementById('filetype').toString()
})
promise.then(function() {
alert("File Uploaded Successfully");
}, function(error){
alert("File Upload Failure: " + error.description);
});
}
This will be slightly different for each of Kinvey's Javascript libraries, but should follow roughly the same outline. Get file, call Kinvey.File.Upload asynchronously, and let the SDK do it's magic. This should handle all the ugliness of CORS for you.
Thanks,
I am uploading a file using dojo.io.iframe.send ajax call using below code.
Am using dojo 1.7 and WebSphere Portal Server 8.0
dojo.io.iframe.send({
form: "workReqIDFormWBS",
handleAs: "text/html",
url:"<portlet:actionURL/>",
load: function(response, ioArgs) {
console.log(response, ioArgs);
return response;
},error: function(response, ioArgs) {
console.log(response, ioArgs);
return response;
}
});
When am uploding the file for the first time it's working fine,where as from second time onwards nothing is happening. Any solution for this issue.
Action URLs are only valid to be invoked once by default. Portal protects against form submission replay incidents by internally assigning an ID within the action URL produced.
You should also be seeing some logging on those subsequent action url requests: http://www-01.ibm.com/support/docview.wss?uid=swg21613334
I suggest either using resource URL and serveResource() in your portlet or ensuring that your response from the render phase following the action URL processing regenerate the Action URL value and update a variable your posted javascript reads and uses in subsequent send() calls.