Cordova file plugin - сохранить файл на устройстве
У меня много проблем с сохранением файлов в Android.
Проект представляет собой гибридное приложение, разработанное с помощью Ionic с этими плагинами:
com.phonegap.plugins.fileopener 1.0.0 "File Opener"
com.telerik.plugins.nativepagetransitions 0.4.2 "Native Page Transitions"
cordova-plugin-compat 1.0.0 "Compat"
cordova-plugin-crosswalk-webview 2.0.0 "Crosswalk WebView Engine"
cordova-plugin-file 4.2.0 "File"
cordova-plugin-network-information 1.2.2-dev "Network Information"
cordova-plugin-whitelist 1.2.3-dev "Whitelist"
cordova-plugin-wkwebview-engine 1.0.4-dev "Cordova WKWebView Engine"
ionic-plugin-keyboard 2.2.1 "Keyboard"
Версия платформы Android 5.2.1
Устройство, которое я использую, является Samsung A7
Это реферат от AndroidManifest.xml
<uses-sdk android:minSdkVersion="16" android:targetSdkVersion="23" />
<uses-permission android:name="android.permission.ACCESS_WIFI_STATE" />
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
Случай 1
если я попробую с этим фрагментом (на самом деле работает над другим проектом)
var storagePath = "/storage/emulated/0";
var fileDir = cordova.file.externalDataDirectory.replace(cordova.file.externalRootDirectory, '');
var fileName = $scope.ngDocument.documentId + ".pdf"
var filePath = storagePath + "/" + fileDir + fileName;
$cordovaFile.writeFile(filePath, BINARY_ARR, {'append': false}).then(function(result) {}, function(err) {});
я получил {"code":5,"message":"ENCODING_ERR"}
как Обратный звонок от $cordovaFile.writeFile
, независимо от того, если я использую абсолютный путь, относительный путь, просто имя файла, и файл никогда не создается.
Вариант 2
С этим фрагментом
window.requestFileSystem(LocalFileSystem.PERSISTENT, 0, function (fs) {
console.log('file system open: ' + fs.name);
fs.root.getFile(fileName, { create: true, exclusive: false }, function (fileEntry) {
console.log("fileEntry:" + JSON.stringify(fileEntry));
writeFile(fileEntry, BINARY_ARR);
}, function(data){});
}, function(data){});
случаются две разные вещи
Случай 2.1
Если параметры конфигурации не указаны в config.xml
приложение создает пустую папку в /storage/emulated/0/Android/media/{myAPP}
Дело 2.2
с этими двумя предпочтениями
<preference name="AndroidPersistentFileLocation" value="Compatibility" />
<preference name="AndroidExtraFilesystems" value="cache" />
файл в /storage/emulated/0
(внешний SSD) создан и в logcat
ошибки:
E/Vold ( 2280): Failed to find mounted volume for /storage/extSdCard/Android/data/{myApp}/files/
W/Vold ( 2280): Returning OperationFailed - no handler for errno 0
W/ContextImpl(13364): Failed to ensure directory: /storage/extSdCard/Android/data/{myApp}/files
E/Vold ( 2280): Failed to find mounted volume for /storage/extSdCard/Android/data/{myApp}/files/
W/Vold ( 2280): Returning OperationFailed - no handler for errno 0
W/ContextImpl(13364): Failed to ensure directory: /storage/extSdCard/Android/data/{myApp}/files
E/Vold ( 2280): Failed to find mounted volume for /storage/extSdCard/Android/data/{myApp}/cache/
W/Vold ( 2280): Returning OperationFailed - no handler for errno 0
W/ContextImpl(13364): Failed to ensure directory: /storage/extSdCard/Android/data/{myApp}/cache
Странный факт в том, что /storage/extSdCard
(символическая ссылка для /mnt/extSdCard
) не подключен, а внешний SSD установлен на /mnt/sdcard
Пожалуйста, помогите: я трясу головой.
Первый фрагмент работал как очарование в другом проекте. Это может быть версия ngCordova?
2 ответа
РЕШИТЬ:
после нескольких попыток я решил таким образом
в config.xml
:
<preference name="AndroidPersistentFileLocation" value="Compatibility" />
<preference name="AndroidExtraFilesystems" value="files,cache, sdcard, cache-external, files-external" />
и основная функция:
window.requestFileSystem(LocalFileSystem.PERSISTENT, 0, function (fs) {
//var absPath = "file:///storage/emulated/0/";
var absPath = cordova.file.externalRootDirectory;
var fileDir = cordova.file.externalDataDirectory.replace(cordova.file.externalRootDirectory, '');
var fileName = "somename.txt";
var filePath = fileDir + fileName;
fs.root.getFile(filePath, { create: true, exclusive: false }, function (fileEntry) {
writeFile(fileEntry, BINARY_ARR).then(function(){
//do something here
});
}, function(err) {});
}, function(err) {});
function writeFile(fileEntry, dataObj) {
return $q(function (resolve, reject) {
fileEntry.createWriter(function (fileWriter) {
fileWriter.onwriteend = function () {
resolve();
};
fileWriter.onerror = function (e) {
reject(e);
};
fileWriter.write(dataObj);
});
});
}
Казалось, что:
<preference name="AndroidPersistentFileLocation" value="Internal" />
это конфигурация по умолчанию, не позволяющая приложению записывать на внешний диск (физический или эмулированный). Вместо этого разрешено приложение только для записи в /data/data/{myApp}/files
Итак, вот полное объяснение того, как сохранить файл. Используя файловый плагин cordova:
Предположим, вам нужно сохранить файл с текстом "Hello Mr. Vaibhav Mojidra" в .txt внутри внутренней памяти.
Итак, вот оно, если у вас есть кнопка в HTML, например: Теперь внутри функции SaveFile:
var textt=""; функция SaveFile(текст) { textt = текст; /* инициализируем глобальную переменную текстом для записи в файл */ window.requestFileSystem(LocalFileSystem.PERSISTENT, 0,onFileSystemSuccess, сбой); /* Это проверит разрешение на чтение и запись в хранилище, и если разрешение получено, то параметр отправки функции будет вызываться иначе, если не предоставлен, то третий параметр, т.е. функция отказа будет вызвана */ } функция onFileSystemSuccess(файловая система) { fileSystem.root.getFile("Demo.txt",{create: true, эксклюзив: false},gotFileEntry,fail); /* Это создаст файл с именем Demo.txt во внутренней памяти. и аналогично успешно создать, он вызовет функцию второго параметра, то есть gotFileEntry */ } function gotFileEntry (fileEntry) { fileEntry.createWriter(gotFileWriter, сбой); /* Будет получен объект файла с вызовом пути createWriter, в котором 1-й параметр использовать для записи содержимого в файл и второй параметр при ошибке создания писателя */ } функция gotFileWriter(писатель) { writer.write (textt); /* передача параметра текста, который является глобальным и инициализируется сначала вызывается функция */ writer.onwriteend = function (evt) { alert ("Файл сохранен"); }; /* Эта функция будет вызываться после того, как файл будет записан с текстом и сохранен */ } сбой функции (ошибка) { alert ("Ошибка","Возникла проблема \n Ошибка:"+error.code,"Хорошо"); }
Используйте эту функцию для записи и создания новой папки
function writeFile(path, filename, blob) {
return new Promise((resolve, reject) => {
window.resolveLocalFileSystemURL(cordova.file.externalRootDirectory, function (dirpar) {
dirpar.getDirectory(path, { create: true }, function (dir) {
dir.getFile(filename, { create: true, exclusive: false }, function (fileEntry) {
fileEntry.createWriter(function (fileWriter) {
fileWriter.onwriteend = resolve
fileWriter.onerror = reject
fileWriter.write(blob);
});
}, reject);
}, reject);
}, reject);
});
}
как вызвать функцию
writeFile("AppFolder", 'file.name', blob)
образец скачать изображение и сохранить в папке
var url = "image url"
fetch(url).then(res => res.blob()).then(blob => {
writeFile("pictures/myapp", url.substring(url.lastIndexOf("/") + 1), blob)
.then(function () { console.log("file donwloaded.") })
.catch(function (e) { console.error("error:", e) })
});
Используйте плагин FileTransfer: https://github.com/apache/cordova-plugin-file-transfer для загрузки и https://github.com/pwlin/cordova-plugin-pdialog чтобы отобразить диалог хода выполнения.
function saveFileDownloaded(url, nameFile) {
var uri = url;
var test = isEncoded(url)
if (test == false) {
uri = encodeURI(url)
}
var fileTransfer = new window.FileTransfer();
var fileURL = cordova.file.externalRootDirectory + "Direct/" + nameFile;
cordova.plugin.pDialog.init({
theme : 'DEVICE_LIGHT',
progressStyle : 'HORIZONTAL',
cancelable : false,
message : 'Téléchargement en cours...'
});
fileTransfer.onprogress = function(result) {
var percent = result.loaded / result.total * 100;
percent = Math.round(percent);
cordova.plugin.pDialog.setProgress(percent);
};
fileTransfer.download(
uri,
fileURL,
function(entry) {
cordova.plugin.pDialog.dismiss();
navigator.notification.confirm(
'Voulez vous ouvrir le fichier', // message
function(buttonIndex) {
onConfirm(buttonIndex, fileURL);
}, // callback to invoke
'Téléchargement terminé', // title
['Ok', 'Exit'] // buttonLabels
);
},
function(error) {
cordova.plugin.pDialog.dismiss();
console.log(error)
alert("Erreur lors du téléchargement, vérifier votre connexion!");
console.log("download error source " + error.source);
console.log("download error target " + error.target);
console.log("upload error code" + error.code);
}
);
}