25

I'm developing phonegap application and I need to save Image from url to the Device Photo Gallery.

I can't find at the Phonegap Api a way for doing it and Also I didn't find phonegap plugin for that.

I need it to work with Iphone & Android

Thanks a lot!

michaelbn
  • 7,393
  • 3
  • 33
  • 46
justtal
  • 800
  • 1
  • 7
  • 16

9 Answers9

34

This is file download code which can be used by anyone. You just have three parameters to use this like-

1) URL

2) Folder name which you want to create in your Sdcard

3) File name (You can give any name to file)

All types of file can download by using this code. you can use this as .js And this works on IOS also.

//First step check parameters mismatch and checking network connection if available call    download function
function DownloadFile(URL, Folder_Name, File_Name) {
//Parameters mismatch check
if (URL == null && Folder_Name == null && File_Name == null) {
    return;
}
else {
    //checking Internet connection availablity
    var networkState = navigator.connection.type;
    if (networkState == Connection.NONE) {
        return;
    } else {
        download(URL, Folder_Name, File_Name); //If available download function call
    }
  }
}

//Second step to get Write permission and Folder Creation

function download(URL, Folder_Name, File_Name) {
//step to request a file system 
    window.requestFileSystem(LocalFileSystem.PERSISTENT, 0, fileSystemSuccess, fileSystemFail);

function fileSystemSuccess(fileSystem) {
    var download_link = encodeURI(URL);
    ext = download_link.substr(download_link.lastIndexOf('.') + 1); //Get extension of URL

    var directoryEntry = fileSystem.root; // to get root path of directory
    directoryEntry.getDirectory(Folder_Name, { create: true, exclusive: false }, onDirectorySuccess, onDirectoryFail); // creating folder in sdcard
    var rootdir = fileSystem.root;
    var fp = rootdir.fullPath; // Returns Fulpath of local directory

    fp = fp + "/" + Folder_Name + "/" + File_Name + "." + ext; // fullpath and name of the file which we want to give
    // download function call
    filetransfer(download_link, fp);
}

function onDirectorySuccess(parent) {
    // Directory created successfuly
}

function onDirectoryFail(error) {
    //Error while creating directory
    alert("Unable to create new directory: " + error.code);
}

  function fileSystemFail(evt) {
    //Unable to access file system
    alert(evt.target.error.code);
 }
}

//Third step for download a file into created folder

function filetransfer(download_link, fp) {
var fileTransfer = new FileTransfer();
// File download function with URL and local path
fileTransfer.download(download_link, fp,
                    function (entry) {
                        alert("download complete: " + entry.fullPath);
                    },
                 function (error) {
                     //Download abort errors or download failed errors
                     alert("download error source " + error.source);
                     //alert("download error target " + error.target);
                     //alert("upload error code" + error.code);
                 }
            );
}

Useful Link

Suhas Gosavi
  • 2,170
  • 19
  • 40
  • If you download image from any URL, it will appear automatically in your device gallery. Using this you can download any file by creating new folder or existing folder not only image. – Suhas Gosavi Feb 05 '14 at 13:52
  • It doesn't work for me :(. I get an error code 1. What should I do? – doron Apr 24 '14 at 17:31
  • @doron which device? this should work. You are so close, it's just your target file that is wrong I think. – Suhas Gosavi Apr 25 '14 at 05:25
  • samsung galaxy s3, android 4.1.2. what could be wrong? I used the code written here. – doron Apr 26 '14 at 18:46
  • @doron this should work. If you are using same code. You added file transfer plugin in config file? And you just have to provide three parameters url, folder name, file name to above code. – Suhas Gosavi Apr 27 '14 at 05:00
  • 3
    Hi, When I add this string to the beginning of the file path: `file:///storage/sdcard0` - it works. Maybe, the fileSystem.root command has some problem? – doron Apr 27 '14 at 16:36
  • @doron firstly, thanks for your tip about file path, it worked for me. Secondly, did you perchance figure out how to store something to one of the folders in your app? – trainoasis Jun 18 '14 at 11:46
  • 2
    Gian's answer worked for me. Change the rootdir.fullPath to rootdir.toUrl(); – h3n Jun 24 '14 at 03:03
  • 3
    `If you download image from any URL, it will appear automatically in your device gallery.` - not for me. I can find it on my filesystem, but it doesnt appear in the gallery ? – commonpike Oct 30 '14 at 15:37
  • Re: commonpike - I read elsewhere the gallery has to be triggered to re-index the sdcard on android. – commonpike Nov 27 '14 at 14:27
  • http://stackoverflow.com/questions/3625640/download-images-and-save-locally-on-iphone-phonegap-app in my ansswer here, I have used fileSystem.root.nativeURL; //root path – decodingpanda Jan 14 '15 at 09:41
  • How can i save a Image for display in Gallery? – Danilo Oliveira Apr 14 '15 at 17:51
  • 3
    I tried this for the past 2 days, but I could not save to the Photo Library of an iOS device. Instead, the images were getting saved to the app's sandbox (as the URL also suggested). To achieve saving the images in the Photo Library, I had to use `cordova-plugin-canvas2image` which worked like a charm. I see this answer has a lot of upvotes, so maybe the API changed in the meantime, or something like that. – Adrian Marinica Nov 03 '15 at 15:47
  • @AdrianMarinica could you please provide your solution with `cordova-plugin-canvas2image`? i tried the solution proposed here, but it keeps saving to the internal folder and does NOT show up in the photo gallery. – Jane Wayne Apr 02 '16 at 07:38
  • @JaneWayne you should be able to find all the information you need here https://www.npmjs.com/package/cordova-plugin-canvas2image – Adrian Marinica Apr 06 '16 at 14:51
  • does it support to downloaded video and display it in the gallery of ios device. – Pritish Dec 27 '17 at 13:42
  • @Suhas I tried this code for ios but it's not working. – Pritish Dec 28 '17 at 06:16
  • @Pritish yes working for iOS also please check if you are getting any error – Suhas Gosavi Dec 28 '17 at 06:19
  • @Suhas I am not getting any error right now I am trying it on the emulator. do I need to test it on the real device of ios. – Pritish Dec 28 '17 at 06:21
  • @Pritish yes please check on device – Suhas Gosavi Dec 28 '17 at 06:22
  • @Suhas on real device it show me error message alert("download error source " + error.source); here – Pritish Dec 28 '17 at 07:05
  • @Suhas var fp = rootdir.fullPath; in console.log it displays only / (slash). – Pritish Dec 28 '17 at 07:06
  • @Suhas same code running on emulator but on real device it gives error error message alert("download error source " + error.source); – Pritish Dec 28 '17 at 11:11
18

The latest version of Cordova (3.3+), the newer (1.0.0+) version of File uses filesystem URLs instead of the file path. So, to make the accepted answer work with the newer version in the FileSystemSuccess function change the line:

var fp = rootdir.fullPath; 

to:

var fp = rootdir.toURL(); 
Community
  • 1
  • 1
Gian Luca Scoccia
  • 725
  • 1
  • 8
  • 26
9

Another easy way is to use the Cordova/Phonegap plugin Canvas2ImagePlugin. Install it and add the following function to your code which is based on getImageDataURL() by Raul Sanchez (Thanks!).

function saveImageToPhone(url, success, error) {
    var canvas, context, imageDataUrl, imageData;
    var img = new Image();
    img.onload = function() {
        canvas = document.createElement('canvas');
        canvas.width = img.width;
        canvas.height = img.height;
        context = canvas.getContext('2d');
        context.drawImage(img, 0, 0);
        try {
            imageDataUrl = canvas.toDataURL('image/jpeg', 1.0);
            imageData = imageDataUrl.replace(/data:image\/jpeg;base64,/, '');
            cordova.exec(
                success,
                error,
                'Canvas2ImagePlugin',
                'saveImageDataToLibrary',
                [imageData]
            );
        }
        catch(e) {
            error(e.message);
        }
    };
    try {
        img.src = url;
    }
    catch(e) {
        error(e.message);
    }
}

Use it like this:

var success = function(msg){
    console.info(msg);
};

var error = function(err){
    console.error(err);
};

saveImageToPhone('myimage.jpg', success, error);
M165437
  • 897
  • 1
  • 10
  • 18
  • 2
    On my end, this is the only answer that not only downloads the photo, but also inserts it into the gallery as the op requested. On android, it calls the MediaScanner intent to reindex the gallery so it shows up right away. On iOS, it requests access to the 'Photos'. – commonpike Nov 29 '14 at 14:32
  • on winphone however, it throws a security error. the canvas is 'tainted' and `canvas.toDataURL` is not allowed; even if the server sets the correct CORS headers on the image. – commonpike Mar 12 '15 at 21:45
  • 1
    winphone (ie10) is discussed here - with a workaround using xhr : http://stackoverflow.com/questions/18112047/canvas-todataurl-working-in-all-browsers-except-ie10 . – commonpike Mar 12 '15 at 22:31
  • this work for me with a little changes. I use phonegap build: https://github.com/devgeeks/Canvas2ImageDemo – J261 Jun 27 '16 at 01:10
  • this will freeze the UI if your are downloading large images. – Julian Paolo Dayag Aug 09 '18 at 10:44
  • And as of now (2018), this just crashes on iOS. Canvas2ImagePlugin is not maintained anymore and there are issues mentioned. Android works (but only if you call it exactly as written above, using cordova.exec(..), otherwise it fails with a message) – commonpike Aug 15 '18 at 15:22
6

This can be done using phone gap file plugin:

 var url = 'http://image_url';
    var filePath = 'local/path/to/your/file';
    var fileTransfer = new FileTransfer();
    var uri = encodeURI(url);

    fileTransfer.download(
        uri,
        filePath,
        function(entry) {
            console.log("download complete: " + entry.fullPath);
        },
        function(error) {
            console.log("download error source " + error.source);
            console.log("download error target " + error.target);
            console.log("upload error code" + error.code);
        },
        false,
        {
            headers: {
                "Authorization": "Basic dGVzdHVzZXJuYW1lOnRlc3RwYXNzd29yZA=="
            }
        }
    );
Hazem Hagrass
  • 9,329
  • 10
  • 32
  • 54
4

Maybe you could try the plugin I wrote for IOS

here is the git link: https://github.com/Nomia/ImgDownloader

Short Example:

document.addEventListener("deviceready",onDeviceReady);

//google logo url
url = 'https://www.google.com/images/srpr/logo11w.png';

onDeviceReady = function(){
    cordova.plugins.imgDownloader.downloadWithUrl(url,function(){
        alert("success");
    },function(){
        alert("error");
    });        
}

//also you can try dataUri like: 1px gif
//url = 'data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///yH5BAEAAAAALAAAAAABAAEAAAIBRAA7'

you can also save a local file to image gallery use the download method

Nimbosa
  • 107
  • 2
  • 4
3

Simplest approach

If you are ok with it being in the download's folder do the following

  1. Install In-App browser plugin

    cordova plugin add cordova-plugin-inappbrowser
    
  2. Create a download button with

    onclick="window.open("Image_URL", '_system');
    

Not only will this download the image it will offer to open the image in the corresponding app or browser.

aWebDeveloper
  • 36,687
  • 39
  • 170
  • 242
  • will that download the image. because when i tried it was only downloading documentation like pdf.for images we have to hold the image and then it asks for save(in chrome). correct me if i'm wrong – santhosh May 19 '16 at 14:11
  • hmmm. would show all applicable programs as handler. Ya but in most cases chrome is the one and what you said is right – aWebDeveloper May 20 '16 at 02:42
  • is their any work around to this small problem for images?? – santhosh May 20 '16 at 08:41
2

I'm currently working on cordova-plugin-photo-library.

It can save image that given by url (file:// or data:). Works on ios and android, jpeg/png/gif:

cordova.plugins.photoLibrary.saveImage(url, 'My album', function () {}, function (err) {});
viskin
  • 493
  • 4
  • 15
  • I recommend you read [How to offer personal open-source libraries?](//meta.stackexchange.com/q/229085) before posting about your projects here. – Martijn Pieters Oct 20 '16 at 09:30
  • I've read. The question asked was to get phonegap plugin to save to photo gallery, that works with ios and android. The answer provided a solution, with sample code to achieve what @justtal wanted. I disclosed that I'm library's author. Is really my answer looks inappropriate to you? I personally read through answers to this specific questions, and when found no solution that worked to me, implemented my project which I shared. – viskin Oct 20 '16 at 10:15
  • You were posting the exact same answer, without any further customisation to the specific question, to multiple places, which is why I prompted you to read that post. Don't go seek out all the places where your library *might* offer a solution, please. – Martijn Pieters Oct 20 '16 at 10:16
  • 1
    Ok. See, I understand that I answer to multiple questions with same copy-paste answer, but we are talking about multiple completely identical questions. I just don't know what I can customize in my answer, maybe saying the same thing with different words? Will it be more appropriate way to post? – viskin Oct 20 '16 at 10:24
  • At that point, *vote to close the questions as duplicates*. That's what we have that option for. – Martijn Pieters Oct 20 '16 at 10:25
  • Great, will do that. – viskin Oct 20 '16 at 10:27
0

I initially got "Could not create target file".

For that use encodeURI() on the url to download:

var DBuri = encodeURI("https://dl.dropbox.com/u/13253550/db02.xml");
fileTransfer.download(
    DBuri,
sPath + "database.xml",

And the code in this thread worked perfectly. Just putting it out here.

Community
  • 1
  • 1
allwynmasc
  • 393
  • 5
  • 18
0

I cleaned-up and wrapped the code suggested by Suhas above - the accepted answer in an angular service so that it can easily be used in other application. You can find the snipet here.

To use it, you include the script in app.js (and your index.html file) then:

angular.module('myApp.controllers.whatever', [])
    .controller('WhateverController', function ($scope, SaveToGalleryService) {

    $scope.savePhoto = function(photoUrl, folderName, fileName, callback) {
        var fileName = new Date().getTime();
        SaveToGalleryService.saveToGallery(photoUrl, "Kiddiz.me", fileName, function saveSuccess(res) {
            console.log("Photo ", photoUrl, "photo saved", res);
            if (callback) {
                callback(true, res);
            }
        }, function saveFail () {
            console.log("Photo ", photoUrl, "failed to save photo");
            if (callback) {
                callback(false);
            }
        });
    }
});
Community
  • 1
  • 1
Tomer Cagan
  • 1,078
  • 17
  • 31