I am trying to create a program that will download image files in my google drive. I was able to do so, however when I am trying to search a file to return a specific file I always got an error when using the 'name' field which is base on this website https://developers.google.com/drive/v3/web/search-parameters. I don't really know the problem. This is my code
GoogleHelper gh = new GoogleHelper();//calling
DriveService service = GoogleHelper.AuthenticateServiceAccount(email, securityPath);
List<String> file = GoogleHelper.GetFiles(service,
"mimeType='image/jpeg' and name contains 'aa'");
String newFile = newPath+id;
gh.DownloadFile(service, file[0],newPath);
//get File Method:
public static List<String> GetFiles(DriveService service, string search)
{
List<String> Files = new List<String>();
try
{
//List all of the files and directories for the current user.
FilesResource.ListRequest list = service.Files.List();
list.MaxResults = 1000;
if (search != null)
{
list.Q = search;
}
FileList filesFeed = list.Execute();
// MessageBox.Show(filesFeed.Items.Count);
//// Loop through until we arrive at an empty page
while (filesFeed.Items != null)
{
// Adding each item to the list.
foreach (File item in filesFeed.Items)
{
Files.Add(item.Id);
}
// We will know we are on the last page when the next page token is
// null.
// If this is the case, break.
if (filesFeed.NextPageToken == null)
{
break;
}
// Prepare the next page of results
list.PageToken = filesFeed.NextPageToken;
// Execute and process the next page request
filesFeed = list.Execute();
}
}
catch (Exception ex)
{
// In the event there is an error with the request.
Console.WriteLine(ex.Message);
MessageBox.Show(ex.Message);
}
return Files;
}
If we check the documentation Search for Files
name string contains1, =, != Name of the file.
They also show it being used
name contains 'hello' and name contains 'goodbye'
Now the file.list method returns a List of file resources. If you check file resources name is not a parameter title is.
So if you do
mimeType='image/jpeg' and (title contains 'a')
Your request will work.
Now the reason the documentation is wrong is that you are using the Google Drive v2 API and the documentation has apparently been updated for Google Drive v3 which you guessed it uses name instead of title for a file.
IMO there should be two because well its just different APIs here.
Related
I have the following code that I want to chance using batch. In this code, first I create a copy of a file, and then using the id of the new file, I am adding a permission.
File readOnlyFile = new File();
readOnlyFile.Name = newFileName.Replace(' ', '-') + "_assess";
readOnlyFile.Parents = new List<string> { targetFolderId };
FilesResource.CopyRequest fileCreateRequest = _driveService.Files.Copy(readOnlyFile, fileId);
string readOnlyFileId = fileCreateRequest.Execute().Id;
if (readOnlyFileId != null)
{
newPermission.ExpirationTime = expirationDate;
newPermission.Type = "anyone";
newPermission.Role = "reader";
PermissionsResource.CreateRequest req = _driveService.Permissions.Create(newPermission, readOnlyFileId);
req.SendNotificationEmail = false;
req.Execute();
}
However, I am puzzled when trying to use batch for this task since I will need the id of the newly copied file to add permission. Below is my initial attempt where I do not know how to proceed after batch.Queue(fileCreateRequest, callback). I can add new action to the batch to add permission. But, I do not know how to get the id of the file. Any suggestions? I need to do this for three different files.
var batch = new BatchRequest(_driveService);
BatchRequest.OnResponse<Permission> callback = delegate (
Permission permission,
RequestError error,
int index,
System.Net.Http.HttpResponseMessage message)
{
if (error != null)
{
// Handle error
Console.WriteLine(error.Message);
}
else
{
Console.WriteLine("Permission ID: " + permission.Id);
}
};
Permission newPermission = new Permission();
File readOnlyFile = new File();
readOnlyFile.Name = newFileName.Replace(' ', '-') + "_assess";
readOnlyFile.Parents = new List<string> { targetFolderId };
FilesResource.CopyRequest fileCreateRequest = _driveService.Files.Copy(readOnlyFile, fileId);
batch.Queue(fileCreateRequest, callback);
To upload and to configure permissions of a file are two different operations that cannot be batched together. Your approach is correct, you only have to use set up the permissions in a second call.
After uploading the files and retrieving the ids as you do, you have to create a second call to create the permissions.
There is no way to do it in a single request, because for setting up the permissions you need the id of the file; and that is only created after finishing the upload. If you need any more clarification, please ask me without hesitating.
I previously made a post asking how to send a .3gpp audio file up to the parse cloud here:
Xamarin C# Android - converting .3gpp audio to bytes & sending to parseObject
I have managed to do this successfully, on parse's data manager, I can click the file's link and play the sound sent from my android device successfully.
Here's the code for uploading the data to the cloud:
async Task sendToCloud(string filename)
{
ParseClient.Initialize ("Censored Key", "Censored Key");
string LoadPath = System.Environment.GetFolderPath(System.Environment.SpecialFolder.ApplicationData);
string savetheFile = sName + ".3gpp";
string tempUserName;
LoadPath += savetheFile;
Console.WriteLine ("loadPath: " + LoadPath);
try
{
byte[] data = File.ReadAllBytes(LoadPath);
ParseFile file = new ParseFile(savetheFile, data);
await file.SaveAsync();
var auidoParseObject = new ParseObject("AudioWithData");
//Console.WriteLine(ParseUser.getUserName());
if (ParseUser.CurrentUser != null)
{
tempUserName = ParseUser.CurrentUser.Username.ToString();
}
else{
tempUserName = "Anonymous";
}
//tempUserName = ParseUser.CurrentUser.Username.ToString();
Console.WriteLine("PARSE USERNAME: " + tempUserName);
auidoParseObject["userName"] = tempUserName;
auidoParseObject["userName"] = tempUserName;
auidoParseObject["file"] = file;
await auidoParseObject.SaveAsync();
}
catch (Exception e)
{
Console.WriteLine("Failed to await audio object! {0}" + e);
}
}
So as you can see, I'm sending a ParseObject called "AudioWithData".
This object contains two children:
-The username of the user who uploaded the file (string)
-The parseFile called "file" (which has the following two children)
---SaveTheFile (A string containing the name of the audio file, input by the user, with the .3gpp extension added on the end, for example "myAudioFile.3gpp"
---data (this contains the bytes of the audio file)
I need to be able to download the file onto my android device, and play it through a mediaplayer object.
I've checked over the documentation on the parse website, but I haven't managed to do this:
(excuse my pseudo querying syntax here)
SELECT (audio files) FROM (the parseObject) WHERE (the username = current user)
I then, eventually, want to place all of these files into a listview, and when the user clicks the file, it plays the audio.
I've tried the following but I don't really know what I'm doing with it...
async Task RetrieveSound(string filename)
{
ParseClient.Initialize ("Censored key", "Censored key");
Console.WriteLine ("Hit RetrieveSound, filename = " + filename);
string username;
var auidoParseObject = new ParseObject("AudioWithData");
if (ParseUser.CurrentUser != null) {
username = ParseUser.CurrentUser.Username.ToString ();
} else {
username = "Anonymous";
}
string cloudFileName;
Console.WriteLine ("username set to: " + username);
var HoldThefile = auidoParseObject.Get<ParseFile>("audio");
//fgher
var query = from audioParseObject in ParseObject.GetQuery("userName")
where audioParseObject.Get<String>("userName") == username
select file;
IEnumerable<ParseFile> results = await query.FindAsync();
Console.WriteLine ("passed the query");
//wfojh
byte[] data = await new HttpClient().GetByteArrayAsync(results.Url);
Console.WriteLine ("putting in player...");
_player.SetDataSourceAsync (data);
_player.Prepare;
_player.Start ();
}
Any help would be GREATLY APPRECIATED! Even a point in the right direction would be great!
Thanks!
EDIT--
I'm actually getting a query error on the following lines
(I can't post images because of my reputation - I lost access to my main stackOverflow account :/ )
Links to images here:
first error: http://i.stack.imgur.com/PZBJr.png
second error: http://i.stack.imgur.com/UkHvX.png
Any ideas? The parse documentation is vague about this.
this line will return a collection of results
IEnumerable<ParseFile> results = await query.FindAsync();
you either need to iterate through them with foreach, or just pick the first one
// for testing, just pick the first one
if (results.Count > 0) {
var result = results[0];
byte[] data = await new HttpClient().GetByteArrayAsync(result.Url);
File.WriteAllBytes(some_path_to_a_temp_file, data);
// at this point, you can just initialize your player with the audio file path and play as normal
}
I have strange problem.
I have some folders in my Google Drive, and one is named myFolder. That folder has visibility option set to Anyone with the link.
I want to get that folder ID. To do so, I have the following code
ChildrenResource.ListRequest request = Google_DriveService.Children.List("root");
request.Q = "mimeType='application/vnd.google-apps.folder' and title='myFolder' and trashed=false";
try
{
ChildList children = request.Fetch();
return children.Items;
}
catch (Exception e)
{
throw e;
}
which throws error 500. But, if I change the query to "mimeType='application/vnd.google-apps.folder' and trashed=false"; I get the list of the folders, but there is no posibility to know which folder in that list is the one that I want.
So
1) why I get that error 500 if I pass the folder name inside that query ?
2) How to get folder details (e.g. its name) if I have ID ?
EDIT
OK, I've changed the code as you guys suggested, now I don't get the error, but the folder is still not found. It is placed in the root folder.
var request = Google_DriveService.Files.List();
request.Q = "mimeType='application/vnd.google-apps.folder' and title='myFolder' and trashed=false";
var children = request.Fetch();
return children.Items.Count > 0 ? children.Items.First().Id : null;
1 . Probably a Bug. Try running your query from https://developers.google.com/drive/v2/reference/files/list#try-it to confirm
What scope are you using? If drive.file, try switching to drive
2 . In the returned JSON, look for 'title'. If you need to be sure it's the right file, you maybe need to check the parent id vs the parent id of myfolder.
I think you need to remove the root you have in there. This works. Not sure which client api you are using. This is using the latest.
FilesResource.ListRequest request = service.Files.List();
request.MaxResults = 1000;
request.Q = "mimeType='application/vnd.google-apps.folder' and trashed=false and title='myFolder'";
Here is a code snippet uses Google.Apis.Drice.V2 Client Library that can be used for locate a folder in Google Drive.
using Google.Apis.Drive.v2;
using Google.Apis.Drive.v2.Data;
using Google.Apis.Discovery;
using Google.Apis.Upload;
string search = string.Format("title = '{0}' and mimeType =
'application/vnd.google-apps.folder'",folderName);
IList<File> files = new List<File>();
try
{
//List all of the files and directories for the current user.
// Documentation: https://developers.google.com/drive/v2/reference/files/list
FilesResource.ListRequest list = _service.Files.List();
list.MaxResults = 1000;
if (search != null)
{
list.Q = search;
}
FileList filesFeed = list.Execute();
//// Loop through until we arrive at an empty page
while (filesFeed.Items != null)
{
// Adding each item to the list.
foreach (File item in filesFeed.Items)
{
files.Add(item);
}
// We will know we are on the last page when the next page token is
// null.
// If this is the case, break.
if (filesFeed.NextPageToken == null)
{
break;
}
// Prepare the next page of results
list.PageToken = filesFeed.NextPageToken;
// Execute and process the next page request
filesFeed = list.Execute();
}
}
catch (Exception ex)
{
// In the event there is an error with the request.
Console.WriteLine(ex.Message);
}
I'm programming an app that interact with dropbox by use DropNet API. I want to check if the folder is exist or not on dropbox in order to I will create one and upload file on it after that. Everything seen fine but if my folder is exist it throw exception. Like this:
if (isAccessToken)
{
byte[] bytes = File.ReadAllBytes(fileName);
try
{
string dropboxFolder = "/Public/DropboxManagement/Logs" + folder;
// I want to check if the dropboxFolder is exist here
_client.CreateFolder(dropboxFolder);
var upload = _client.UploadFile(dropboxFolder, fileName, bytes);
}
catch (DropNet.Exceptions.DropboxException ex) {
MessageBox.Show(ex.Response.Content);
}
}
I'm not familiar with dropnet, but looking at the source code, it appears you should be able to do this by using the GetMetaData() method off of your _client object. This method returns a MetaData object.
Example:
//gets contents at requested path
var metaData = _client.GetMetaData("/Public/DropboxManagement/Logs");
//without knowing how this API works, Path may be a full path and therefore need to check for "/Public/DropboxManagement/Logs" + folder
if (metaData.Contents.Any(c => c.Is_Dir && c.Path == folder)
{
//folder exists
}
I am working on a client that access an Exchange Web Service via a web reference. (not the Managed API). This is the first time I'm worked with EWS so I hope its just a simple mistake that I overlooked.
I have a method called MoveItem that is supposed to take email message and move it from the Inbox to destinationFolder. When I run this code, the item does disappear from the Inbox however it never shows up in the destination folder. I've spent a couple of days looking at examples online and I've also not been able to find anyone else that has had a similar issue. Can anyone tell me what I am doing wrong? Thanks in advance
Scott
static void MoveItem(ExchangeServiceBinding esb, BaseFolderType destinationFolder, MessageType msg)
{
ItemIdType[] items = new ItemIdType[1] { (ItemIdType)msg.ItemId };
BaseFolderIdType destFolder = destinationFolder.FolderId;
MoveItemType request = new MoveItemType();
request.ItemIds = items;
request.ToFolderId = new TargetFolderIdType();
request.ToFolderId.Item = destFolder;
try
{
MoveItemResponseType response = esb.MoveItem(request);
ArrayOfResponseMessagesType aormt = response.ResponseMessages;
ResponseMessageType[] rmta = aormt.Items;
foreach (ResponseMessageType rmt in rmta)
{
if (rmt.ResponseClass == ResponseClassType.Error)
{
throw new Exception("Item move failed.");
}
}
}
catch (Exception e)
{
Console.WriteLine(e.Message);
}
}
Definitely not an expert here, but this is the following code I used to grab an item and move it into a folder:
Folder rootfolder = Folder.Bind(service, WellKnownFolderName.MsgFolderRoot);
rootfolder.Load();
foreach (Folder folder in rootfolder.FindFolders(new FolderView(100)))
{
// Finds the emails in a certain folder, in this case the Junk Email
FindItemsResults<Item> findResults = service.FindItems(WellKnownFolderName.JunkEmail, new ItemView(10));
// Enter your destination folder name below this:
if (folder.DisplayName == "Example")
{
// Stores the Folder ID in a variable
var fid = folder.Id;
Console.WriteLine(fid);
foreach (Item item in findResults.Items)
{
// Load the email, move it to the specified folder
item.Load();
item.Move(fid);
}
}
}
One thing about the EWS is that when moving to a folder, the ID of the folder is key. In this example, I first find the folders in the inbox, then access the messages. Therefore, any code regarding the individual message would go after the folders have been found.
I have same problem. The moved message doesn't exists in folder (outlook.com) but can be retrieved via APIs with new assigned id.
Outlook.com can find it in search with an error while loading message body:
Error: Your request can't be completed right now. Please try again later.