How to get proper filepath from FileResult fileData = await FilePicker.PickAsync();? - xamarin

I am using FileResult fileData = await FilePicker.PickAsync();
for picking file in xamarin forms app.
But fileData.FullPath is not correct, Can anyone help me for getting proper filePath?

Related

Xamarin.Essentials; FilePicker; Save a new file

Using FilePicker one can open an existing file:
FileResult file = await FilePicker.PickAsync();
TextView textview = FindViewById<TextView>(Resource.Id.textview);
string path = file.FullPath;
var handle = File.Open(path, FileMode.OpenOrCreate);
byte[] data = new byte[10];
handle.Read(data, 0, 10);
Is there a similar way for saving a new file?
For now, the FilePicker plugin is only designed to pick existing files.
On Android and iOS, you could not do that. But on UWP, you could use the FileSavePicker.
Xamarin: https://learn.microsoft.com/en-us/xamarin/essentials/file-picker?tabs=android
UWP: https://learn.microsoft.com/en-us/windows/uwp/files/quickstart-save-a-file-with-a-picker

How to save images from assets to the internal storage in flutter?

I am trying to save the image from assets to internal storage. But, I could not load the image from assets to file. Here is what I have done:
onTap: () async {
final String documentPath = (await getApplicationDocumentsDirectory()).path;
String imgPath = (galleryItems[currentIndex].assetName).substring(7);
File image = await getImageFileFromAssets(imgPath);
print(image.path);
}
I used substring(7) to eliminate assets/ as, my assetName comes as assets/images/foo.jpg.
Future<File> getImageFileFromAssets(String path) async {
final byteData = await rootBundle.load('assets/$path');
final file =
await File('${(await getApplicationDocumentsDirectory()).path}/$path')
.create(recursive: true);
await file.writeAsBytes(byteData.buffer
.asUint8List(byteData.offsetInBytes, byteData.lengthInBytes));
return file;
}
After I get image, I don't know how to proceed forward to create a directory with my name in internal storage. And, copy file there.
*Note:- I have editted the post, as some basic mistakes were pointed out.
Update
Here is what I came up with. And it saves image in the /storage/emulated/0/Android/data/com.example.my_project/files/Pics/foo.jpg path.
File image = await getImageFileFromAssets(imgPath);
final extDir = await getExternalStorageDirectory();
// Path of file
final myImagePath = '${extDir.path}/Pics';
// Create directory inside where file will be saved
await new Directory(myImagePath).create();
// File copied to ext directory.
File newImage =
await image.copy("$myImagePath/${basename(imgPath)}");
print(newImage.path);
Here are some links that really helped me:
Flutter How to save Image file to new folder in gallery?
How to Save Image File in Flutter ? File selected using Image_picker plugin
How to convert asset image to File?
Special thanks to #David for the help. Please see comments to understand full scene if you are here to solve your similar problem.
So, I am accepting the answer from #David.
You are trying to create a file object in a path that doesn't exist. You're using your asset path, the path relative to the root of your Flutter project. However, this path doesn't exist in the device's documents folder, so the file can't be created there. The file also doesn't exist in the assets folder because you're prepending the documents path.
To fix your issue, you should pass assetName to rootBundle.load(), without the documents path and open the File() somewhere like $documentPath/foo.jpg
Edit:
To create the file you still have to call File.create, so you need to run:
final file = await File('$documentPath/images/foo.jpg').create(recursive: true);
For future reference, this is just to update the solution of #Biplove which really helped me a lot as a newbie...
Future<File> getImageFileFromAssets(String unique, String filename) async {
ByteData byteData = await rootBundle.load(assets/filename));
// this creates the file image
File file = await File('$imagesAppDirectory/$filename').create(recursive: true);
// copies data byte by byte
await file.writeAsBytes(byteData.buffer.asUint8List(byteData.offsetInBytes, byteData.lengthInBytes));
return file;
}
Thanks.

how to convert image to byte and again convert it to image in flutter?

I am trying to use the image_picker plugin. I can get the image as file using this plugin. I need to convert this image to bytes and send to a api. So I tried to use dart:convert to convert the image to byte string. Now when I decode I am getting a Uint8List type. How to convert this to a file and display in a Image.file(). I couldn’t proceed from here. Can someone help me with this.
consider i am getting this decodedBytes i am getting from a api response, how can i convert them to display in a Image widget
This is the code I tried so far.
var image = await ImagePicker.pickImage(source: ImageSource.camera);
setState(() {
imageURI = image;
final bytes = image.readAsBytesSync();
String img64 = base64Encode(bytes);
print(bytes);
print(img64);
final decodedBytes = base64Decode(img64);
print(decodedBytes);
//consider i am getting this decodedBytes i am getting from a api response, how can i convert them to display in a Image widget
});
I am getting this error using writeAsBytesSync(),
Unhandled Exception: FileSystemException: Cannot open file, path = 'decodedimg.png'
You get this error, because you can't write to any arbitrary location in an application sandbox. You can use path_provider to look up a temporary directory.
But in your case, just use the image object, pickImage already returns a File object, so just use Image.file(image)
If you want to decode a base64 into a temporary directory you can use:
import 'package:path_provider/path_provider.dart';
import 'package:path/path.dart' as path;
Future<File> writeImageTemp(String base64Image, String imageName) async {
final dir = await getTemporaryDirectory();
await dir.create(recursive: true);
final tempFile = File(path.join(dir.path, imageName));
await tempFile.writeAsBytes(base64.decode(base64Image));
return tempFile;
}
with pubspec.yaml:
dependencies:
path: ^1.6.0
path_provider: ^1.6.7

How to resolve StatusCode: 415, ReasonPhrase: 'Unsupported Media Type'?

How do you post a file with HttpClient?
It can't be that hard, can it?
I am posting a file from a Windows forms client to an ASP.Net Core 2.2 website API (not WebApi)
The file could be anything, word, pdf, image, video etc...
The file could be anything up to 500MB and my JSON methods won't send anything above 25MB
No matter what I do I keep getting
StatusCode: 415, ReasonPhrase: 'Unsupported Media Type'
I can't work out what's gong wrong I have no idea what's missing. I've narrowed it down to this
string filepath = file;
string filename = Path.GetFileName(file);
MultipartFormDataContent content = new MultipartFormDataContent();
var fileContent = new StreamContent(File.OpenRead(filepath));
fileContent.Headers.ContentDisposition = new ContentDispositionHeaderValue("form-data") { FileName = $"\"{filename}\"" };
content.Add(fileContent);
HttpResponseMessage response = await _httpClient.PostAsync(serviceMethod, content);
All the examples I've read (loads of them), most seem to be sensing JSON and I can do that in spades. The rest tell you what to read and look for but I'm still lost I just want to post a file. I have the server code ready to go.
[HttpPost]
public async Task<JsonResult> UploadFile([FromForm]IFormFile result)
I'll keep reading but any help would be much appreciated.
Ok, I got a bit closer. I've updated my code (see above) and now the controller on my API is getting invoked but now result is null
Try to change your code as shown:
public async Task<IActionResult> PostFile()
{
string filepath =file;
string filename = Path.GetFileName(file);
MultipartFormDataContent content = new MultipartFormDataContent();
var fileContent = new StreamContent(System.IO.File.OpenRead(filepath));
content.Add(fileContent, "result", filename);
HttpResponseMessage response = await _httpClient.PostAsync(serviceMethod, content);
}
[HttpPost]
public async Task<JsonResult> UploadFile(IFormFile result)
Result

Downloading a file from Azure Storage to client using Angular2 with .NET Web Api 2

I am trying to download a 1GB file from blob storage into the client. I used before Memory Stream and I get OutOfMemory exception.
now I am trying to open a read stream from the blob and send it directly to the client.
[HttpGet]
[ResponseType(typeof(HttpResponseMessage))]
public async Task<HttpResponseMessage> DownloadAsync(string file)
{
HttpResponseMessage result = new HttpResponseMessage(HttpStatusCode.OK);
var stream = await blob.OpenReadAsync("container", file);
result.Content = new StreamContent(stream);
return result;
}
The file is downloaded correctly, but the problem is: The code download the complete stream in the client, then the client sees the downloaded file.
I wanted the client to see the file as being downloaded, so the user knows that he is downloading something. Not just blocking the request and wait till it finished.
I am using FileSaver in Angular2:
this.controller.download('data.zip').subscribe(
data => {
FileSaver.saveAs(data, 'data.zip');
});
Has anybody an idea how to fix it?
Thank you!
To fix it you'd need to use the following javascript code instead:
var fileUri = "http://localhost:56676/api/blobfile"; //replace with your web api endpoint
var link = document.createElement('a');
document.body.appendChild(link);
link.href = fileUri;
link.click();
And then in your backend, make it like so:
HttpResponseMessage result = new HttpResponseMessage(HttpStatusCode.OK);
var stream = await blob.OpenReadAsync("container", file);
result.Content = new StreamContent(stream);
result.Content.Headers.ContentDisposition = new ContentDispositionHeaderValue("attachment")
{
FileName = "data.zip"
};
result.Content.Headers.ContentType = new MediaTypeHeaderValue("application/octet-stream");
return result;
I had the same problem.
The Solution I sorted out was -
First thing, the expected behaviour can occur only when client tries to download the file from blob and usually I prefer downloading the file from the client itself.
As in your case, try to get file blob uri and do some operations as below to open file in browser using Angular Router or simply window.location.href.
window.location.href = “https://*/filename.xlsx”
This worked for me.

Resources