I am trying to create a blob in Javascript to serve up a file. However, the link created by window.URL.createObjectURL(blob) becomes invalid over time. I wish to be able to generate a link that will be valid for as long as the page is open. Looking online, I saw that the autoRevoke option is set to true, so this led me to believe that the url is being revoked when not being used actively. I tried setting it to false, but I get a TypeError.
Here is the code:
var res = xhr.response;
var blob = new Blob([res]);
var url = window.URL.createObjectURL(blob, {autoRevoke : false});
Here is the error:
Uncaught TypeError: Type error background.js:52
How can I prevent the blob's url from becoming invalid?
If you save the blob to the file system using the API discussed here:
http://www.html5rocks.com/en/tutorials/file/filesystem/
You can create a file system URL that will persist. This solution does have the downside of a prompt to the user to approve saving files.
Can you talk more about the feature as the user would see it? What are you linking to?
In response to your comment:
I recommend keeping the input element in the DOM for as long as you want to hold a reference to the file's content. If you're linking to the content, you could create create a link that invokes a function with the input element's unique id. This function would generate a blob URL on demand and forward the browser to that URL. If you're using the URL as an img src or something similar, then perhaps your app has a user interaction that still allows for you to create the blob URL on demand.
Related
Dear SAPUI5 developers,
How can I download a blob data as file in SAPUI5?
I have a blob object:
"data:image/jpeg;base64,MjU1MjE2MjU1MjI0MDE2NzQ3MDc....."
I can not use the normal method that we usually use in JavaScript.
I mean window.URL.createObjectURL(blob); does not make a correct url for the blob data.
Can you tell me how can I do that?
Thanks in advance.
I had the same problem. Mostly you used sap.m.Link for creating the download link. I know if you create a anchor (a tag in HTML) and want to inject it in the body element you will receive the following warning:
ESLint(sap-no-dom-insertion): Direct DOM insertion is forbidden!
But ignore the warning and create a a tag and inject it in the body.
There is a good solution here:
JavaScript blob filename without link
You can create download link with object onfly and fire click event or user can click. Example: Create a file in memory for user to download, not through server
I have a filebrowser on my server that uses Azure storage to store the files. The website has a feature where when you click on a file, it'll bring up a details window. I use ViewerJS to display a pdf preview of the file (if applicable), and it all works pretty well. The only problem is that when downloading the preview file, you have to reload the preview iframe manually to get it to display. The relevant php function is:
http://pastebin.com/sAyhsbfi
When this function is completed (I'm using ajax), the $.done function calls
response = JSON && JSON.parse(response) || jQuery.parseJSON(response);
$scope.pdfthingy=response; document.getElementById("viewerjs_preview").contentDocument.location.reload(true);
where response on the first line is set to the full pathname to the pdf preview file, and viewerjs_preview is the id of the relevant iframe.
For some reason, this isn't working, and the iframe isn't reloading itself. How do I make it do that when the blob has finished downloading, and pdfthingy is set?
Is the iframe’s domain the same as your host website’s domain? If not, we cannot access its contentDocument (or contentWindow) in host website’s JavaScript code.
To refresh the iframe, per my understanding you can set its src:
document.getElementById('viewerjs_preview').src = document.getElementById('viewerjs_preview').src;
Please note if the src contains a hash tag, we may need additional work. I’d like to suggest you to check What's the best way to reload / refresh an iframe using JavaScript? for more information.
Base on my experience, It is possible that we changed the IFrame URL, but the IFrame showed the preview contents. In this scenario, I suggest you can create the IFarme dynamic. For example, When you got the Blob URI form Azure storage, You could try to remove the Iframe and create a new. For instance, if Your preview content is shown in the iframe as :
<iframe id="viewerjs_preview" src = "/ViewerJS/#../azure blob storage url /pre-blobname .pdf " width='400' height='300' allowfullscreen webkitallowfullscreen></iframe>
You can try to use this code:
function recreateIFM() {
document.getElementById("viewerjs_preview").parentNode.removeChild(document.getElementById("viewerjs_preview"));
var ifm = document.createElement("iframe");
ifm.id = "viewerjs_preview";
ifm.width = "600px";
ifm.height = "400px";
ifm.src = "/ViewerJS/#../azure blob storage url /new-blobname .pdf";
document.body.appendChild(ifm);
}
Also, you can try MingXu's reference about how to refresh/reload the Iframe.
Regards,
Bill_Sww
I find the answer, the major reason is that we shouldn't use controllers to manipulate DOM.
sentence like document.getElementById("viewerjs_preview").contentDocument.location.reload(true) will not work anymore in angular scope, so you have to a directive to do it. I think the same question with you is and which's answer with most votes dose work well.
I think maybe my question was unclear, and for that I apologize. I'll try to go back and edit it tomorrow.
The solution for me was to, rather than set the src attribute of the iframe using angularjs, directly set it with
document.getElementById("iframe-id").src=/path_where_I_put_the_files/filename
(for reference I use "pdfthingy" to store the filename returned by the ajax call that downloads a blob).
This prevented the iframe from loading a null source before the filename was set.
This is perhaps part of why walkformusle has said that DOM should not be controlled in this manner.
I'm using the Window.URL.createObjectURL function to generate a blob url for a local video file, which I then use to set the source of a <video> element. This loads the video when the URL is first constructed, and everything works well. But when the web page is reloaded, the generated URL is no longer valid -- the browser automatically revokes the generated URL.
My question: Is there a way to determine if this Blob URL has actually been revoked? In other words, how do I determine if I can still use this Blob url using javascript, jquery, or whatever options are out there?
I came up with a simple solution, which works... albeit, probably isn't ideal.
Basically, I take the url, set the <video> src to that url, and then attach a jquery error event handler to it. If the error event is called (which it is, if the blob url has been revoked) I then prompt the user to reselect their video file.
I'm making an application in HTML5 where you choose a video file, and then the application plays it with the HTML5 video tag and the window.URL.createObjectURL(). The problem is that I want to save the data about this video in localStorage and play it again when the user uses my application, but as Mozilla MDN states about the results of this method:
Browsers will release these automatically when the document is unloaded
So is it possible to do what I'm trying to do? Or do the same thing without the window.URL.createObjectURL() but with something else?
I haven't used createObjectURL(), but if I understand correctly, it's essentially a temporary reference to a file or an in-memory object. If you want to save the actual video, it won't be useful, because the video itself will no longer be referenced by this pointer the next time the user visits the application.
I think you might be able to do this with a data: URL instead, as that URL actually includes the full data from the file. This example demonstrates using a FileReader to generate a data URL. I think you should be able to do this:
var reader = new FileReader();
reader.onload = function(e) {
var myDataUrl = e.target.result;
// do something with the URL in the DOM,
// then save it to local storage
};
reader.readAsDataURL(file);
Update: If you want to go up to 1GB, as you note in your comment, you'd probably be better served by the FileSystem API. This would require you to get the local file, save a copy of the file to persistent filesystem storage, and then use createObjectURL() to get a URL for the file copy. You still have a problem with disk space - you just added 1GB of duplicative file content to the user's filesystem - but I don't think it's possible to keep a persistent reference to a file outside of the browser sandbox otherwise.
When a user is uploading an image, is there a way I can load the image client side and show it to them first, before uploading it to the server? Preferably using javascript/jquery only, but using flash would be acceptable too.
It is possible with the new FileReader interface defined in HTML5 and works on Firefox currently.
A file input has an associated files property which tracks the list of files currently selected for that input. To display a file from this list, create a new FileReader object, initialize its onload event handler, and read the file as a data URL.
// get the first file, foo is a file input field
var file = document.getElementById('foo').files[0];
// setup the reader and the load complete callback
var reader = new FileReader();
reader.onload = function(e) {
var image = new Image();
// string representing the image
image.src = e.target.result;
document.body.appendChild(image);
};
// read the file as a data url
reader.readAsDataURL(file);
Once the file is loaded, you will have access to its contents in a data url scheme, for instance:
data:image/jpeg;base64,...aqHI7sNyPGFjdtQvFr/2Q==
Create a new Image and set its src attribute to this data string.
See a working example here. Firefox only.
You can't really do this cross-browser in JavaScript alone due security restrictions that are in place, there are a few flash versions available though, here's one example (the free version does what you're after).
There are probably more free flash versions out there as well.
Since HTML 5 those things are possible, thanks to the File Object, File Reader and the ´files´ property of the input element.
See here for more information: http://demos.hacks.mozilla.org/openweb/ & http://hacks.mozilla.org/2009/12/file-drag-and-drop-in-firefox-3-6/.
Example (only for demonstration, requires FF 3.5+):
See here: http://gist.github.com/536024
In case you wonder, File.url is brand new, with it you dont anymore need to read the whole file into the memory, and assign the whole DataUrl (data:image/src,base64;DF15EDFE86..) to the src property.
Well, the <img> tag needs a path to the image. That path can be to something on the web, or to a local file. So far, so good. The trick is, how do you tell your javascript the path on the local system, so it can set the IMG SRC attribute.
The path of the file <input> tag is unavailable to javascript (as a security precaution --- you don't want a want page upload files from you system behind your back).
On the other hand, if you can get your users to enter a correct file path name into a text <input> field, then it should be possible.