veron-li / google-gdata

Automatically exported from code.google.com/p/google-gdata
0 stars 0 forks source link

content is empty when inserting or updating text files to Google #540

Closed GoogleCodeExporter closed 8 years ago

GoogleCodeExporter commented 8 years ago
When inserting or updating new text files to Google Documents, the files are 
created with correct file names, but the content is empty.

Here the sample Code in C#, using GoogleAPI version 1.9 (released in Sep 2011):

RequestSettings rs = new RequestSettings("GoogleContactSyncMod", username, 
password); 
DocumentsRequest documentsRequest = new DocumentsRequest(rs);
string fileName = "C:\\Test.txt"; //This is a file with text content
string contentType = MediaFileSource.GetContentTypeForFileName(fileName);
Document doc = new Document()
doc.Categories.Add(new 
AtomCategory("http://schemas.google.com/docs/2007#document"));
doc.MediaSource = new MediaFileSource(fileName, contentType);
Uri feedUri = new Uri(documentsRequest.BaseUri);
Document createdEntry = documentsRequest.Insert(feedUri, doc);

Expected result: uploaded text file with content.

Received result: empty document file.

Original issue reported on code.google.com by Saller....@gmail.com on 26 Sep 2011 at 5:57

GoogleCodeExporter commented 8 years ago
Your code is working correctly, you are creating a new document entry but not 
reading the content of the local file.
You may want to check DocumentsService.UploadDocument instead:

http://www.google.com/codesearch#VETFb4oZYpw/clients/cs/src/documents3/documents
ervice.cs&q=uploaddocument%20package:http://google-gdata%5C.googlecode%5C.com&l=
115

Original comment by ccherub...@google.com on 26 Sep 2011 at 5:15

GoogleCodeExporter commented 8 years ago
Hmm, but I thought assigning the MediaSource to the document and calling 
documentsRequest.Insert reads the local file content and uploads it?

I tried the DocumentsService.UploadDocument, it worked for new uploads (even 
with content), but when I just want to update the content of an existing 
document (currently done by documentsRequest.Update(doc), it returns the error 
503, Server not available. I tried also DocumentsService.Update, but also 
didn't work.

I just want to have the oportunity to upload new files or update existing files 
contents (but if possible without deleting them before), Any proposal?

Original comment by Saller....@gmail.com on 26 Sep 2011 at 7:13

GoogleCodeExporter commented 8 years ago
And how can I upload documents to certain subfolder in my documents?

Original comment by Saller....@gmail.com on 30 Sep 2011 at 8:31

GoogleCodeExporter commented 8 years ago

Original comment by ccherub...@google.com on 30 Sep 2011 at 9:11

GoogleCodeExporter commented 8 years ago
I have found a workaround to do this by using "DocumentsService.UploadDocument":

RequestSettings rs = new RequestSettings("GoogleContactSyncMod", username, 
password); 
DocumentsRequest documentsRequest = new DocumentsRequest(rs);
string fileName = "C:\\Test.txt"; //This is a file with text content
DocumentEntry entry = _documentsRequest.Service.UploadDocument(fileName, 
"Test");                               

Nevertheless, this is just a workaround, because if you want to update an 
existing document, you have to delete it first before uploading. In addition to 
that, it is quite difficult to work with subfolders in this case, because the 
UploadDocument function always uploads to the root folder and then you have to 
take care how to save the file to a subfolder (I solved it by getting the file 
again by its AtomId and then use DocumentsRequest.MoveDocumentTo(folder, 
document), but this is a very hard workaround

Original comment by Saller....@gmail.com on 30 Sep 2011 at 11:47

GoogleCodeExporter commented 8 years ago
Hi All,

I have compared between JAVA class and .Net class documentation that provided 
by Google.

In Java, there is method that related with MediaSource

http://code.google.com/apis/gdata/javadoc/com/google/gdata/data/media/MediaEntry
.html#updateMedia(boolean)

And I think, if I can set MediaSource Property in AtomEntry with latest data 
that I want to update then execute update command, it will update content in 
Google. But I don't change anything.

This is code what I use.

Dim MedSrc As New MediaFileSource(New IO.FileStream(txtSource.Text, 
O.FileMode.Open), txtTitle.Text, "RTF")

AtomEntry.MediaSource = MedSrc
AtomEntry.Update()  --> Note in Java, there is method updateMedia that not 
exist in .Net class.

Is there any reason, why this method is not supported in .Net ?
Is there any solution how to update document without deleting and re-uploading 
again?
In Enterprise solution we need link (Document ID) that can not be changed and 
all modification that made by user should update related document that have 
been uploaded    before.

Thanks.

Original comment by yindra...@gmail.com on 6 Oct 2011 at 5:46

GoogleCodeExporter commented 8 years ago
The new Documents List API documentation includes a sample showing how to to 
update document or file content with the resumable protocol:

https://developers.google.com/google-apps/documents-list/#updatingchanging_docum
ents_and_files

Original comment by ccherub...@google.com on 19 Apr 2012 at 11:23

GoogleCodeExporter commented 8 years ago
Hmm ok, but I don't see the benefit, because with an Async upload I have to 
handle the OnDone event, and this will change my program structure completely, 
because currently I am deleting an existing document (what I would like to 
avoid by updating) and then completely new upload the document, but everything 
is synchronous.

In addition to that, I don't know how to instantiate an authenticator, I am 
using Client login and I didn't find a complete code sample for it, in your 
code this is always commented out:

// TODO: Instantiate an Authenticator object according to your authentication   
   // mechanism (e.g. OAuth2Authenticator).      // Authenticator authenticator 
=  ...

Is there any way to use a synchronous update of a document

Original comment by Saller....@gmail.com on 21 Apr 2012 at 5:12

GoogleCodeExporter commented 8 years ago
Resumable upload is going to be the only accepted upload method, so you should 
start adapting your code to be asynchronous.

You can instantiate a new ClientLoginAuthenticator as in the following code:

ClientLoginAuthenticator authenticator = new 
ClientLoginAuthenticator(applicationName, serviceName, username, password);

Original comment by ccherub...@google.com on 21 Apr 2012 at 5:34

GoogleCodeExporter commented 8 years ago
[deleted comment]
GoogleCodeExporter commented 8 years ago
[deleted comment]
GoogleCodeExporter commented 8 years ago
Now I changed to ResumableUploader and it works fine. But is there a better 
why, how to upload a new document directly to a subfolder (e.g. "Notes")? 
Currently (and also in the past when I used the Service.UploadDocument 
function), I have to first upload it into the root folder and then move it to 
the Notes subfolder.

I am using the following code:
void SaveGoogleNote(NoteMatch match)
{
...
// Instantiate the ResumableUploader component.  
ResumableUploader uploader = new ResumableUploader();  

if (match.GoogleNote.DocumentEntry.Id.Uri != null)
{ //Document already exists
    // Start the update process.  
    uploader.AsyncOperationCompleted += new AsyncOperationCompletedEventHandler(OnGoogleNoteUpdated);    
        uploader.UpdateAsync(_authenticator, match.GoogleNote.DocumentEntry, match);

}
else
{

    // Define the resumable upload link  
    Uri createUploadUrl = new Uri("https://docs.google.com/feeds/upload/create-session/default/private/full"); 
    AtomLink link = new AtomLink(createUploadUrl.AbsoluteUri); 
    link.Rel = ResumableUploader.CreateMediaRelation; 
    match.GoogleNote.DocumentEntry.Links.Add(link);  
    // Set the service to be used to parse the returned entry 
    match.GoogleNote.DocumentEntry.Service = _documentsRequest.Service;   
    uploader.AsyncOperationCompleted += new AsyncOperationCompletedEventHandler(OnGoogleNoteCreated);
        // Start the upload process   
        //uploader.InsertAsync(_authenticator,  match.GoogleNote.DocumentEntry, new object());
    uploader.InsertAsync(_authenticator, match.GoogleNote.DocumentEntry, match);   
}

private void OnGoogleNoteCreated(object sender, 
AsyncOperationCompletedEventArgs e)
{

    //Move now to Notes subfolder
    DocumentEntry entry = e.Entry as DocumentEntry;

    if (e.Error != null)
    throw new Exception("Google Note couldn't be created: " + entry == null?null:entry.Title.Text, e.Error);

    if (e.Cancelled || e.Entry == null)
    throw new Exception("Google Note creation was cancelled: " + entry == null ? null : entry.Title.Text);

    Document newNote = LoadGoogleNotes(entry.Id);
    NoteMatch match = e.UserState as NoteMatch;
    match.GoogleNote = newNote;
    _documentsRequest.MoveDocumentTo(_googleNotesFolder, newNote);

    //Then update the match IDs
    UpdateNoteMatchId(match);
}

private void OnGoogleNoteUpdated(object sender, 
AsyncOperationCompletedEventArgs e)
{
    DocumentEntry entry = e.Entry as DocumentEntry;

    if (e.Error != null)
    throw new Exception("Google Note couldn't be updated: " + entry == null ? null : entry.Title.Text, e.Error);

    if (e.Cancelled || e.Entry == null)
    throw new Exception("Google Note update was cancelled: " + entry == null ? null : entry.Title.Text);

    //Then update the match IDs
    UpdateNoteMatchId((NoteMatch)e.UserState);
}

Another question is: Do I have to change the call to DocumentRequest.Delete 
also? currently I use the following, I changed to the more complex call 
(instead of just use Delete) to not only remove the Notes parentFolder, but 
also remove it from the root folder:
_documentsRequest.Delete(new 
Uri(Google.GData.Documents.DocumentsListQuery.documentsBaseUri + "/" + 
match.GoogleNote.ResourceId), match.GoogleNote.ETag);
//_documentsRequest.Delete(match.GoogleNote);

Original comment by Saller....@gmail.com on 21 Apr 2012 at 2:43