我创建了一个简单的 cordova android 应用程序,我试图从 URL 下载图像到图片库,但我真的不知道出了什么问题。 我已经在 stackoverflow 上搜索了很多,包括以下链接:
Phonegap - 将 URL 中的图像保存到设备照片库中
如何在Android中使用Phonegap将Image对象保存到文件中?
我已经安装了cordova文件传输插件并尝试从官方站点执行示例,但它也不起作用:https://cordova.apache.org/docs/en/latest/reference/cordova-plugin-文件传输/
我尝试了2个不同的代码,它们是:
1)第一次尝试:
document.getElementById("myBtn").addEventListener("click", function () {
download("http://cordova.apache.org/static/img/cordova_bot.png", "data", "new_file");
});
function download(URL, Folder_Name, File_Name) {
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.toURL();
fp = fp + "/" + Folder_Name + "/" + File_Name + "." + ext; // fullpath and name of the file which we want to give
filetransfer(download_link, fp);
}
function onDirectorySuccess(parent) {
// Directory created successfuly
}
function onDirectoryFail(error) {
alert("Unable to create new directory: " + error.code);
}
function fileSystemFail(evt) {
//Unable to access file system
alert(evt.target.error.code);
}
}
function filetransfer(download_link, fp) {
var fileTransfer = new FileTransfer();
fileTransfer.download(download_link, fp,
function (entry) {
alert("download complete: " + entry.fullPath);
//cordova.plugins.imagesaver.saveImageToGallery(entry.fullPath, successCallback, errorCallback);
},
function (error) {
alert("download error source " + error.source);
}
);
}
在此尝试中,我收到警报消息“下载完成:/my_folder/new_file.png”,但我找不到图片的下载位置。 它绝对不在图片库中或我能找到的任何地方。
2)第二次尝试:
function download() {
window.requestFileSystem(window.TEMPORARY, 5 * 1024 * 1024, function (fs) {
var url = 'http://cordova.apache.org/static/img/cordova_bot.png';
fs.root.getFile('downloaded-image.png', {
create: true,
exclusive: false
}, function (fileEntry) {
file_transfer(fileEntry, encodeURI(url), true);
}, onErrorCreateFile);
}, onErrorLoadFs);
}
function onErrorLoadFs(msg){
alert(msg);
}
function onErrorCreateFile(msg){
alert(msg);
}
function file_transfer(fileEntry, uri, readBinaryData) {
var fileTransfer = new FileTransfer();
var fileURL = fileEntry.toURL();
fileTransfer.download(
uri,
fileURL,
function (entry) {
alert("download complete: " + entry.toURL());
if (readBinaryData) {
// Read the file...
readBinaryFile(entry);
} else {
// Or just display it.
displayImageByFileURL(entry);
}
},
function (error) {
alert("download error source " + error.source);
alert("download error target " + error.target);
alert("upload error code" + error.code);
},
null, // or, pass false
{
//headers: {
// "Authorization": "Basic dGVzdHVzZXJuYW1lOnRlc3RwYXNzd29yZA=="
//}
}
);
}
在此尝试中,我收到警报消息“下载完成:file:///data/user/0/com.companyname.xxxxxxx/cache/downloaded-image.png”,但我也找不到设备中任意位置的图片。
我已经在两个不同的 Android 设备上尝试过该应用程序。
我就是这样做的。 你将需要 cordova 文件插件 它需要一个网址(在我的例子中为png) 它会将其保存在您的下载文件夹中(这使其出现在您手机的图库中)
//download file to device
function DownloadToDevice(fileurl) {
var blob = null;
var xhr = new XMLHttpRequest();
xhr.open("GET", fileurl);
xhr.responseType = "blob";//force the HTTP response, response-type header to be blob
xhr.onload = function()
{
blob = xhr.response;//xhr.response is now a blob object
console.log(blob);
var storageLocation = "";
switch (device.platform) {
case "Android":
storageLocation = 'file:///storage/emulated/0/';
break;
case "iOS":
storageLocation = cordova.file.documentsDirectory;
break;
}
var folderpath = storageLocation + "Download";
var filename = "Myimg.png";
var DataBlob = blob;
window.resolveLocalFileSystemURL(folderpath, function(dir) {
dir.getFile(filename, {create:true}, function(file) {
file.createWriter(function(fileWriter) {
fileWriter.write(DataBlob);
//Download was succesfull
}, function(err){
// failed
console.log(err);
});
});
});
}
xhr.send();
}
你应该换线
window.requestFileSystem(window.TEMPORARY, 5 * 1024 * 1024,
->
window.requestFileSystem(LocalFileSystem.PERSISTENT, 0,
和 如果下载成功,您应该重新扫描您的设备存储,因为Cordova不知道文件是否已下载。
所以我做了一个插件,
这是一个下载后更新图库的插件。
https://github.com/pouu69/cordova-plugin-gallery-refresh
如果您仍在寻找解决方案,请尝试这个适用于 Android 的工作插件
cordova plugin add cordova-plugin-downloadimage-to-gallery
我将此函数与回调一起使用。
要检查不同类型的
cordovaFileSystem
,请参阅 here 或通过在控制台中键入来检查可用的类型 console.log(cordova.file)
downloadFileToDevice('https://example.com/image.jpg', 'myimg.jpg', cordova.file.cacheDirectory,
(err, filePath) => {
if (err) {
console.log('An error was found: ', err)
} else {
console.log('file downloaded successfully to: ' + filePath)
}
})
function downloadFileToDevice (fileurl, filename, cordovaFileSystem, callback) {
var blob = null
var xhr = new XMLHttpRequest()
xhr.open('GET', fileurl)
xhr.responseType = 'blob' // force the HTTP response, response-type header to be blob
xhr.onload = function () {
blob = xhr.response // xhr.response is now a blob object
var DataBlob = blob
window.resolveLocalFileSystemURL(cordovaFileSystem, function (dir) {
dir.getFile(filename, { create: true }, function (file) {
file.createWriter(function (fileWriter) {
fileWriter.write(DataBlob)
callback(null, cordovaFileSystem + filename)
}, function (err) {
callback(err)
})
})
})
}
xhr.send()
}
您可以使用这些方法直接从Url下载图像并将其存储到所需的文件夹路径。
此方法用于从Url路径下载图像。
fun downloadAndSaveImage(
context: Context, imageUrl: String, fileName: String, listener: OnProgressListener
) {
Log.d("SaveImage", "downloadAndSaveImage: start 1")
Thread {
try {
val url = URL(imageUrl)
val connection: HttpURLConnection = url.openConnection() as HttpURLConnection
connection.doInput = true
connection.connect()
val inputStream: InputStream = connection.inputStream
val bitmap: Bitmap = BitmapFactory.decodeStream(inputStream)
if (bitmap != null) {
saveImageToPicturesFolder(context, bitmap, fileName, listener)
} else {
Log.e("SaveImage", "Bitmap is null. Failed to decode the image.")
}
inputStream.close()
} catch (e: Exception) {
e.printStackTrace()
}
}.start()
}
此方法用于将下载的图像存储到设备中所需的文件夹中。
private fun saveImageToPicturesFolder(
context: Context, bitmap: Bitmap, fileName: String, listener: OnProgressListener
) {
try {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) {
// Use MediaStore for Android 10 and above
val contentUri = MediaStore.Images.Media.EXTERNAL_CONTENT_URI
val selection = "${MediaStore.MediaColumns.DISPLAY_NAME} = ?"
val selectionArgs = arrayOf("$fileName.jpg")
// Check if the file already exists
context.contentResolver.query(contentUri, null, selection, selectionArgs, null)?.use { cursor ->
if (cursor.moveToFirst()) {
// File exists, return its URI
val uri = ContentUris.withAppendedId(contentUri, cursor.getLong(cursor.getColumnIndexOrThrow(MediaStore.MediaColumns._ID)))
Log.d("SaveImage", "Image already exists: $uri")
listener.onWallpaperSaved(uri.toString())
return
}
}
// Image doesn't exist, proceed to save it
val contentValues = ContentValues().apply {
put(MediaStore.MediaColumns.DISPLAY_NAME, "$fileName.jpg")
put(MediaStore.MediaColumns.MIME_TYPE, "image/jpeg")
put(
MediaStore.MediaColumns.RELATIVE_PATH,
Environment.DIRECTORY_PICTURES + File.separator + context.getString(R.string.app_name)
)
}
val uri = context.contentResolver.insert(contentUri, contentValues)
uri?.let {
context.contentResolver.openOutputStream(it).use { outputStream ->
if (outputStream != null) {
bitmap.compress(Bitmap.CompressFormat.JPEG, 100, outputStream)
outputStream.flush()
Log.d("SaveImage", "Image saved successfully using MediaStore: $uri")
listener.onWallpaperSaved(uri.toString())
} else {
Log.e("SaveImage", "Failed to open output stream.")
}
}
} ?: run {
Log.e("SaveImage", "Failed to insert image into MediaStore.")
}
} else {
// Fallback for Android 9 and below
val picturesFolder = File(
Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_PICTURES),
context.getString(R.string.app_name)
)
if (!picturesFolder.exists()) {
val folderCreated = picturesFolder.mkdirs()
Log.d(
"SaveImage",
"Folder creation result: $folderCreated, path: ${picturesFolder.absolutePath}"
)
if (!folderCreated) {
Log.e("SaveImage", "Failed to create folder: ${picturesFolder.absolutePath}")
return
}
}
val file = File(picturesFolder, "$fileName.jpg")
// Check if the file already exists
if (file.exists()) {
Log.d("SaveImage", "Image already exists at: ${file.absolutePath}")
listener.onWallpaperSaved(file.absolutePath)
return
}
// Save the image if it doesn't already exist
val fileOutputStream = FileOutputStream(file)
bitmap.compress(Bitmap.CompressFormat.JPEG, 100, fileOutputStream)
fileOutputStream.flush()
fileOutputStream.close()
Log.d("SaveImage", "Image saved successfully at: ${file.absolutePath}")
listener.onWallpaperSaved(file.absolutePath)
}
} catch (e: Exception) {
e.printStackTrace()
Toast.makeText(context, "Wallpaper failed!", Toast.LENGTH_SHORT).show()
Log.e("SaveImage", "Error saving image: ${e.message}")
}
}