I am encrypting a file in Node.js client side and saving it on server as file, when I try to decrypt file it is not in the right format.
Encryptor.encryptFile = function (inputPath, outputPath, key, options, callback) {
if (typeof options === 'function') {
callback = options;
options = {};
}
options = Encryptor.combineOptions(options);
var keyBuf = new Buffer(key);
console.log(key)
var inputStream = fs.createReadStream(inputPath);
var outputStream = fs.createWriteStream(outputPath);
var cipher = crypto.createCipher(options.algorithm, keyBuf);
inputStream.on('data', function (data) {
console.log(data.length)
var buf = new Buffer(cipher.update(data));
outputStream.write(buf);
});
inputStream.on('end', function () {
try {
var buf = new Buffer(cipher.final('binary'), 'binary');
outputStream.write(buf);
outputStream.end();
outputStream.on('close', function () {
return callback();
});
} catch (e) {
fs.unlink(outputPath);
return callback(e);
}
});
};
Above is the encryption code, and on Android side I use the following code.
FIle Downloading:
Ion.with(this).load(documentModel.filePath)
.progress { downloaded, total -> println("$downloaded / $total") }
.write(file)
.setCallback { e, result ->
if (result != null) {
// val keys = MedpayDatabaseHelper.getInstance(this#ViewMedicalRecordActivity)?.keyDao()?.getKeys()
val handler = EncryptionHandler()
val decrepted = handler.decryptFile(handler.getSymmetricKey(), result)
val outfile = File(dir, "output.pdf")
pdfView.fromBytes(decrepted).load()
} else {
Toast.makeText(this#ViewMedicalRecordActivity, "Failed to load file", Toast.LENGTH_LONG).show()
}
}
Following is the decryption code.
fun decryptFile(symmetricKey: String, file: File): ByteArray {
encryptionAlgorithm = "AES"
encryptionMode = "/ECB"
paddingMode = "/NoPadding"
return decrypt(symmetricKey, file)
}
private fun decrypt(decryptionKey: String, file: File): ByteArray {
val inputStream = BufferedReader(InputStreamReader(FileInputStream(file), Charsets.UTF_16BE))
var x: String? = ""
var builder = StringBuilder()
while (x != null) {
x = inputStream.readLine()
if (x != null)
builder.append(x).append('\n')
}
val text = builder.toString()
val read = text.toByteArray().decrypt(decryptionKey)
val path = Environment.getExternalStorageDirectory().absolutePath + "/folder"
val dir = File(path)
if (!dir.exists())
dir.mkdirs()
val outfile = File(dir, "output.pdf")
val dos = OutputStreamWriter(FileOutputStream(outfile))
dos.write(read.toString(Charsets.UTF_16LE))
dos.flush()
dos.close()
return read
}
//extension function for decrypting the byte array
private fun ByteArray.decrypt(decryptionKey: String): ByteArray {
val secretKeySpec = SecretKeySpec(decryptionKey.toByteArray(), encryptionAlgorithm)
val cipher = Cipher.getInstance(encryptionAlgorithm + encryptionMode + paddingMode)
cipher.init(Cipher.DECRYPT_MODE, secretKeySpec)
return cipher.doFinal(this)
}
As I am new in cryptography I am not really sure where i am going wrong but i think it has something to do with file formats and encoding.
The files get decrypted without any errors but still the following exception is thrown when i try to open file in code or from the file explorer.
E/PDFView: load pdf error
java.io.IOException: cannot create document: File not in PDF format or corrupted.
at com.shockwave.pdfium.PdfiumCore.nativeOpenMemDocument(Native Method)
Related
I cannot open the pdf file I downloaded from the internet on my android device.
It gives the error that the file is corrupt. (corrupt file opens in pc)
//Request;
#GET("url")
suspend fun getDocumentDownload(#Path("File") file: String?): Response<ResponseBody>
//writeResponseBodyToDisk
var inputStream: InputStream? = null
var outputStream: OutputStream? = null
val byteArray = ByteArray(4096)
val fileSize = body.contentLength()
var fileSizeDownloaded: Long = 0
inputStream = body.byteStream()
outputStream = FileOutputStream(file)
while (true) {
val read = inputStream.read(byteArray)
if (read == -1) {
break
}
outputStream.write(byteArray, 0, read)
fileSizeDownloaded += read.toLong()
}
outputStream.flush()
Response corrupt;
Response success;
I need to upload image to my Graphql server from android application. The details in the documentation is not working. I need an example.
Came up with the solution. 1st I needed to create an upload scalar type. in Fragment class:
requireContext().contentResolver.openFileDescriptor(
selectedImageUri!!,
"r",
null
) ?: return
val file = File(
requireContext().cacheDir, requireContext().contentResolver.getFileName(
selectedImageUri
)
)
val body = UploadRequestBody(file, "image")
val upload = DefaultUpload.Builder()
.content(file)
.fileName(file.name)
.contentType(body.contentType().toString())
.build()
In case what the UploadRequestBody class does:
class UploadRequestBody(
private val file: File,
private val contentType: String
) : RequestBody() {
override fun contentType() = "$contentType/*".toMediaTypeOrNull()
override fun contentLength() = file.length()
override fun writeTo(sink: BufferedSink) {
val length = file.length()
val buffer = ByteArray(DEFAULT_BUFFER_SIZE)
val fileInputStream = FileInputStream(file)
var uploaded = 0L
fileInputStream.use { inputStream ->
var read: Int
while (inputStream.read(buffer).also { read = it } != -1) {
uploaded += read
sink.write(buffer, 0, read)
}
}
}
companion object {
private const val DEFAULT_BUFFER_SIZE = 2048
}
}
I'm using below code for downloading the image and it download successfully but not showing in galary please help!!!
I have tried couple of examples none of them are working..
I have also tried the MediaScanner to scan the file and update the gallery
If anyone have links related this question please share
class DownloadFileFromURL : AsyncTask<Void, Void, Void>() {
override fun doInBackground(vararg params: Void): Void? {
var count: Int
try {
val url = URL(getUrl())
val conection: URLConnection = url.openConnection()
conection.connect()
// input stream to read file - with 8k buffer
val input: InputStream = BufferedInputStream(url.openStream(), 8192)
val output: OutputStream?
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) {
val resolver: ContentResolver = activity?.contentResolver!!
val contentValues = ContentValues()
val name = System.currentTimeMillis()
contentValues.put(MediaStore.MediaColumns.DISPLAY_NAME, "$name.jpg")
contentValues.put(MediaStore.MediaColumns.MIME_TYPE, "image/jpg")
contentValues.put(MediaStore.MediaColumns.RELATIVE_PATH, Environment.DIRECTORY_PICTURES)
val imageUri: Uri? = resolver.insert(MediaStore.Images.Media.EXTERNAL_CONTENT_URI, contentValues)
output = imageUri?.let { resolver.openOutputStream(it) }!!
} else {
val imgFile = createImageFile()
if (!imgFile.exists()) {
imgFile.createNewFile()
}
output = FileOutputStream(imgFile)
}
// Output stream to write file
val data = ByteArray(1024)
var total: Long = 0
while (input.read(data).also { count = it } != -1) {
total += count.toLong()
// writing data to file
output.write(data, 0, count)
}
// flushing output
output.flush()
// closing streams
output.close()
input.close()
} catch (e: Exception) {
Log.e("Error: ", e.message)
}
return null
}
override fun onPostExecute(result: Void?) {
downloadComplete()
}
#Throws(IOException::class)
private fun createImageFile(): File {
// Create an image file name
val timeStamp: String = SimpleDateFormat("yyyyMMdd_HHmmss", Locale.US).format(Date())
val storageDir: File = activity?.getExternalFilesDir(Environment.DIRECTORY_PICTURES)!!
return File(
storageDir, /* directory */
"JPEG_${timeStamp}"+ /* prefix */
".jpg" /* suffix */
).apply {
// Save a file: path for use with ACTION_VIEW intents
mCurrentPhotoPath = absolutePath
}
}
}
What I am doing: I am using a connection to download file from server and write into a storage
What is happening: Code is working
What I am trying to do: How to achieve the same using okhttp
try {
val url = URL(DICTIONARY_FILE_URL)
val conection = url.openConnection()
conection.connect()
// getting file length
// input stream to read file - with 8k buffer
val input = BufferedInputStream(url.openStream(), 8192)
// Output stream to write file
val directoryPathName = Environment.getExternalStorageDirectory().absolutePath.plus("/CNX/dictionary/")
val dictionaryFileName = "DictionaryEN.quickdic"
var f = File(directoryPathName)
if(!f.isDirectory) {
f.mkdirs()
}
val output = FileOutputStream(directoryPathName.plus(dictionaryFileName))
val data = ByteArray(1024)
var count: Int? = 0
while ({ count = input.read(data);count }() != -1) {
output.write(data, 0, count!!)
}
// flushing output
output.flush()
// closing streams
output.close()
input.close()
isJobSuccess = true
//sharedPreferences[IS_DICTIONARY_DOWNLOADED] = true
} catch (e: Exception) {
Log.e("Exception",e.message)
isJobSuccess = false
//sharedPreferences[IS_DICTIONARY_DOWNLOADED] = false
}
Sample for Downloading a file with OkHttp asynchronously
fun downloadFileAsync(downloadUrl: String) {
val client = OkHttpClient();
val request = Request.Builder().url(downloadUrl).build();
client.newCall(request).enqueue(object : Callback {
override fun onFailure(call: Call, e: IOException) {
Log.e("fail", e.printStackTrace().toString())
}
override fun onResponse(call: Call, response: Response) {
if (!response.isSuccessful) {
Log.e("fail", "Download error")
}else{
// Output stream to write file
val directoryPathName = Environment.getExternalStorageDirectory().absolutePath.plus("/CNX/dictionary/")
val dictionaryFileName = "DictionaryEN.quickdic"
val f = File(directoryPathName)
if(!f.isDirectory) {
f.mkdirs()
}
val output = FileOutputStream(directoryPathName.plus(dictionaryFileName))
response.body?.let {
output.write(it.bytes())
}
// flushing output
output.flush()
// closing streams
output.close()
}
}
})
}
Sample for Downloading a file with OkHttp synchronously
fun downloadFileSync(downloadUrl: String) {
val client = OkHttpClient();
val request = Request.Builder().url(downloadUrl).build();
val response = client.newCall (request).execute();
if (!response.isSuccessful) {
Log.e("fail", "Failed to download file: " + response)
}else {
val directoryPathName = Environment.getExternalStorageDirectory().absolutePath.plus("/CNX/dictionary/")
val dictionaryFileName = "DictionaryEN.quickdic"
val f = File(directoryPathName)
if (!f.isDirectory) {
f.mkdirs()
}
val output = FileOutputStream(directoryPathName.plus(dictionaryFileName))
response.body?.let {
output.write(it.bytes())
}
// flushing output
output.flush()
// closing streams
output.close()
}
}
build.gradle
implementation("com.squareup.okhttp3:okhttp:4.5.0")
I'm using Storage Access Network to pick file and save in internal storage so that app can use if in future.
I'm getting URI without any issues. It's something like content://com.android.providers.media.documents/document/image%3A141274
Problem comes when I'm trying to save image into internal directory. Code passes without crashes, image with same size is saved into internal directory (I can see it in device Explorer: https://take.ms/3TwBS).
But image itself is broken and can't be opened.
Here's code I'm using (after getting URI)
val destinationFile = File("${context.filesDir.absolutePath}/$fileName")
try {
val writer = FileWriter(destinationFile)
writer.append(readTextFromUri(it))
writer.flush()
writer.close()
} catch (e: Exception) {
e.printStackTrace()
}
#Throws(IOException::class)
private fun readTextFromUri(uri: Uri): String {
val inputStream = activity!!.contentResolver.openInputStream(uri)
val reader = BufferedReader(InputStreamReader(inputStream))
val stringBuilder = StringBuilder()
var line: String? = null
while ({ line = reader.readLine(); line }() != null) {
stringBuilder.append(line)
}
inputStream?.close()
reader.close()
return stringBuilder.toString()
}
As #CommonsWare described I should have used proper dealing with files, not texts.
Proper way to do:
private fun inputStreamToFile(uri: Uri){
val inputStream = contentResolver.openInputStream(uri)
val output = FileOutputStream(File("${filesDir.absoluteFile}/magic.png"))
inputStream?.copyTo(output, 4 * 1024)
}
Or longer way (without extension functions)
fun inputStreamToFile(uri: Uri){
val inputStream = contentResolver.openInputStream(uri)
inputStream.use {
val directory = getDir("test", Context.MODE_PRIVATE)
val file = File(directory, "correct.txt")
val output = FileOutputStream(file)
output.use {
val buffer = ByteArray(4 * 1024) // or other buffer size
var read: Int = inputStream?.read(buffer) ?: -1
while (read != -1) {
output.write(buffer, 0, read)
read = inputStream?.read(buffer) ?: -1
}
output.flush()
}
}
}