Trying to create File from URI fails Kotlin - kotlin

I am trying to create a File using the URI from ActivityResultContracts like this:
val galleryLauncher = rememberLauncherForActivityResult(ActivityResultContracts.GetContent()) { uri ->
val myFile = uri?.toFile()
The file is a jpeg image. I have got this error: Uri lacks 'file' scheme: content://com.android.providers.media.documents/document/image%3A1000000001

Related

How can ı upload file or image using retrofit on kotlin?

ı dont know how to upload file or image etc. using retrofit multipart. Can anyone help me ?strong text
First, you have to create API Interface like this with #Multipart annotation:
#Multipart
#POST(Constants.API_LINK)
fun createProfile(
#Part("name") name: RequestBody,
#Part("email") email: RequestBody,
#Part image: MultipartBody.Part?
): Call<CreateProfileResponse>
Now, choose the image using MediaStore, get it's URI Path and use that to make a MultipartBody.Part object of that image like this:
val mediaType: String = "image/png"
val fileName: String = "photo_" + System.currentTimeMillis() + ".png"
val file: File = File(uriPath!!)
val reqFile = file.asRequestBody(mediaType.toMediaTypeOrNull())
profilePic = MultipartBody.Part.createFormData("file", fileName, reqFile)
Now just call the API using retrofit and pass this profilePic object in the respective parameter.
For more info about structuring your Retrofit and calling APIs, you can refer to my previous detailed answer here Retrofit calling APIs

Parsing pdf with Kotlin using a Uri?

I write Kotlin code in Android Studio. The user chooses a file from the phone (I need to access the content as a string). There I get a Uri?. With that Uri? I can extract text from .csv and .txt files:
if (typeOfFile == ".txt" || typeOfFile == ".csv") {
try {
val ins: InputStream? = contentResolver?.openInputStream(uriFromSelectedFile)
val reader = BufferedReader(ins!!.reader())
textIWant = reader.readText()
...
Getting the file type also works fine, but when it comes to opening pdf files, nothing seems to work. I tried using PDFBox from Apache in various ways. The pdf I try to open is a simple onePager and contains only extractable text (can be copied) like this pdf.
This is one of the things I tried, the phone freezes when the file to open is a pdf:
if (typeOfFile == ".pdf") {
try {
val myPDDocument:PDDocument = PDDocument(COSDocument(ScratchFile(File(uriFromSelectedFile.path))))
textIWant = PDFTextStripper().getText(myPDDocument)
...
I´ve been trying for days. Does anyone know, how it works in Kotlin?
It worked using tom_roush.pdfbox and a companion object:
import com.tom_roush.pdfbox.text.PDFTextStripper
class MainActivity : AppCompatActivity() {
companion object PdfParser {
fun parse(fis: InputStream): String {
var content = ""
com.tom_roush.pdfbox.pdmodel.PDDocument.load(fis).use { pdfDocument ->
if (!pdfDocument.isEncrypted) {
content = PDFTextStripper().getText(pdfDocument)
}
}
return content
}
}
Calling the parse function of the companion object:
val fis: InputStream = contentResolver?.openInputStream(uriFromSelectedFile)!!
textIWant = parse(fis)

How can I access a file on my local drive?

In Elm, how can I access a file on my local drive?
For example, I need to access the file:
c:\MyFolder\somefile.txt
(I'm assuming you're targeting the browser and not Node. If you want Node support, here is the documentation for it's fs module. The high-level usage will be similar to what I'm describing below for browsers.)
There is not (yet) an Elm-only API for this, so you'll have to use ports. This article is very helpful, I will adapt its example.
In short, you have to use File and FileReader API (caniuse.com), and on load of the file send the data to Elm through port. (In my example below, Elm will get a GetFile {name : String, content : String} message for every file submitted.) Here is a working example in Ellie.
Msg:
type Msg
= GetFile File
type alias File =
{ name : String
, content : String
}
Port:
port getFile : (File -> msg) -> Sub msg
(don't forget port module instead of module on top of the Elm source)
Subscription:
subscriptions : Model -> Sub Msg
subscriptions model =
getFile GetFile
HTML file input:
<input type="file" id="files" name="files[]" multiple />
JS (the main part!):
<script>
var app = Elm.Main.fullscreen();
function handleFileSelect(evt) {
var files = evt.target.files;
for (var i = 0, f; f = files[i]; i++) {
if (!f.type.match('image.*')) {
continue;
}
var reader = new FileReader();
reader.onload = (function(theFile) {
return function(e) {
app.ports.getFile.send({name: theFile.name, content: e.target.result});
};
})(f);
reader.readAsDataURL(f);
}
}
document.getElementById('files').addEventListener('change', handleFileSelect, false);
</script>
EDIT: this example only accepts images. If you don't want that, remove the
if (!f.type.match('image.*')) {
continue;
}
part and do something different in the viewFile function (ie. don't try to interpret the content data as an image src).
Elm is now able open files as of 0.19.
Steps are as follows:
Attach an event handler to a button that sends the appropriate message to the update function.
Update function receives message and runs the file-opening function, which tells Elm runtime to ask browsers to open a file selection dialogue.
Once user action has completed, Elm runtime returns a data of type File to the update function, and the update function can decide what to do.
To read file's content, a file-reading function has to be invoked. Again, the function tells the Elm runtime to read the content of the file. The runtime again invokes your update function, this time passing the content of the file.
Please refer to this thread on Elm discourse, which includes this example on Ellie app

Get the uploaded file name in play framework 2.5

I'm creating an image upload API that takes files with POST requests. Here's the code:
def upload = Action(parse.temporaryFile) { request =>
val file = request.body.file
Ok(file.getName + " is uploaded!")
}
The file.getName returns something like: requestBody4386210151720036351asTemporaryFile
The question is how I could get the original filename instead of this temporary name? I checked the headers. There is nothing in it. I guess I could ask the client to pass the filename in the header. But should the original filename be included somewhere in the request?
All the parse.temporaryFile body parser does is store the raw bytes from the body as a local temporary file on the server. This has no semantics in terms of "file upload" as its normally understood. For that, you need to either ensure that all the other info is sent as query params, or (more typically) handle a multipart/form-data request, which is the standard way browsers send files (along with other form data).
For this, you can use the parse.multipartFormData body parser like so, assuming the form was submitted with a file field with name "image":
def upload = Action(parse.multipartFormData) { request =>
request.body.file("image").map { file =>
Ok(s"File uploaded: ${file.filename}")
}.getOrElse {
BadRequest("File is missing")
}
}
Relevant documentation.
It is not sent by default. You will need to send it specifically from the browser. For example, for an input tag, the files property will contain an array of the selected files, files[0].name containing the name of the first (or only) file. (I see there are possibly other properties besides name but they may differ per browser and I haven't played with them.) Use a change event to store the filename somewhere so that your controller can retrieve it. For example I have some jquery coffeescript like
$("#imageFile").change ->
fileName=$("#imageFile").val()
$("#imageName").val(fileName)
The value property also contains a version of the file name, but including the path (which is supposed to be something like "C:\fakepath" for security reasons, unless the site is a "trusted" site afaik.)
(More info and examples abound, W3 Schools, SO: Get Filename with JQuery, SO: Resolve path name and SO: Pass filename for example.)
As an example, this will print the original filename to the console and return it in the view.
def upload = Action(parse.multipartFormData(handleFilePartAsFile)) { implicit request =>
val fileOption = request.body.file("filename").map {
case FilePart(key, filename, contentType, file) =>
print(filename)
filename
}
Ok(s"filename = ${fileOption}")
}
/**
* Type of multipart file handler to be used by body parser
*/
type FilePartHandler[A] = FileInfo => Accumulator[ByteString, FilePart[A]]
/**
* A FilePartHandler which returns a File, rather than Play's TemporaryFile class.
*/
private def handleFilePartAsFile: FilePartHandler[File] = {
case FileInfo(partName, filename, contentType) =>
val attr = PosixFilePermissions.asFileAttribute(util.EnumSet.of(OWNER_READ, OWNER_WRITE))
val path: Path = Files.createTempFile("multipartBody", "tempFile", attr)
val file = path.toFile
val fileSink: Sink[ByteString, Future[IOResult]] = FileIO.toPath(file.toPath())
val accumulator: Accumulator[ByteString, IOResult] = Accumulator(fileSink)
accumulator.map {
case IOResult(count, status) =>
FilePart(partName, filename, contentType, file)
} (play.api.libs.concurrent.Execution.defaultContext)
}

Cannot get file name when upload file in google app script

I want to get file name when upload file finish. I have this example and follow this code.
However, when I get file name from following code:
var fileBlob = e.parameter.thefile;
The result is always return string "FileUpload".
How can I get the file name? Thank you so much.
You can get the name of the file by using the following code.
var fileBlob = e.parameter.thefile;
fileBlob.getName();
You can get the name of the file without storing in Drive through this.
Since fileBlob is of type blob we are getting through e.parameter.name, we have to refer Class Blob for that.
For further methods supported by Class Blob refer to
Class Blob.
The example script you were following produces a DocsList File object. This object has a method getName() so to extend the function in the example…
function doPost(e) {
// data returned is a blob for FileUpload widget
var fileBlob = e.parameter.thefile;
var doc = DocsList.createFile(fileBlob);
var fileName = doc.getName();
}
give that a whirl.