We are currently working on giving download option to the users to download MP3 files.
We are developing an application that fully execute in local system that no server is required.
But downloading mp3 files option is not working in most of the browsers. Its get opened in inbuilt media players in most browsers.
We have checked the solutions for this as we get answers like setting 'content-disposition' using header in server side or using PHP or ASP scripts to make it downloadable.
I have also checked jquery filedownload.js plugin. that also had a section like setting content-disposition and set-cookie.
So I want to know is it possible to create a file download link (for MP3)* compatible for all browsers using only client side scripts like Javascript or jQuery.
Important note:
Actually the process is not downloading file from a server but from client system itself.
That is the MP3 file should copy from from one location(Directory) to another location with in the client system.
This solution requires browser support of XHR2 (http://dvcs.w3.org/hg/xhr/raw-file/tip/Overview.html)
It will download the MP3 into a blob and then will create a URL you can access the blob. During this process you can override the Mimetype to whatever you need.
window.URL = window.URL || window.webkitURL;
var xhr = new XMLHttpRequest();
xhr.open('GET', 'http://robtowns.com/music/blind_willie.mp3', true);
xhr.responseType = 'blob';
xhr.overrideMimeType('application/octet-stream');
xhr.onload = function(e) {
if (this.status == 200) {
var blob = this.response;
$('#link').html('Download');
}
};
xhr.send();
The JSfiddle example requires you to have turned off web-security in your browser to allow a cross domain request.
http://jsfiddle.net/D2DzR/3/
Related
I'm writing an application in phonegap/cordova. In the application, users have a profile and they can select facebook images to include with their profile.
When they select the images for their profile, I want to upload those specific images to my own server.
I did some research and was able to write some code that download the images but I didn't test it on mobile until after I wrote the code.
I used an XML HTTP Request to download the image as a blob. However, upon testing in mobile, I got errors that the blob.size parameter was not set.
I checked in the browser and indeed the blob.size parameter exists. In mobile, the blob.size parameter is undefined. This led me to believe that the webkit that is on my phone does not support blobs and therefore cannot download the images as blobs.
I have 2 questions really:
1) Is my assessment correct that the blob is not being downloaded because the webkit does not support blob?
2) If 1 is true what is the proper way to download an image in cordova and then upload it to my own server? Alternatively, is there any way I can just tweak my code so that it works on mobile? Also I should note that since the files are already downloaded to my phone, is there a way to simply access them in the local storage instead of downloading them again and then upload that file to my server?
My current code to download as a blob is below:
function xhrPromise(url){
var xhr = new XMLHttpRequest();
xhr.open('GET', url, true);
xhr.responseType = 'blob';
xhr.onload = function(e) {
if (this.status == 200) {
var myBlob = this.response;
return myBlob;
}
};
xhr.send();
}
Based on further research I'm wondering if the solution is to use the cordova file-transfer plugin?
Any suggestions would be greatly appreciated.
1) Webkit supports blob through HTML File API. Read: Exploring the FileSystem APIs
2) I will try to point you into the right direction. What I would do, if I wanted to download an image then re-upload it to another server.
Use Cordova's FileTransfer Plugin to download the picture and write it to a temp location in the SD Card (Android) or the App's Document folder (iOS).
If the image is under 2MB, use a simple HTML tag to link to the downloaded picture, using CDVFILE protocol, <img src="cdvfile://localhost/persistent/temp/image.jpg" /> (for Android) then use AJAX to post it to your server, by encoding the image into base64. Read: How to convert image into base64 string using javascript.
If the image is over 2MB, use Cordova's FileTransfer Plugin to upload.
When using Cordova's FileTransfer Plugin, you will come across HTML File API, I strongly suggest you keep this link as a reference. Read: Exploring the FileSystem APIs
The reason why I would prefer using base64 encoding is because 1) I don't like to rely on Cordova plugins, they used to be super buggy. 2) You can save base64 strings into MySQL (but anything over 2MB will impact your server and the device encoding it).
I'm having a hard time finding easy documentation for JSZip that doesn't involve Base64 or NodeJS. Basically, I have a directory, in which is test.html and a folder called "images". Inside that folder is a bunch of images. I would like to make a zip file out of that folder.
Can anyone help me with some very simple "hello world" type code for this? The documentation on http://stuk.github.io/jszip/ includes things like adding an image from Base64 data or adding a text file that you create in JavaScript. I want to create a .zip file from existing files.
Perhaps the only support for adding images to .zip files with JSZip involves adding them via Base64 data? I don't see that anywhere in the documentation, nor an image-url-to-base64 function, though I did find one elsewhere on StackOverflow.
Any advice?
In a browser you can use an ajax request and use the responseType attribute to get an arraybuffer (if you need IE 9 support, you can use jszip-utils for example) :
var xhr = new XMLHttpRequest();
xhr.open('GET', "images/img1.png", true);
xhr.responseType = "arraybuffer";
xhr.onreadystatechange = function(evt) {
if (xhr.readyState === 4) {
if (xhr.status === 200) {
var zip = new JSZip();
zip.file("images/img1.png", xhr.response);
}
}
};
xhr.send();
This example is limited because it handles only one file and manually creates the xhr object (I didn't use any library because you didn't mention any) but should show you how to do it.
You can find a more complete example in the JSZip documentation : it uses jQuery promises and jszip-utils to download a list of files and trigger a download after that.
If you use a library to handle the ajax request, be sure to check if you can ask for an arraybuffer. The default is to treat the response as text and that will corrupt your images. jQuery for example should support it soon.
I try to write an extension caching some large media files used on my website so you can locally cache those files when the extension is installed:
I pass the URLs via chrome.runtime.sendMessage to the extension (works)
fetch the media file via XMLHttpRequest in the background page (works)
store the file using FileSystem API (works)
get a File object and convert it to a URL using URL.createObjectURL (works)
return the URL to the webpage (error)
Unfortunately the URL can not be used on the webpage. I get the following error:
Not allowed to load local resource: blob:chrome-extension%3A//hlcoamoijhlmhjjxxxbl/e66a4ebc-1787-47e9-aaaa-f4236b710bda
What is the best way to pass a large file object from an extension to the webpage?
You're almost there.
After creating the blob:-URL on the background page and passing it to the content script, don't forward it to the web page. Instead, retrieve the blob using XMLHttpRequest, create a new blob:-URL, then send it to the web page.
// assuming that you've got a valid blob:chrome-extension-URL...
var blobchromeextensionurlhere = 'blob:chrome-extension....';
var x = new XMLHttpRequest();
x.open('GET', blobchromeextensionurlhere);
x.responseType = 'blob';
x.onload = function() {
var url = URL.createObjectURL(x.response);
// Example: blob:http%3A//example.com/17e9d36c-f5cd-48e6-b6b9-589890de1d23
// Now pass url to the page, e.g. using postMessage
};
x.send();
If your current setup does not use content scripts, but e.g. the webRequest API to redirect request to the cached result, then another option is to use data-URIs (a File or Blob can be converted to a data-URI using <FileReader>.readAsDataURL. Data-URIs cannot be read using XMLHttpRequest, but this will be possible in future versions of Chrome (http://crbug.com/308768).
Two possibilities I can think of.
1) Employ externally_connectable.
This method is described in the docs here.
The essence of it: you can declare that such and such webpage can pass messages to your extension, and then chrome.runtime.connect and chrome.runtime.sendMessage will be exposed to the webpage.
You can then probably make the webpage open a port to your extension and use it for data. Note that only the webpage can initiate the connection.
2) Use window.PostMessage.
The method is mentioned in the docs (note the obsolete mention of window.webkitPostMessage) and described in more detail here.
You can, as far as I can tell from documentation of the method (from various places), pass any object with it, including blobs.
Now first of all, I'm making a UserScript, meaning that I don't own the servers from which I download files or the servers to which I upload files.
So I need to download a file from a server (needs to be any type, not just text files), and then somehow submit that file to a file upload form on another website. Is that possible? At first I was wondering if I'd be able to submit the file directly from one server to the other, but I don't think that's possible.
So is there any way I can do this? I can use jQuery as well.
As long as you won't be blocked by XSS prevention, load the data using an XMLHttpRequest then post it to the other site.
Here is a very basic functional example:
var xhr = new XMLHttpRequest();
xhr.open("get", "http://www.example.com/file", true);
xhr.onload = function () {
xhr.close();
var xhr2 = new XMLHttpRequest();
xhr2.open("post", "http://www.example2.com/form", true);
xhr2.send(xhr.response);
}
xhr.send();
I would advise that you add some code to catch errors
For more details on XMLHttpRequests, the documentation can be found on MDN here, with instructions on how to use it on MDN here
The script adds a download link for videos (on a specific site). How do I change the filename to something else while downloading?
Example URL:
"http://website.com/video.mp4"
Example of what I want the filename to be saved as during download:
"The_title_renamed_with_javascript.mp4"
This actually is possible with JavaScript, though browser support would be spotty. You can use XHR2 to download the file from the server to the browser as a Blob, create a URL to the Blob, create an anchor with its href property set to that URL, set the download property to whatever you want the filename to be, and then click the link. This works in Google Chrome, but I haven't verified support in other browsers.
window.URL = window.URL || window.webkitURL;
var xhr = new XMLHttpRequest(),
a = document.createElement('a'), file;
xhr.open('GET', 'someFile', true);
xhr.responseType = 'blob';
xhr.onload = function () {
file = new Blob([xhr.response], { type : 'application/octet-stream' });
a.href = window.URL.createObjectURL(file);
a.download = 'someName.gif'; // Set to whatever file name you want
// Now just click the link you created
// Note that you may have to append the a element to the body somewhere
// for this to work in Firefox
a.click();
};
xhr.send();
You can't do this with client-side JavaScript, you need to set the response header...
.NET
Response.AddHeader("Content-Disposition", "inline;filename=myname.txt")
Or PHP
header('Content-Disposition: inline;filename=myname.txt')
Also available in other server-side languages of your choice.
The filename for downloading is set in the header (take a look at "Content-Disposition"), wich is created on server-side.
There's no way you could change that with pure javascript on a file you're linking to unless you have access to the server-side (that way you could pass an additional parameter giving the filename and change the server-side behaviour to set the header to match that... but that would also be possible with pure html, no need for javascript). Conclusion: Javascript is absolute useless to achive what you want.
You can probably do this with a Chrome userscript, but it cannot be done (yet) with Greasemonkey (Firefox) javascript.
Workaround methods (easiest to hardest):
Add the links with Greasemonkey but use the excellent DownThemAll! add-on to download and rename the videos.
Download the videos as-is and use a batch file, shell-script, Python program, etc. to rename them.
Use Greasemonkey's GM_xmlhttpRequest()Doc function to send the files to your own web application on a server you control.
This server could be your own PC running XAMPP (or similar).
Write your own Firefox add-on, instead of a Greasemonkey script. Add-ons have the required privileges, Greasemonkey does not.
AFAIK, you will not be able to do this right from the client itself. You could first upload the file onto the server with the desired name, and then serve it back up to the end user (in which case your file name would be used).
Just in case you are looking for such a solution for your nasty downloading chrome extension, you should look into chrome.downloads API, it needs additional permission ('downloads') and allows you to specify filename. https://developer.chrome.com/extensions/downloads
However there is a problem I'm facing right now. The chrome extension I'm refactoring has 600k+ user base and adding a new permission would disable the extension for all of them. So it is no-go solution for me, but if you are developing a new extension you definitely should use it.