I want rename file and when use bellow code and rename file successful but after I don't see that file on my phone and the file is deleted. I requested 2 permissions READ_EXTERNAL_STORAGE and WRITE_EXTERNAL_STORAGE successful
My code to get all image in device and rename function
MainActivity{
getAllImages()
btn_rename.setOnClickListener{
var old_file=listImageFile.get(pos_selected)
var new_file=File(old_file.parent,new_name)
var check:Boolean=old_file.renameTo(new_file)
if(check){
// check return true
}
}
}
fun getAllImages() {
listImageFile= arrayListOf()
val allImages = arrayListOf<Uri>()
val imageProjection = arrayOf(
MediaStore.Images.Media.DATA,
)
val cursor = requireActivity().contentResolver.query(
MediaStore.Images.Media.EXTERNAL_CONTENT_URI,
imageProjection,
null,
null
)
cursor.use {
if (cursor != null) {
val data = cursor.getColumnIndexOrThrow(MediaStore.Images.Media.DATA)
while (cursor.moveToNext()) {
var path = cursor.getString(data)
var file=File(path)
if(file.exists()){
listImageFile.add(
FileData(
file,
false
)
)
}
}
}
}
}
Whenever you create/rename/delete file, you must refresh the system files.
Try this below solution after rename the file:
btn_rename.setOnClickListener{
var old_file=listImageFile.get(pos_selected)
var new_file=File(old_file.parent,new_name)
var check:Boolean=old_file.renameTo(new_file)
if(check){
// check return true
MediaScannerConnection.scanFile(context, arrayOf(old_file.absolutePath),null,null)
MediaScannerConnection.scanFile(context, arrayOf(new_file.absolutePath),null,null)
}
}
Related
I got files in device. And i want when click select one file and rename name file. But after rename, file become have not format file. How to rename file ?
fun renameFile(){
var file=listDownloadsFile.get(i).file
var filetwo=File("/storage/emulated/0/Download/",new_name)
var check:Boolean=file.renameTo(filetwo)
if(check){
Log.d("kkdkdk",check.toString())
}
else{
Log.d("kkdkdk",check.toString())
}
}
private fun getAllFileInDownload() {
var listDownloadsFile = Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DOWNLOADS)
.listFiles()
for (i in 0 until files.size) {
listDownloads.add(
FileData(
files[i],
false
)
)
}
} ```
you can try this:
fun renameFile(){
var file = listDownloadsFile.get(i).file
val oldName = file.nameWithoutExtension
val newPath = file.path.replace(oldName, new_name).trim()
val filetwo = File(newPath)
if (filetwo.exists()) {
//show a message file exited
} else {
val check = renameFile(file, filetwo)
if(check){
Log.d("kkdkdk",check.toString())
}
else{
Log.d("kkdkdk",check.toString())
}
}
}
private fun rename(from: File, to: File): Boolean {
return from.parentFile.exists() && from.exists() && from.renameTo(to)
}
I'm developing an applicaiton using Android 11 and Kotlin. I've successfully written a file to the Download folder on the device. When writing to the folder again using the same file name, the result is another file with the same name. So now I have two files with the same name.
So first I thought I'd just delete the file then write it again. I spent hours and hours trying that to no avail. The delete code would execute without exception but the file would never delete. I'm pretty sure I set the proper permissions by using
if (!isWriteExternalStoragePermissionGranted()) {
val permissions = arrayOf(WRITE_EXTERNAL_STORAGE)
for (i in permissions.indices) {
requestPermission(permissions[i], i)
}
}
private fun isWriteExternalStoragePermissionGranted(): Boolean {
val permissionCheck = ActivityCompat.checkSelfPermission(this, WRITE_EXTERNAL_STORAGE)
return permissionCheck == PackageManager.PERMISSION_GRANTED
}
Then I thought I'd truncate the contents of the file and just overwrite the files contents. That didn't work. Just annother copy of file again and again. I have spent almpost a full day on this. It really shouldn't be this hard. I've tried numerous examples.. nothing works. Here's my code to write the file...
fun writeToFile(applicationContext: Context, filename: String, data: String) {
try {
val resolver = applicationContext.contentResolver
val values = ContentValues()
values.put(MediaStore.MediaColumns.DISPLAY_NAME, filename)
values.put(MediaStore.MediaColumns.MIME_TYPE, "text/xml")
values.put(MediaStore.MediaColumns.RELATIVE_PATH, Environment.DIRECTORY_DOWNLOADS)
val uri = resolver.insert(MediaStore.Files.getContentUri("external"), values)
//val cr: ContentResolver = getContentResolver()
val os: OutputStream? = uri?.let { resolver.openOutputStream(it,"wt") }
if (os != null) {
os.write(data.toByteArray())
os.flush()
os.close()
}
/*
if (uri != null) {
resolver.openFileDescriptor(uri, "wt")?.use {
FileOutputStream(it.fileDescriptor).use {
it.write(data.toByteArray()
)
}
}
}
*/
} catch (e: FileNotFoundException) {
e.printStackTrace()
} catch (e: IOException) {
e.printStackTrace()
}
}
Here's my code to delete the file first that never works. I've tried multiple variations...
fun deleteFile(context: Context, filename: String, applicationContext: Context){
val myFile = File(context.getExternalFilesDir(Environment.DIRECTORY_DOWNLOADS), filename)
if (myFile.exists()) {
myFile.delete()
}
}
fun deleteFile(context: Context, filename: String, applicationContext: Context){
val resolver = applicationContext.contentResolver
val values = ContentValues()
values.put(MediaStore.MediaColumns.DISPLAY_NAME, filename)
values.put(MediaStore.MediaColumns.MIME_TYPE, "text/xml")
values.put(MediaStore.MediaColumns.RELATIVE_PATH, Environment.DIRECTORY_DOWNLOADS)
val uri = resolver.insert(MediaStore.Files.getContentUri("external"), values)
if (uri != null) {
resolver.delete(uri, null, null)
}
}
You should use the uri you got with the first insert() where you created the file.
My current Android Application stores pdf files on external storage using
val contentUri = MediaStore.Files.getContentUri(VOLUME_NAME_EXTERNAL)
The application creates a sub folder in the standard Documents folder.
My manifest contains
android:requestLegacyExternalStorage = true
For Android 30 I request the following
val intent = Intent(Settings.ACTION_MANAGE_APP_ALL_FILES_ACCESS_PERMISSION)
val uri = Uri.fromParts("package", packageName, null)
intent.data = uri
startActivity(intent)
I have a background worker that attempts to clear all down loaded files, the code I employ is as follows:-
#RequiresApi(Build.VERSION_CODES.Q)
override suspend fun doActualFlowedWork(): Result {
if (hasSdkHigherThan(Build.VERSION_CODES.P)) {
clearDownloadFiles()
} else {
clearDownloadLegacyFiles()
}
return result ?: Result.success()
}
#Suppress("BlockingMethodInNonBlockingContext")
#RequiresApi(Build.VERSION_CODES.Q)
private fun clearDownloadFiles() {
val resolver = context.contentResolver
val relativeLocation = "${Environment.DIRECTORY_DOCUMENTS}${MY_SUB_FOLDER}"
val contentUri = MediaStore.Files.getContentUri(VOLUME_NAME_EXTERNAL)
resolver.query(
contentUri,
arrayOf(MediaStore.MediaColumns._ID, MediaStore.MediaColumns.DISPLAY_NAME, MediaStore.MediaColumns.RELATIVE_PATH),
"${MediaStore.MediaColumns.RELATIVE_PATH}=?",
arrayOf(relativeLocation),
null
).use { cursor ->
cursor?.let {
while (it.moveToNext()) {
val idIndex = cursor.getColumnIndex(MediaStore.MediaColumns._ID)
val displayNameIndex = cursor.getColumnIndex(MediaStore.MediaColumns.DISPLAY_NAME)
val relativePathNameIndex = cursor.getColumnIndex(MediaStore.MediaColumns.RELATIVE_PATH)
if (cursor.getString(relativePathNameIndex) == relativeLocation) {
val fileContentUri = MediaStore.Files.getContentUri(VOLUME_NAME_EXTERNAL, cursor.getLong(idIndex))
val count = context.contentResolver.delete(fileContentUri, null, null)
if (count == 0) Timber.e("FAILED to clear downloaded file = ${cursor.getString(displayNameIndex)}")
else Timber.i("Cleared downloaded file = ${cursor.getString(displayNameIndex)}")
}
}
}
}
}
#Suppress("DEPRECATION")
private fun clearDownloadLegacyFiles() {
val documentsFolder = File(Environment.getExternalStorageDirectory(), Environment.DIRECTORY_DOCUMENTS)
if (!documentsFolder.exists()) return
val mendeleyLiteSubFolder = File(Environment.getExternalStorageDirectory(), "${Environment.DIRECTORY_DOCUMENTS}$MY_SUB_FOLDER")
if (!mendeleyLiteSubFolder.exists()) return
val downloadFiles = mendeleyLiteSubFolder.listFiles()
downloadFiles?.forEach { downloadFile ->
if (downloadFile.exists()) downloadFile.delete()
Timber.i("Clearing downloaded file = $downloadFile")
}
}
This clear down worker completes OK, with the logs showing the files have been deleted
however when I use Android Studio Device File Explorer to view my Document sub folder the physical pdf files are still present.
Are my expectations incorrect?
What does this code achieve context.contentResolver.delete(fileContentUri, null, null)?
How do I delete physical files from my sub folder?
In my Android application I have a feature of renaming files. I have implemented this feature by creating a new file with new name on same path and then copying the content of original file to new file after all that I delete the file with old name.
The problem here is that the timestamp of the original file is not retained and the renamed file gets created with time when it was renamed.
What I have tried so far
1- I used file.renameTo() function.
2- 1 never works so I used setLastModified method for new file and passed it the last modified date of original file. Got this last modified date by using existingFile.lastModified().
3- After that in function where i am fetching files using Media Store I sorted the files by DATE_MODIFIED
4- Point 3 doesn't worked properly as it keeps showing renamed file on top with original file date, so I removed Sort by DATE_MODIFIED from media store and tried fetchedFiles.sortByDescending { it.getMFileDate() }
5- Point 4 also have same issue the renamed file shows up on top.
Code for renameTo function usage that didn't work properly
try {
val existingFile = File(selectedFile.getMAbsolute_path())
val separator = "."
val arrValues: Array<String> =
selectedFile.getMAbsolute_path()?.split(separator)!!.toTypedArray()
val newFileName = inputText
val newFilePath =
selectedFile.getMParent_file() + "/$newFileName.${arrValues[arrValues.size - 1]}"
val newFile = File(newFilePath)
existingFile.renameTo(newFile)
} catch (e: Exception) {
e.printStackTrace()
}
The above code renames the file on device version 8 but on Android version 7 it just removes the file. It doesn't shows up same results on different devices
Below is my current code:
Permissions
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
<uses-permission android:name="com.android.launcher.permission.INSTALL_SHORTCUT" />
<uses-permission android:name="com.android.launcher.permission.UNINSTALL_SHORTCUT" />
<uses-permission android:name="com.android.launcher.permission.READ_PHONE_STATE" />
UPDATED [23-12-2020]
I have made changes to proceedRenaming function, first i created new file object then copied it, after that i have set lastModified and at the end Media Store scan is called.
This is the right call hierarchy. It works fine on devices greater than or equal to Android Version 8 (OREO).
I have figured out the setLastModified function is not working on devices below Android Version 8 (OREO). It keeps on setting the current date to new file.
Rename Function
private fun proceedRenaming(
context: Context,
selectedFile: MyFileModel,
positionOfDeleted: Int,
inputText: String,
isFileShortcutCreated: Boolean
) {
try {
//delete shortcut if exists
deleteFileShortCut(context, selectedFile, positionOfDeleted)
val existingFile = File(selectedFile.getMAbsolute_path())
val separator = "."
val arrValues: Array<String> =
selectedFile.getMAbsolute_path()?.split(separator)!!.toTypedArray()
val newFileName = inputText
val newFilePath = selectedFile.getMParent_file() + "/$newFileName.${arrValues[arrValues.size - 1]}"
val newFile = File(newFilePath)
copy(existingFile, newFile)
//print the original last modified date
val sdf = SimpleDateFormat("MM/dd/yyyy")
val date1 = "" + sdf.format(existingFile.lastModified())
Log.d("Origina Date :", date1)
//set this date
//need convert the above date to milliseconds in long value
val newDate: Date = sdf.parse(date1)
newFile.setLastModified(newDate.time)
//print the latest last modified date
val date2 = "" + sdf.format(newFile.lastModified())
Log.i("Lastest Date : ", date2)
context?.sendBroadcast(
Intent(
Intent.ACTION_MEDIA_SCANNER_SCAN_FILE,
Uri.fromFile(newFile)
)
)
if (existingFile.exists()) {
existingFile.delete()
existingFile.canonicalFile.delete()
if (existingFile.exists()) {
BaseApplication.applicationContext()
.deleteFile(existingFile.getName())
}
}
MediaScannerConnection.scanFile(
context,
arrayOf<String>(selectedFile.getMAbsolute_path().toString()),
null
) { path, uri ->
Log.i("ExternalStorage", "Scanned $path:")
Log.i("ExternalStorage", "-> uri=$uri")
context?.contentResolver
?.delete(uri, null, null)
}
selectedFile.setOldFileName(selectedFile.getMFile_name()!!)
selectedFile.setOldFileParentFileh(selectedFile.getMParent_file()!!)
selectedFile.setOldFilePath(selectedFile.getMAbsolute_path()!!)
selectedFile.setMAbsolute_path(newFilePath)
selectedFile.setMFile_name(newFileName)
selectedFile.setPosition(positionOfDeleted)
renamedFile.postValue(selectedFile)
if (isFileShortcutCreated) {
createFileShortCut(context, selectedFile, positionOfDeleted)
}
} catch (e: Exception) {
e.printStackTrace()
Toast.makeText(
context,
context?.getString(R.string.text_rename_error),
Toast.LENGTH_SHORT
).show()
}
}
Copy Function
#Throws(IOException::class)
fun copy(src: File?, dst: File?) {
val inStream = FileInputStream(src)
val outStream = FileOutputStream(dst)
val inChannel: FileChannel = inStream.getChannel()
val outChannel: FileChannel = outStream.getChannel()
inChannel.transferTo(0, inChannel.size(), outChannel)
inStream.close()
outStream.close()
}
Function Where I am fetching files from MediaStore
private fun readFiles(
args: Array<String?>,
where: String
): ArrayList<MyFileModel> {
val fetchedFiles = ArrayList<MyFileModel>()
var fileCursorExternal: Cursor? = null
var fileCursorInternal: Cursor? = null
try {
//Tables
val tableExternal = MediaStore.Files.getContentUri("external")
val tableInternal = MediaStore.Files.getContentUri("internal")
//Column
val column = arrayOf(
MediaStore.Files.FileColumns.DATE_ADDED,
MediaStore.MediaColumns.DATA,
MediaStore.MediaColumns.TITLE,
MediaStore.MediaColumns.SIZE,
MediaStore.Files.FileColumns.DATE_MODIFIED
)
//Sort by date
val orderBy = MediaStore.Files.FileColumns.DATE_MODIFIED
fileCursorExternal = context.contentResolver.query(
tableExternal,
column,
where,
args, "$orderBy DESC"
)
while (fileCursorExternal!!.moveToNext()) {
fetchedFiles.add(setMyFileModel(fileCursorExternal))
}
fileCursorInternal = context.contentResolver.query(
tableInternal,
column,
where,
args,
"$orderBy DESC"
)
while (fileCursorInternal!!.moveToNext()) {
fetchedFiles.add(setMyFileModel(fileCursorInternal))
}
} catch (ex: java.lang.Exception) {
ex.printStackTrace()
} finally {
fileCursorExternal?.close()
fileCursorInternal?.close()
}
//fetchedFiles.sortByDescending { it.getMFileDate() } //commented as not working
return fetchedFiles
}
Function Where the data from cursor is converted to MyFileModel class object
private fun setMyFileModel(cursor: Cursor): MyFileModel {
val MyFileModel = MyFileModel()
if (cursor != null) {
try {
MyFileModel.setMFileDate(
getReadableDate(
cursor.getLong(
cursor.getColumnIndexOrThrow(
MediaStore.Files.FileColumns.DATE_MODIFIED
)
)
)
)
MyFileModel.setMAbsolute_path(
cursor.getString(
cursor.getColumnIndexOrThrow(
MediaStore.MediaColumns.DATA
)
)
)
MyFileModel.setMFile_name(
cursor.getString(
cursor.getColumnIndexOrThrow(
MediaStore.MediaColumns.TITLE
)
)
)
MyFileModel.setMFile_size(
getReadableSize(
cursor.getLong(
cursor.getColumnIndexOrThrow(
MediaStore.MediaColumns.SIZE
)
)
)
)
MyFileModel.setFileType(getFileType(MyFileModel.getMAbsolute_path()).name)
if (MyFileModel.getMAbsolute_path() != null) {
val file = File(MyFileModel.getMAbsolute_path())
MyFileModel.setMParent_file(file.parent)
}
} catch (ex: Exception) {
ex.printStackTrace()
}
}
return MyFileModel
}
Function to convert long date to string
private fun getReadableDate(dateVal: Long): String {
try {
var date = dateVal
date *= 1000L
return SimpleDateFormat("dd MMM yyyy").format(Date(date))
} catch (ex: Exception) {
ex.printStackTrace()
}
return ""
}
Required Output
1- On renaming a file, new file should be created old file should be deleted.
2- New file should have timestamp of old file so that sorting is not disturbed.
What can I try to resolve this?
I don't want my app to require any permissions, but I want the user to be able to select a file for reading. My app doesn't need arbitrary access to the filesystem. However, all openfiledialog implementations I have researched so far seem to assume permission to access external storage.
One workaround I can think of is to configure my app to be among the list of apps to open a certain type of file. I haven't tried this, but I hope this would work without permission to access external storage. However, user guidance would be less then ideal in this case. I would prefer a solution with a dialog and have the user pick the file.
I think this requirement does not undermine security, because the user has full control over the file my app can read. Is this possible somehow?
However, all openfiledialog implementations I have researched so far seem to assume permission to access external storage.
Set your minSdkVersion to 19, then use ACTION_OPEN_DOCUMENT, part of the Storage Access Framework.
Or, if you need your minSdKVersion to be below 19, use ACTION_GET_CONTENT on the older devices.
You will get a Uri back via onActivityResult(). Use a ContentResolver and methods like openInputStream() to consume the content identified by that Uri.
I haven't tried this, but I hope this would work without permission to access external storage
Only if you exclude file: Uri values. For example, an <intent-filter> that supports only content: Uri values would work.
Android 11 Resolve file access issue without use of MANAGE_EXTERNAL_STORAGE.
I have added code for get doc file and Upload to server.
AndroidManifest
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
<application
android:preserveLegacyExternalStorage="true"
android:requestLegacyExternalStorage="true"
</application>
Now, Add this lib in your project
https://github.com/FivesoftCode/FilePicker
Add below code to Activity/Fragment
FilePicker.from(activity)
.setFileTypes(FilePicker.IMAGE, FilePicker.VIDEO) //Set file types you want to pick.
.setAllowMultipleFiles(true) //Allow user to select multiple files
.setListener { files -> //Wait for results
if (files != null && files.size > 0) {
//Do something with uris.
for (items in files) {
val extension: String = getMimeType(activity!!,items)!!
if (extension == "pdf") {
val cacheDir: String = context!!.cacheDir.toString()
val getCopyFilePath = copyFileToInternalStorage(context!!,items,cacheDir)
Log.e("TAG", "getPathToUploadDoc: " + getCopyFilePath )
}
}
} else {
//Add msg here...
}
}
.setTitle("Pick a file from My Files")
.pick() //Open file picker
Add below method for get Mime Type
fun getMimeType(context: Context, uri: Uri): String? {
val extension: String?
//Check uri format to avoid null
extension = if (uri.scheme == ContentResolver.SCHEME_CONTENT) {
//If scheme is a content
val mime = MimeTypeMap.getSingleton()
mime.getExtensionFromMimeType(context.contentResolver.getType(uri))
} else {
//If scheme is a File
//This will replace white spaces with %20 and also other special characters. This will avoid returning null values on file name with spaces and special characters.
MimeTypeMap.getFileExtensionFromUrl(Uri.fromFile(File(uri.path)).toString())
}
return extension
}
fun getFiledetails(uri: Uri,context: Context,getCopyFilePath:String): NormalFile? {
// var result: String? = null
if (uri.scheme == "content") {
val cursor: Cursor = context.contentResolver.query(uri,
FileLoader.FILE_PROJECTION, null, null, null)!!
try {
if (cursor != null && cursor.moveToFirst()) {
// result = cursor.getString(cursor.getColumnIndex(OpenableColumns.DISPLAY_NAME))
val path: String = cursor.getString(cursor.getColumnIndexOrThrow(MediaStore.MediaColumns.DATA))
if (path != null && path != "") {
//Create a File instance
cursor.getLong(cursor.getColumnIndexOrThrow(BaseColumns._ID))
// cursor.getLong(cursor.getColumnIndexOrThrow(BaseColumns._ID)).toInt()
cursor.getString(cursor.getColumnIndexOrThrow(MediaStore.MediaColumns.TITLE))
// cursor.getString(cursor.getColumnIndexOrThrow(MediaStore.MediaColumns.DATA))
cursor.getLong(cursor.getColumnIndexOrThrow(MediaStore.MediaColumns.SIZE))
cursor.getLong(cursor.getColumnIndexOrThrow(MediaStore.MediaColumns.DATE_ADDED))
cursor.getString(cursor.getColumnIndexOrThrow(MediaStore.Files.FileColumns.MIME_TYPE))
}
}
} finally {
cursor.close()
}
}
/*if (result == null) {
result = uri.path
val cut = result!!.lastIndexOf('/')
if (cut != -1) {
result = result.substring(cut + 1)
}
}*/
return file
}
fun copyFileToInternalStorage(context: Context?,uri: Uri, newDirName: String): String? {
val returnCursor = context!!.contentResolver.query(
uri, arrayOf(
OpenableColumns.DISPLAY_NAME, OpenableColumns.SIZE
), null, null, null
)
/*
* Get the column indexes of the data in the Cursor,
* * move to the first row in the Cursor, get the data,
* * and display it.
* */
val nameIndex = returnCursor!!.getColumnIndex(OpenableColumns.DISPLAY_NAME)
val sizeIndex = returnCursor.getColumnIndex(OpenableColumns.SIZE)
returnCursor.moveToFirst()
val name = returnCursor.getString(nameIndex)
val size = java.lang.Long.toString(returnCursor.getLong(sizeIndex))
val output: File
output = if (newDirName != "") {
val dir = File(/*context!!.filesDir.toString() + "/" +*/ newDirName)
if (!dir.exists()) {
dir.mkdir()
}
File(/*context!!.filesDir.toString() + "/" +*/ newDirName + "/" + name)
} else {
File(context!!.filesDir.toString() + "/" + name)
}
try {
val inputStream: InputStream? = context!!.contentResolver.openInputStream(uri)
val outputStream = FileOutputStream(output)
var read = 0
val bufferSize = 1024
val buffers = ByteArray(bufferSize)
while (inputStream?.read(buffers).also { read = it!! } != -1) {
outputStream.write(buffers, 0, read)
}
inputStream?.close()
outputStream.close()
} catch (e: Exception) {
Log.e("Exception", e.message!!)
}
return output.path
}
For upload Doc
implementation 'net.gotev:uploadservice:2.1'
var uploadId = UUID.randomUUID().toString()
val url = ServerConfig.MAIN_URL
uploadReceiver.setDelegate(this)
uploadReceiver.setUploadID(uploadId)
val data = MultipartUploadRequest(mContext, uploadId, url)
.addFileToUpload(path, "attachment")
.addHeader("Authentication", getMD5EncryptedString())
.addParameter(USER_ID,1)
.setMaxRetries(5)
.startUpload()
fun getMD5EncryptedString(): String {
val encTarget = ServerConfig.AUTHENTICATE_VALUE //Any pwd
var mdEnc: MessageDigest? = null
try {
mdEnc = MessageDigest.getInstance("MD5")
} catch (e: NoSuchAlgorithmException) {
println("Exception while encrypting to md5")
e.printStackTrace()
}
mdEnc!!.update(encTarget.toByteArray(), 0, encTarget.length)
var md5 = BigInteger(1, mdEnc.digest()).toString(16)
while (md5.length < 32) {
md5 = "0$md5"
}
return md5
}