Unable to add pdf and doc files using Recent files using Xamarin.Plugin.Filepicker - xaml

When I attach pdf and doc files using Recent files I'm getting the following exception. Can anyone help on this.
Working fine when i attach image file using Recent files
please help on this I m new to this Xamarin forms.
Thanks in advance.
at Java.Interop.JniEnvironment+InstanceMethods.CallNonvirtualObjectMethod (Java.Interop.JniObjectReference instance, Java.Interop.JniObjectReference type, Java.Interop.JniMethodInfo method, Java.Interop.JniArgumentValue* args) [0x0008e] in <bd6bd528a8784b7caf03e9f25c9f0d7b>:0
at Java.Interop.JniPeerMembers+JniInstanceMethods.InvokeNonvirtualObjectMethod (System.String encodedMember, Java.Interop.IJavaPeerable self, Java.Interop.JniArgumentValue* parameters) [0x0001f] in <bd6bd528a8784b7caf03e9f25c9f0d7b>:0
at Android.Content.ContentResolver.Query (Android.Net.Uri uri, System.String[] projection, System.String selection, System.String[] selectionArgs, System.String sortOrder) [0x000a0] in /Users/builder/azdo/_work/1/s/xamarin-android/src/Mono.Android/obj/Release/monoandroid10/android-28/mcw/Android.Content.ContentResolver.cs:1098
at Plugin.FilePicker.IOUtil.GetDataColumn (Android.Content.Context context, Android.Net.Uri uri, System.String selection, System.String[] selectionArgs) [0x00013] in D:\a\1\s\src\Plugin.FilePicker\Android\IOUtil.android.cs:154
at Plugin.FilePicker.IOUtil.GetPath (Android.Content.Context context, Android.Net.Uri uri) [0x0017d] in D:\a\1\s\src\Plugin.FilePicker\Android\IOUtil.android.cs:111
at Plugin.FilePicker.FilePickerActivity.OnActivityResult (System.Int32 request Code, Android.App.Result resultCode, Android.Content.Intent data) [0x00054] in D:\a\1\s\src\Plugin.FilePicker\Android\FilePickerActivity.android.cs:168
--- End of stack trace from previous location where exception was thrown ---
at Plugin.FilePicker.FilePickerImplementation.PickFile (System.String[] allowedTypes) [0x00028] in D:\a\1\s\src\Plugin.FilePicker\Android\FilePickerImplementation.android.cs:60
at FileUploadPOC.MainPage.PickAndShow (System.String[] fileTypes) [0x0002e] in C:\Users\Gadda.Raju\Downloads\XamarinForms-FilePicker-master\FileUploadPOC\MainPage.xaml.cs:47
--- End of managed Java.Lang.NullPointerException stack trace ---
java.lang.NullPointerException: uri
at java.util.Objects.requireNonNull(Objects.java:245)
at android.content.ContentResolver.query(ContentResolver.java:1166)
at android.content.ContentResolver.query(ContentResolver.java:1124)
at android.content.ContentResolver.query(ContentResolver.java:1080)
at crc64424a8adc5a1fbe28.FilePickerActivity.n_onActivityResult(Native Method)
at crc64424a8adc5a1fbe28.FilePickerActivity.onActivityResult(FilePickerActivity.java:47)
at android.app.Activity.dispatchActivityResult(Activity.java:8469)
at android.app.ActivityThread.deliverResults(ActivityThread.java:5364)
at android.app.ActivityThread.handleSendResult(ActivityThread.java:5412)
at android.app.servertransaction.ActivityResultItem.execute(ActivityResultItem.java:51)
at android.app.servertransaction.TransactionExecutor.executeCallbacks(TransactionExecutor.java:135)
at android.app.servertransaction.TransactionExecutor.execute(TransactionExecutor.java:95)
at android.app.ActivityThread$H.handleMessage(ActivityThread.java:2317)
at android.os.Handler.dispatchMessage(Handler.java:106)
at android.os.Looper.loop(Looper.java:255)
at android.app.ActivityThread.main(ActivityThread.java:8192)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:632)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1049)
} ```
**The following code im using**
``` private async Task PickAndShow(string[] fileTypes)
{
try
{
var pickedFile = await CrossFilePicker.Current.PickFile(fileTypes);
if (pickedFile != null)
{
lblName.Text = pickedFile.FileName;
lblFilePath.Text = pickedFile.FilePath;
}
}
catch (Exception ex)
{
}
} ```

Yes, from Xamarin.Plugin.FilePicker,we know that :
This package has been deprecated as it is legacy and is no longer
maintained.
Just as SushiHangover said, you can use Xamarin.Essentials: File Picker to achieve this.
The FilePicker class lets a user pick a single or multiple files from the device.
FilePicker.PickAsync() method enables your user to pick a file from the device. You are able to specific different PickOptions when calling the method enabling you to specify the title to display and the file types the user is allowed to pick. By default.
You can refer to the following sample code:
async Task<FileResult> PickAndShow(PickOptions options)
{
try
{
var result = await FilePicker.PickAsync(options);
if (result != null)
{
Text = $"File Name: {result.FileName}";
if (result.FileName.EndsWith("jpg", StringComparison.OrdinalIgnoreCase) ||
result.FileName.EndsWith("png", StringComparison.OrdinalIgnoreCase))
{
var stream = await result.OpenReadAsync();
Image = ImageSource.FromStream(() => stream);
}
}
return result;
}
catch (Exception ex)
{
// The user canceled or something went wrong
}
return null;
}
Default file types are provided with FilePickerFileType.Images, FilePickerFileType.Png, and FilePickerFilerType.Videos. You can specify custom files types when creating the PickOptions and they can be customized per platform.
For more,check:https://learn.microsoft.com/en-us/xamarin/essentials/file-picker?context=xamarin%2Fxamarin-forms&tabs=android .
Update:
For how to open an existing file, you can refer: Xamarin.Essentials; FilePicker; Save a new file .

Related

How to get details about an error from RequestFailedException

I am trying to port code that had been using Microsoft.WindowsAzure.Storage classes to use the newer classes in Azure.Data.Tables, Azure.Storage.Queues, etc. From what I have been able to discern, the StorageException class has been replaced by RequestFailedException. Unfortunately, there are some properties in StorageException that do not exist in RequestFailedException, making it difficult to log appropriate messages when an exception is encountered (for example: RequestId, RequestInformation, etc.).
The migration document does not address the differences between StorageException and the new RequestFailedException, or how to get error details from it.
It seems that either the new libraries are not yet mature enough for prime time, or maybe it is just because the documentation is lacking the relevant information and I can't find the appropriate methodologies for getting all of the error information from the RequestFailedException.
Does anyone know how to get more data out of the new class? Here are some examples of what we used to do:
catch (StorageException e)
{
operation.Telemetry.Properties.Add("AzureServiceRequestID", e.RequestInformation.ServiceRequestID);
Changing the above to use RequestFailedException is a problem because RequestInformation is not a property of RequestFailedException.
Here is another case:
catch (StorageException se)
{
var ri = se.RequestInformation;
if (ri.ErrorCode == "TableNotFound")
{
Logger.Info(
$"{SJResult.MakeInfo(64)} {ri.HttpStatusCode} {ri.HttpStatusMessage}, Storage Service code={ri.ErrorCode} This is OK if HL7 has not yet received messages."); // 60240040
}
else
{
Logger.Error(
$"{SJResult.MakeError(65)} HttpStatusCode: {ri.HttpStatusCode}, HttpStatusMessage: {ri.HttpStatusMessage}, Storage Service code={ri.ErrorCode}, " +
$"Extended.ErrorCode: {ri.ExtendedErrorInformation.ErrorCode} Extended.ErrorMessage: {ri.ExtendedErrorInformation.ErrorMessage}"); // E0240041
throw;
}
Again, RequestInformation is not available in RequestFailedException.
How do we get access to all the detailed information (RequestInformation) about an exception from the new RequestFailedException class?
As you can see the definition of RequestFailedException Class (Azure) and constuctors in the latest version of azure sdk.
RequestFailedException(Int32, String, String, Exception) : gives HTTP status code ,specified error message, error code, and a reference to the inner exception .
And
RequestFailedException(Response)
Gives error message, HTTP status code, error code obtained from the specified response.
The response in the argument represents the HTTP response from the service which has ClientRequestId as one of the properties as shown in the table which gets client request id that was sent to server in the form of x-ms-client-request-id headers.You can try the same while catching the error in the try-catch block.
In exception class you can give
public class RequestFailedException : Exception
{
...
public RequestFailedException(int status, string message, string? errorCode, Exception? innerException) : base(message , innerException) { }
}
Or use RequestFailedException(Response) from which you can get ClientRequestId.
I’ve not tested it myself, but please check if below can be worked around which is taken from the below references or check if something similar can give an idea.Also see if content property can be retrieved as a part of response.
try
{
...
}
catch (Exception aex)
{
foreach (var ex in aex.InnerExceptions)
{
if (ex is RequestFailedException except)
{
var innerException = excep.InnerException;
if (innerException != null && innerException.GetType() == typeof(WebException))
{
WebException webEx = innerException as WebException;
WebResponse resp = webEx.Response;
var responseHeaders = resp.Headers;
string requestId = responseHeaders["x-ms-request-id"];
Console.WriteLine("Request Id: " + requestId);
Console.WriteLine(except.InnerException.Message);
}
else
{
// (not a RequestFailedException)
Console.WriteLine($"{ex.Message}");
}
}
References:
How can I get Request ID when an exception occurs? (microsoft.com)
c# - How can you catch a RequestFailedException if making multiple
DownloadToAsync calls in parallel? - Stack Overflow

Google Drive Api Error 403 cannotAddParent with service account

Using a service account, Google Drive API and Google SpreadSheet API, I create a spreadsheet that i then move to a specific folder, using the following code :
public async Task<File> SaveNewSpreadsheet(Spreadsheet spreadsheet, File folder)
{
try
{
Spreadsheet savedSpreadsheet = await _sheetService.Spreadsheets.Create(spreadsheet).ExecuteAsync();
string spreadsheetId = GetSpreadsheetId(savedSpreadsheet);
File spreadsheetFile = await GetFileById(spreadsheetId);
File spreadsheetFileMoved = await MoveFileToFolder(spreadsheetFile, folder);
return spreadsheetFileMoved;
}
catch (Exception e)
{
_logger.LogError(e, $"An error has occured during new spreadsheet save to Google drive API");
throw;
}
}
public async Task<File> MoveFileToFolder(File file, File folder)
{
try
{
var updateRequest = _driveService.Files.Update(new File(), file.Id);
updateRequest.AddParents = folder.Id;
if (file.Parents != null)
{
string previousParents = String.Join(",", file.Parents);
updateRequest.RemoveParents = previousParents;
}
file = await updateRequest.ExecuteAsync();
return file;
}
catch (Exception e)
{
_logger.LogError(e, $"An error has occured during file moving to folder.");
throw;
}
}
This used to work fine for a year or so, but since today, the MoveFileToFolder request throw the following exception:
Google.GoogleApiException: Google.Apis.Requests.RequestError
Increasing the number of parents is not allowed [403]
Errors [
Message[Increasing the number of parents is not allowed] Location[ - ] Reason[cannotAddParent] Domain[global]
]
The weird thing is that if I create a new service account and use it instead of the previous one, it works fine again.
I've looked for info on this "cannotAddParent" error but I couldn't find anything.
Any ideas on why this error is thrown ?
I have the same problem and filed in issue in the Google Issue Tracker. This is intended behavior, unfortunately. You are no longer able to place a file in multiple parents as in your example. See the linked documentation for migration.
Beginning Sept. 30, 2020, you will no longer be able to place a file in multiple parent folders; every file must have exactly one parent folder location. Instead, you can use a combination of status checks and a new shortcut implementation to accomplish file-related operations.
https://developers.google.com/drive/api/v2/multi-parenting

How to upload file in jhipster form?

I am just starting to use jhipster 5 and angular 5. I have a form and in that form in addition to few regular fields, I have a file input.
I could not find any documentation on how to file in jhipster.
EDIT 1:
I could somehow managed to upload file and send to server. Below is my server method to handle the form submission.
#PostMapping("/email-jobs")
#Timed
public ResponseEntity<EmailJobDTO> createEmailJob(MultipartFile file, #Valid #RequestBody EmailJobDTO emailJobDTO) throws URISyntaxException {
log.debug("REST request to save EmailJob : {}", emailJobDTO);
if (emailJobDTO.getId() != null) {
throw new BadRequestAlertException("A new emailJob cannot already have an ID", ENTITY_NAME, "idexists");
}
System.out.println(file.getName() + " File Name ");
EmailJobDTO result = emailJobService.save(emailJobDTO);
return ResponseEntity.created(new URI("/api/email-jobs/" + result.getId()))
.headers(HeaderUtil.createEntityCreationAlert(ENTITY_NAME, result.getId().toString()))
.body(result);
}
Here i get following exception,
Unsupported Media Type: Content type 'multipart/form-data;boundary=----WebKitFormBoundary73sdwuJtdeRk6xsO;charset=UTF-8' not supported
If I remove #RequestBody from method signature then I dont get above exception but then I start getting 400 bad request exception saying my form fields can not be null.
You must define MultipartFile is #RequestParam and declare produces = MediaType.APPLICATION_JSON_VALUE in post mapping, like:
#PostMapping("/email-jobs", produces = MediaType.APPLICATION_JSON_VALUE)
Client side, you can try send request as this:
Upload.upload({
url: 'api/path',
data: {
file: yourdatafile
},
headers: {'Content-Type': 'multipart/form-data'}
}).progress(function (evt) {
// handle progress
}).success(function (data, status, headers, config) {
// handle success
});
Instead of uploading a file, create a field type as a BLOB and then in your business logic, make a file if u need or else do your.

AmazonS3: Getting warning: S3AbortableInputStream:Not all bytes were read from the S3ObjectInputStream, aborting HTTP connection

Here's the warning that I am getting:
S3AbortableInputStream:Not all bytes were read from the S3ObjectInputStream, aborting HTTP connection. This is likely an error and may result in sub-optimal behavior. Request only the bytes you need via a ranged GET or drain the input stream after use.
I tried using try with resources but S3ObjectInputStream doesn't seem to close via this method.
try (S3Object s3object = s3Client.getObject(new GetObjectRequest(bucket, key));
S3ObjectInputStream s3ObjectInputStream = s3object.getObjectContent();
BufferedReader reader = new BufferedReader(new InputStreamReader(s3ObjectInputStream, StandardCharsets.UTF_8));
){
//some code here blah blah blah
}
I also tried below code and explicitly closing but that doesn't work either:
S3Object s3object = s3Client.getObject(new GetObjectRequest(bucket, key));
S3ObjectInputStream s3ObjectInputStream = s3object.getObjectContent();
try (BufferedReader reader = new BufferedReader(new InputStreamReader(s3ObjectInputStream, StandardCharsets.UTF_8));
){
//some code here blah blah
s3ObjectInputStream.close();
s3object.close();
}
Any help would be appreciated.
PS: I am only reading two lines of the file from S3 and the file has more data.
Got the answer via other medium. Sharing it here:
The warning indicates that you called close() without reading the whole file. This is problematic because S3 is still trying to send the data and you're leaving the connection in a sad state.
There's two options here:
Read the rest of the data from the input stream so the connection can be reused.
Call s3ObjectInputStream.abort() to close the connection without reading the data. The connection won't be reused, so you take some performance hit with the next request to re-create the connection. This may be worth it if it's going to take a long time to read the rest of the file.
Following option #1 of Chirag Sejpal's answer I used the below statement to drain the S3AbortableInputStream to ensure the connection can be reused:
com.amazonaws.util.IOUtils.drainInputStream(s3ObjectInputStream);
I ran into the same problem and the following class helped me
#Data
#AllArgsConstructor
public class S3ObjectClosable implements Closeable {
private final S3Object s3Object;
#Override
public void close() throws IOException {
s3Object.getObjectContent().abort();
s3Object.close();
}
}
and now you can use without warning
try (final var s3ObjectClosable = new S3ObjectClosable(s3Client.getObject(bucket, key))) {
//same code
}
To add an example to Chirag Sejpal's answer (elaborating on option #1), the following can be used to read the rest of the data from the input stream before closing it:
S3Object s3object = s3Client.getObject(new GetObjectRequest(bucket, key));
try (S3ObjectInputStream s3ObjectInputStream = s3object.getObjectContent()) {
try {
// Read from stream as necessary
} catch (Exception e) {
// Handle exceptions as necessary
} finally {
while (s3ObjectInputStream != null && s3ObjectInputStream.read() != -1) {
// Read the rest of the stream
}
}
// The stream will be closed automatically by the try-with-resources statement
}
I ran into the same error.
As others have pointed out, the /tmp space in lambda is limited to 512 MB.
And if the lambda context is re-used for a new invocation, then the /tmp space is already half-full.
So, when reading the S3 objects and writing all the files to the /tmp directory (as I was doing),
I ran out of disk space somewhere in between.
Lambda exited with error, but NOT all bytes from the S3ObjectInputStream were read.
So, two things one need to keep in mind:
1) If the first execution causes the problem, be stingy with your /tmp space.
We have only 512 MB
2) If the second execution causes the problem, then this could be resolved by attacking the root problem.
Its not possible to delete the /tmp folder.
So, delete all the files in the /tmp folder after the execution is finished.
In java, here is what I did, which successfully resolved the problem.
public String handleRequest(Map < String, String > keyValuePairs, Context lambdaContext) {
try {
// All work here
} catch (Exception e) {
logger.error("Error {}", e.toString());
return "Error";
} finally {
deleteAllFilesInTmpDir();
}
}
private void deleteAllFilesInTmpDir() {
Path path = java.nio.file.Paths.get(File.separator, "tmp", File.separator);
try {
if (Files.exists(path)) {
deleteDir(path.toFile());
logger.info("Successfully cleaned up the tmp directory");
}
} catch (Exception ex) {
logger.error("Unable to clean up the tmp directory");
}
}
public void deleteDir(File dir) {
File[] files = dir.listFiles();
if (files != null) {
for (final File file: files) {
deleteDir(file);
}
}
dir.delete();
}
This is my solution. I'm using spring boot 2.4.3
Create an amazon s3 client
AmazonS3 amazonS3Client = AmazonS3ClientBuilder
.standard()
.withRegion("your-region")
.withCredentials(
new AWSStaticCredentialsProvider(
new BasicAWSCredentials("your-access-key", "your-secret-access-key")))
.build();
Create an amazon transfer client.
TransferManager transferManagerClient = TransferManagerBuilder.standard()
.withS3Client(amazonS3Client)
.build();
Create a temporary file in /tmp/{your-s3-key} so that we can put the file we download in this file.
File file = new File(System.getProperty("java.io.tmpdir"), "your-s3-key");
try {
file.createNewFile(); // Create temporary file
} catch (IOException e) {
e.printStackTrace();
}
file.mkdirs(); // Create the directory of the temporary file
Then, we download the file from s3 using transfer manager client
// Note that in this line the s3 file downloaded has been transferred in to the temporary file that we created
Download download = transferManagerClient.download(
new GetObjectRequest("your-s3-bucket-name", "your-s3-key"), file);
// This line blocks the thread until the download is finished
download.waitForCompletion();
Now that the s3 file has been successfully transferred into the temporary file that we created. We can get the InputStream of the temporary file.
InputStream input = new DataInputStream(new FileInputStream(file));
Because the temporary file is not needed anymore, we just delete it.
file.delete();

Returning binary content from a JPF action with Weblogic Portal 10.2

One of the actions of my JPF controller builds up a PDF file and I would like to return this file to the user so that he can download it.
Is it possible to do that or am I forced to write the file somewhere and have my action forward a link to this file? Note that I would like to avoid that as much as possible for security reasons and because I have no way to know when the user has downloaded the file so that I can delete it.
I've tried to access the HttpServletResponse but nothing happens:
getResponse().setContentLength(file.getSize());
getResponse().setContentType(file.getMimeType());
getResponse().setHeader("Content-Disposition", "attachment;filename=\"" + file.getTitle() + "\"");
getResponse().getOutputStream().write(file.getContent());
getResponse().flushBuffer();
We have something similar, except returning images instead of a PDF; should be a similar solution, though, I'm guessing.
On a JSP, we have an IMG tag, where the src is set to:
<c:url value="/path/getImage.do?imageId=${imageID}" />
(I'm not showing everything, because I'm trying to simplify.) In your case, maybe it would be a link, where the href is done in a similar way.
That getImage.do maps to our JPF controller, obviously. Here's the code from the JPF getImage() method, which is the part you're trying to work on:
#Jpf.Action(forwards = {
#Jpf.Forward(name = FWD_SUCCESS, navigateTo = Jpf.NavigateTo.currentPage),
#Jpf.Forward(name = FWD_FAILURE, navigateTo = Jpf.NavigateTo.currentPage) })
public Forward getImage(final FormType pForm) throws Exception {
final HttpServletRequest lRequest = getRequest();
final HttpServletResponse lResponse = getResponse();
final HttpSession lHttpSession = getSession();
final String imageIdParam = lRequest.getParameter("imageId");
final long header = lRequest.getDateHeader("If-Modified-Since");
final long current = System.currentTimeMillis();
if (header > 0 && current - header < MAX_AGE_IN_SECS * 1000) {
lResponse.setStatus(HttpServletResponse.SC_NOT_MODIFIED);
return null;
}
try {
if (imageIdParam == null) {
throw new IllegalArgumentException("imageId is null.");
}
// Call to EJB, which is retrieving the image from
// a separate back-end system
final ImageType image = getImage(lHttpSession, Long
.parseLong(imageIdParam));
if (image == null) {
lResponse.sendError(404, IMAGE_DOES_NOT_EXIST);
return null;
}
lResponse.setContentType(image.getType());
lResponse.addDateHeader("Last-Modified", current);
// public: Allows authenticated responses to be cached.
lResponse.setHeader("Cache-Control", "max-age=" + MAX_AGE_IN_SECS
+ ", public");
lResponse.setHeader("Expires", null);
lResponse.setHeader("Pragma", null);
lResponse.getOutputStream().write(image.getContent());
} catch (final IllegalArgumentException e) {
LogHelper.error(this.getClass(), "Illegal argument.", e);
lResponse.sendError(404, IMAGE_DOES_NOT_EXIST);
} catch (final Exception e) {
LogHelper.error(this.getClass(), "General exception.", e);
lResponse.sendError(500);
}
return null;
}
I've actually removed very little from this method, because there's very little in there that I need to hide from prying eyes--the code is pretty generic, concerned with images, not with business logic. (I changed some of the data type names, but no big deal.)