wkh237 / react-native-fetch-blob

A project committed to making file access and data transfer easier, efficient for React Native developers.
MIT License
2.61k stars 1.59k forks source link

Download manager could not resolve downloaded file path. #474

Open kholiavko-roman opened 7 years ago

kholiavko-roman commented 7 years ago

Hi! Thanks for you module! While development I have one issue, when I try to download file using addAndroidDownloads

Error: Error: Download manager could not resolve downloaded file path.
Status code: undefined

Here is my code:

RNFetchBlob
    .config({
        addAndroidDownloads : {
            useDownloadManager : true,
            notification : false,
            title: 'pdfurl-guide.pdf',
            mime : 'application/pdf',
            description : 'File downloaded by download manager.'
        },
    })
    .fetch('GET', 'http://www.axmag.com/download/pdfurl-guide.pdf')
    .then((resp) => {
        console.log('DOWNLOAD complete');

        RNFetchBlob.fs.exists(resp.path())
        .then((exist) => {
            console.log(`file ${exist ? '' : 'not'} exists`)
        })
        .catch(() => {
            console.log('error while checking file for exists');
        });

        console.log(resp.path());      
    })
    .catch((errorMessage, statusCode) => {
        console.log('Error: ' + errorMessage);
        console.log('Status code: ' + statusCode);
    });

I check my path, and it return FOLDER exists

let path = RNFetchBlob.fs.dirs.DocumentDir;

RNFetchBlob.fs.exists(path)
        .then((exist) => {
            console.log(`FOLDER ${exist ? '' : 'not'} exists`)
        })
        .catch(() => {
            console.log('error while checking FOLDER for exists');
        });

Can you help me please ? Maybe I make mistake somewhere ?

kholiavko-roman commented 7 years ago

Also i trying add path to adnroidDownloads config:

let path = RNFetchBlob.fs.dirs.DocumentDir;

RNFetchBlob.config({
    addAndroidDownloads : {
        useDownloadManager : true,
        notification : false,
        path: path + '/pdfurl-guide.pdf' ,
        title: 'pdfurl-guide.pdf',
        mime : 'application/pdf',
        description : 'File downloaded by download manager.'
    },
})

in this case I recive red screen with error: Unsupported path /data/user/0/com.chat/files/pdfurl-guide.pdf

And also I trying download without addAndroidDownloads,

let path = RNFetchBlob.fs.dirs.DocumentDir;

RNFetchBlob
    .config({
        path: path + '/pdfurl-guide.pdf'
    })

In this case it downloads, return path of file, but I can not find it on the device in the com.chat/files directory it is empty. But whe I check the file for existing

RNFetchBlob.fs.exists(resp.path())
        .then((exist) => {
            console.log(`file ${exist ? '' : 'not'} exists`)
        })
        .catch(() => {
            console.log('error while checking file for exists');
        });

It return that file is exist.

What I am doing wrong ?

wkh237 commented 7 years ago

@kholiavko-roman , Try to add file:// before the path.

kholiavko-roman commented 7 years ago

@wkh237, I tried, but I still have an error.

I trying this path: file:///data/user/0/com.chat/files, also I tried to remove one slash before the data file://data/user/0/com.chat/files, but result the same - I have red screen with error Unsupported path /data/user/0/com.chat/files/pdfurl-guide.pdf

 let path = 'file://' + RNFetchBlob.fs.dirs.DocumentDir;
 RNFetchBlob
    .config({
        path: path + '/pdfurl-guide.pdf',
        addAndroidDownloads : {
            useDownloadManager : true,
            notification : false,
            path: path + '/pdfurl-guide.pdf' ,
            title: 'pdfurl-guide.pdf',
            mime : 'application/pdf',
            description : 'File downloaded by download manager.'
        },
    })
    .fetch('GET', 'http://www.axmag.com/download/pdfurl-guide.pdf')
kholiavko-roman commented 7 years ago

I found some tmp fix, If I set path to DownloadDir - I can download file without error. let path = RNFetchBlob.fs.dirs.DownloadDir + '/pdfurl-guide.pdf';

And I found that when I set DocumentDir as in prev post, with or without file:// protocol, I recive red screen and on it path different from path that I see in the console. Also I trying MainBundleDir - result the same.

Unsupported path /data/data/user/0/com.chat/files/pdfurl-guide.pdf data/data in path duplicate. I trying to set math manually without data, like this: /user/0/com.chat/files/pdfurl-guide.pdf but I also revive an error, but on this time without duplicate /data/data/

Can you help me please? I tested on real devices with android 7.1 and 6.0

wkh237 commented 7 years ago

I think this is a restriction as Android Download Manager only accepts a path on external storage.

see related SO thread

kholiavko-roman commented 7 years ago

Ok, but if I need save file into the app directory, how I can do this without download managed ? I tried, but app folder com.myapp is empty.

wkh237 commented 7 years ago

You can download the file with DownloadManager API then copy the file (fs.cp) to your app folder (DocumentDir)

kholiavko-roman commented 7 years ago

Ok, I understand. Thanks for helping!

kholiavko-roman commented 7 years ago

@wkh237, can I download file in cash directory and open it after download ? I wanna just download image in cache and open it using actionViewIntent,

I tried to do this:

RNFetchBlob
                    .config({
                       fileCache : true,
                      appendExt : 'jpg'
                    })
                    .fetch('GET', attachItem.url)
                    .then((resp) => {
                      console.log(resp);
                      console.log(resp.path());

                      RNFetchBlob.fs.exists(resp.path())
                        .then((exist) => {
                            console.log(`file ${exist ? '' : 'not'} exists`)
                        })
                        .catch(() => { console.log('err while checking') });

                      if (Platform.OS === 'ios') {
                        RNFetchBlob.ios.openDocument(resp.path());
                      } else {
                        RNFetchBlob.android.actionViewIntent('file://' + resp.path(), 'image/jpg');
                      }
                    })
                    .catch((errorMessage, statusCode) => {
                      console.log('Error: ' + errorMessage);
                      console.log('Status code: ' + statusCode);
                    });

After downloading I see the path with extension /data/user/0/com.chat/files/RNFetchBlobTmp_0boqybb710yu9tyaknbt48w.jpg and after checking on existing file result - file exists but when I opened image using default gallery app I can not see it.

The same code on ios works fine. How to save image in cache and open it ?

kholiavko-roman commented 7 years ago

If I setup path to the RNFetchBlob.fs.dirs.CacheDir, I cant open file using actionViewIntent, but if I set path to the DownloadDir, or DCIMDir I can open file via actionViewIntent.

kholiavko-roman commented 7 years ago

You can download the file with DownloadManager API then copy the file (fs.cp) to your app folder (DocumentDir)

@wkh237, also I tried to copy from download directory to DocumentDirs, but it it was not successful, document dirs are empty. ( I tried to move or copy it, and save it directry to DocumentDir or save in sub folder in DocumentDir - result the same, I see in console that file moved, but in my app directory is nothing change)

 RNFetchBlob.fs.mv(resp.path(), RNFetchBlob.fs.dirs.DocumentDir + '/test/qq.jpg')
                          .then(() => {
                            console.log('file moved');
                          })
                          .catch(() => {
                            console.log('err while moving');
                          });
mohamedtijani commented 6 years ago

@kholiavko-roman I have the same problem, you solved it

kholiavko-roman commented 6 years ago

@mohamedtijani, no.

romreed commented 6 years ago

@kholiavko-roman you still not solved problem?

kholiavko-roman commented 6 years ago

@romreed, unfortunately no.

romreed commented 6 years ago

@kholiavko-roman i solved problem like this

`export function getMimeType(type) {

switch (type) {
    case "doc" :
        return "application/msword";
    case "docx" :
        return "application/vnd.openxmlformats-officedocument.wordprocessingml.document"
    case "ppt":
        return "application/vnd.ms-powerpoint";
    case "pptx":
        return "application/vnd.openxmlformats-officedocument.presentationml.presentation"
    case "xls" :
        return "application/vnd.ms-excel";
    case "xlsx" :
        return "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet";
    case "pdf" :
        return "application/pdf";
    case "png" :
        return "image/png";
    case "bmp" :
        return "application/x-MS-bmp";
    case "gif" :
        return "image/gif";
    case "jpg" :
        return "image/jpeg";
    case "jpeg" :
        return "image/jpeg";
    case "avi" :
        return "video/x-msvideo";
    case "aac" :
        return "audio/x-aac";
    case "mp3" :
        return "audio/mpeg";
    case "mp4" :
        return "video/mp4";
    case "apk" :
        return "application/vnd.Android.package-archive";
    case "txt" :
    case "log" :
    case "h" :
    case "cpp" :
    case "js" :
    case "html" :
        return "text/plain";
    default:
        return "*/*";
}

} export const downloadFile = (id, type, url, name) => (dispatch, getState) => { let filename = "default" var m = url.toString().match(/.*\/(.+?)./); if (m && m.length > 1) { filename = m[1] }

    let dirs = RNFetchBlob.fs.dirs
    filePath = `${dirs.DownloadDir}/${filename}.${type}`

        dispatch({type: 'DOWNLOAD_FILE_BEGIN'})

        RNFetchBlob.config({
            path: filePath,
            addAndroidDownloads: {
                title: `${name} загружен`,
                description: `${name} загружен`,
                mediaScannable: true,
                mime: getMimeType(type),
                notification: true
            }
        })
            .fetch('GET', url, {
                'Cache-Control': 'no-store'
            })
            .then((res) => {
                    RNFetchBlob.android.actionViewIntent(res.path(), getMimeType(type));
                    dispatch({type: DOWNLOAD_FILE_SUCCESS, payload: {id: id, location: res.path(),mime: getMimeType(type)}})
            })
            .catch((errorMessage, statusCode) => {
                dispatch({type: DOWNLOAD_FILE_ERROR, payload: {message: errorMessage}})
          })}

` maybe this help you

LtkStark commented 6 years ago

@romreed Thank you ! I create an account juste to say thank you ! Was blocked on this so much time...

romreed commented 6 years ago

@LtkStark I'm glad that my code helped you

thallamsai commented 6 years ago

@romreed @LtkStark Every time the control is going to catch block with the error Error: Download manager could not resolve downloaded file path. and the file is getting downloaded. I want to know the res.path() of the downloaded file. Here is my code

    const dirs = RNFetchBlob.fs.dirs;
    const filePath = `file://${dirs.DownloadDir}/${caption}.pdf`;
    const configOptions = {
      addAndroidDownloads: {
        useDownloadManager: true,
        mime: 'application/pdf',
        description: 'File downloaded by download manager.',
        path: filePath
      }
    };
    RNFetchBlob
     .config(configOptions)
     .fetch('GET', srcUrl)
     .then((res) => {
       console.log(res.path());
     })
     .catch((err) => {
         console.log(err);
      });

platform : Android

thallamsai commented 6 years ago

removing file:// in the file path solved the issue.

aoarashi1988 commented 6 years ago

set the path in addAndroidDownoload, not directly in config work

let savePath = RNFetchBlob.fs.dirs.DownloadDir + '/video.mp4' RNFetchBlob .config({ fileCache: true, addAndroidDownloads: { useDownloadManager: true, notification: true, title: 'video.mp4', mime: 'video/mp4', description: 'download description', mediaScannable: true, path: savePath, } }) .fetch('GET', url) .then(res => { let downloadPath = res.path() console.log(downloadPath) }) .catch(err => { console.log(err) })

don't work ,

llet savePath = RNFetchBlob.fs.dirs.DownloadDir + '/video.mp4' RNFetchBlob .config({ fileCache: true, path: savePath, addAndroidDownloads: { useDownloadManager: true, notification: true, title: 'video.mp4', mime: 'video/mp4', description: 'download description', mediaScannable: true, } }) .fetch('GET', url) .then(res => { let downloadPath = res.path() console.log(downloadPath) }) .catch(err => { console.log(err) })