all you guys who know things I don't :-)
I've run into this problem that may not be actually a problem, only a revelation that I don't know what I'm doing. AGAIN!
I'm uploading a JPEG with some description and indexable keywords. Works like a charm. But I can't figure out how to add/modify meta data later, without creating another instance of the file. So, when I add a picture of my dog with description "dog", I end up with what I wanted. But if I try to modify the metadata by either using:
gooFl = drvSvc.files().insert(meta).execute();
or
gooFl = drvSvc.files().insert(meta,null).execute();
I end up with a new file (of the same name) on GOOGLE Drive.
See the code snippet below:
File meta = new File();
meta.setTitle("PicOfMyDog.jpg");
meta.setMimeType("image/jpeg");
meta.setParents(Arrays.asList(new ParentReference().setId(ymID)));
File gooFl = null;
if (bNewJPG == true) {
meta.setDescription("dog");
meta.setIndexableText(new IndexableText().setText("dog"));
gooFl = drvSvc.files().insert(meta,
new FileContent("image/jpeg", new java.io.File(fullPath("PicOfMyDog.jpg"))))
.execute();
} else {
meta.setDescription("dick");
meta.setIndexableText(new IndexableText().setText("dick"));
// gooFl = drvSvc.files().insert(meta).execute();
gooFl = drvSvc.files().insert(meta,null).execute();
}
if (gooFl != null)
Log.d("atn", "success " + gooFl.getTitle());
It is the "else" branch I'm asking about. First file one has meatadata "dog", second "dick".
So, what's the solution. Do I delete the previous instance (and how)? Is there another syntax / method I don't know about?
thank you, sean
If you need to modify the metadata, use files.patch.
drvSvc.files().patch(id, meta).execute();
In cases you need both modify the metadata and the file contents, use files.update.
drvSvc.files().update(id, meta, content).execute();
Insertions make POST requests that always create a new resource.
You need to use Files.Patch if you want to update only Metadata. files().insert always creates a new file.
A full list of File commands and what operations you need to use can be found in the API Reference
Related
Dropbox now have an apsolutely new API, which is absolutely differ from the old one (it's interesting why), but there's no ANY actual examples in the internet, so I've found only some code in their examples. Here is it:
// Download the file.
try (OutputStream outputStream = new FileOutputStream (file)) {
mDbxClient.files ()
.download (metadata.getPathLower (), metadata.getRev ())
.download (outputStream);
}
I need to download file from remote folder to the local one, so I need to use this path for example:
.download ("Backups/backup.ab", "/storage/sdcard/Folder/backup.ab")
I've tried it, but get a error
IllegalArgumentException: String 'rev' does not match pattern'
Do you know, what it can be, and metadata.getPathLower () and metadata.getRev () methods are using for? I've learned, that metadata var gets from the first argv from execute (), but what this functions do?
Thanks a lot!
Not sure if if works for android. I have posted the following method just in case someone is looking for a C# .net solution.
private async Task Download(DropboxClient dbx, string folder, string file, string localFilePath)
{
using (var response = await dbx.Files.DownloadAsync(folder + "/" + file))
{
using (var fileStream = File.Create(localFilePath))
{
(await response.GetContentAsStreamAsync()).CopyTo(fileStream);
}
}
}
Parameter example:
file = "YourFileName.pdf";
folder = "/YourDropboxFolderName";
localFilePath = #"C:\Users\YourUserName\YourFileName.pdf";
The Dropbox API v2 Java SDK's download method takes these two parameters:
String path
String rev
Per the download method documentation there, the first is the remote path of the file in Dropbox you want to download, and the second is the identifier for the revision of the file you want. The second parameter is not the local path where you want to save the file, as it appears you're supplying in your code. Instead, you save the file content using the .download (outputStream); portion of the sample code you posted, e.g., as also shown in this sample code.
Also, as stated in the documentation, the second parameter is deprecated and should no longer be used. You can just use the version of the download method that only takes the one parameter. The code for using it is otherwise the same as the sample.
For reference, in the sample, the metadata object is an instance of FileMetadata. You can find more information on the getPathLower and getRev methods in the documentation as well.
I have used this below code for get object from google cloud storage bucket.i have error in getMetadata. Can any one please tell me here what is getMetadata and how to get that ?
Storage.Objects.Get getObject = client.objects().get(bucketName, objectname);
if (getMetadata == true) {
StorageObject object = getObject.execute();
} else {
// Downloading data.
ByteArrayOutputStream out = new ByteArrayOutputStream();
// If you're not in AppEngine, download the whole thing in one request, if possible.
getObject.getMediaHttpDownloader().setDirectDownloadEnabled(true);
getObject.executeMediaAndDownloadTo(out);
}
It looks like you're running through the sample code snippet; in that snippet, getMetadata is simply referring to your own choice of whether you want to view the object's metadata like size, content-type, creation time, etc., or whether you actually want to download the object's contents.
In your actual code using it, you probably won't structure it that way using any getMetadata variable. Instead, you should just use the code from the branch of that conditional that you need in each particular circumstance. For example, if you just want to get the size of the object so that you can display the number of bytes somewhere without actually downloading it:
Storage.Objects.Get getObject = client.objects().get(bucketName, objectname);
StorageObject object = getObject.execute();
System.out.println("Size is: " + object.getSize().longValue());
Or if you just wanted to dump the contents to System.out:
Storage.Objects.Get getObject = client.objects().get(bucketName, objectname);
getObject.getMediaHttpDownloader().setDirectDownloadEnabled(true);
getObject.executeMediaAndDownloadTo(System.out);
i am trying to get this really easy setup to work, and it works on my computer but not on Android.
After trying it for the whole day im now asking since i cant find a single example on the internet.
The setup:
I have a lot of *.png files in a folder. Since the problem is with android i put them into a "StreamingAssets" folder
I have a RawImage called "Overlay"
I have a Dropdown called "Dropdown"
What should happen:
1. The Dropdown_script checks the StreamingAssets folder for all *.png files and adds every Filename to the dropdown options menu.
2. Once the user chooses one of the dropdown values my "Overlay" image changes its texture to the according file.
Pretty easy on PC ... impossible on android(with unity3d) as it seems.
My Dropdown Script:
public class DDScript : MonoBehaviour {
void Start () {
GameObject obj = GameObject.Find("Dropdown");
//Get all filenames
var info = new DirectoryInfo(Application.streamingAssetsPath);
var fileInfo = info.GetFiles("*.png");
//Clear the DropDown Menu Items from the Inspector
obj.GetComponent<Dropdown>().options.Clear();
//Make the first chosen item the first filename
obj.GetComponent<Dropdown>().captionText.text = fileInfo[0].Name.Substring(0, fileInfo[0].Name.IndexOf("."));
foreach (var file in fileInfo)
{
Dropdown.OptionData list = new Dropdown.OptionData(file.Name.Substring(0, file.Name.IndexOf(".")));
obj.GetComponent<Dropdown>().options.Add(list);
}
}
Its not working. It is working on my Computer but it is just not working on Android. I know that under Android everything gets packed into a jar file and there is nothing like a folderstructure. StreamingAssets should still have the files but i can understand that this part maybe cant work. Which would not be that bad, since it just finds the names and puts it into an array, i could do that within the program by hand. Since i know from beforehand how much and which files will be in the folder and it wont change ever.
This is my Change Texture Method
It is invoked by the Dropdown OnValueChange so the "newOverlay" is simply the int from the Dropdown. For debugging purposes i set the filepath to a specific file. later it will change depending on newOverlay
public IENumerator SetOverlay(int newOverlay)
{
GameObject obj = GameObject.Find("Overlay");
img = (RawImage)obj.GetComponent<RawImage>();
string filePath = System.IO.Path.Combine(Application.streamingAssetsPath, "testfile.png");
WWW www = new WWW(filePath);
yield return www;
img.texture = www.texture;
}
And i do not understand why this is not working!
The Documentation reads:
" This means that if you do not use Unity’s WWW class to retrieve the file then you will need to use additional software"
So using www is the right way. But it is not working!
No Texture gets loaded. i dont get the red questionmark, my image is just plain white. Please can someone help me here? Maybe i just cant see the forest due to all of the trees or the day was too long.
I really just cant believe that it is this hard to load a bunch of images that are within my apk file wiht unity :(
Thank you very much in advance
Edit: Solution (somehow)
First of all the problem was that System.IO.Path.Combine adds a back-slash between file and folder, but not between the folders themself!!!!
public void SetOverlay(int newOverlay)
{
GameObject obj = GameObject.Find("Overlay");
img = (RawImage)obj.GetComponent<RawImage>();
string filePath = Application.streamingAssetsPath + "/testfile.png";
WWW www = new WWW(filePath);
while (!www.isDone)
{}
img.texture = www.texture;
GameObject.Find("DebugText").GetComponent<Text>().text = filePath;
}
Havent found a solution to the Filename problem yet but im glad that this stupid "bug" is resolved
Have you tried putting the png files into the drawable folder and accessing them with BitmapFactory.decodeResources()?
The following 2 code snippets demonstrate the problem I ran into with the NEW Google Drive Android API / Google Play Services 4.2 (libver 15). Or is it a feature I don't know about? All error checking and initialization is removed in order to keep the code simple.
1/ I create a picture of "image/jpeg" MIME type;
GoogleApiClient mGAC;
byte[] jpgBuffer;
DriveFolder fldr;
ContentsResult rslt = Drive.DriveApi.newContents(mGAC).await();
Contents cont = rslt.getContents();
cont.getOutputStream().write(jpgBuffer);
MetadataChangeSet meta = new MetadataChangeSet.Builder()
.setTitle("foo.jpg").setMimeType("image/jpeg")
.build();
fldr.createFile(mGAC, meta, cont);
Everything is nice and dandy in the Drive. Image is there, looking great, I can even send it to my mom. But this is not what I'm after. I would like to retrieve it in another part of my Android app.
2/ So I try this:
Query query = new Query.Builder().addFilter(
Filters.eq(SearchableField.MIME_TYPE, "image/jpeg")
).build();
MetadataBufferResult rslt = Drive.DriveApi.query(mGAC, query).await();
for (Metadata md : rslt.getMetadataBuffer()) {
Log.d("TAG", md.getTitle() + " " + md.getMimeType());
}
Result: big, fat NOTHING.
I'm not giving up, so the next logical step is to look for ANY file. And the file "foo.jpg" I saved in step 1/ is showing as "image/png" MIME type.
Mystery is solved. IT IS A FEATURE! The "jpgBuffer" in
cont.getOutputStream().write(jpgBuffer);
actually contains PNG binary data. So even if my app specified "image/jpeg" MIME type, Google after snooping through my (my user's) data decided to correct MIME type to "image/png". It should also be noted that it happens with some delay, making the debugging process even more mysterious.
I have yet another hurdle to climb with my GOOGLE DRIVE SDK Android App. I am uploading scanned images with tightly controlled index fields - user defined 'tags' from local dictionary. For instance XXX.JPG has index words "car" + "insurance". Here is a simplified code snippet:
...
body.setTitle("XXX.JPG");
body.setDescription("car, insurance");
body.setIndexableText(new IndexableText().setText("car insurance"));
body.setMimeType("image/jpeg");
body.setParents(Arrays.asList(new ParentReference().setId(...)));
FileContent cont = new FileContent("image/jpeg", new java.io.File(fullPath("xxx.jpg")));
File gooFl = _svc.files().insert(body, cont).execute();
...
Again, everything works great, except when I start a search, I get results that apparently come from some OCR post process, thus rendering my system's DICTIONARY unusable. I assume I can use a custom MIME type, but then the JPEG images become invisible for users who use standard GOOGLE DRIVE application (local, browser-based ... ). So the question is: Can I upload MIME "image/jpeg" files with custom indexes (either Indexable, or Description fields) but stop GOOGLE from OCR-ing my files and adding indexes I did not intend to have?
Just to be more specific, I search for "car insurance" and instead of my 3 files I indexed this way, I get unmanageable pile of other results (JPEG scanned documents) that had "car" and "insurance" somewhere in them. Not what my app wants.
Thank you in advance, sean
...
Based on Burcu's advise below, I modified my code to something that looks like this (stripped to bare bones):
// define meta-data
File body = new File();
body.setTitle("xxx.jpg");
body.setDescription(tags);
body.setIndexableText(new IndexableText().setText(tags));
body.setMimeType("image/jpeg");
body.setParents(Arrays.asList(new ParentReference().setId(_ymID)));
body.setModifiedDate(DateTime.parseRfc3339(ymdGOO));
FileContent cont =
new FileContent("image/jpeg",new java.io.File(fullPath("xxx.jpg")));
String sID = findOnGOO(driveSvc, body.getTitle());
// file not found on gooDrive, upload and fix the date
if (sID == null) {
driveSvc.files().insert(body, cont).setOcr(false).execute();
driveSvc.files().patch(gooFl.getId(), body).setOcr(false).setSetModifiedDate(true).execute();
// file found on gooDrive - modify metadata and/or body
} else {
// modify content + metadata
if (contentModified) {
driveSvc.files().update(sID, body, cont).setOcr(false).setSetModifiedDate(true).execute();
// only metadata (tags,...)
} else {
driveSvc.files().patch(sID, body).setOcr(false).setSetModifiedDate(true).execute();
}
}
...
It is a block that uploads or modifies a Google Drive file. The two non-standard operations are:
1/ resetting the file's 'modified' date in order to force the date of file creation - tested, works OK
2/ stopping the OCR process that interferes with my apps indexing scheme - will test shortly and update here
For the sake of simplicity, I did not include the implementation of "findInGOO()" method. It is quite simple 2-liner and I can supply it upon request
sean
On insertion, set the ocr parameter to false:
service.files().update(body, content).setOcr(false).execute();