I'm trying to use the Google Docs GData API (.NET) to upload a file to my docs, but I keep getting errors thrown. I can't find any example that uses this method, so I'm not even sure that I am usign it correctly.
DocumentsService docService = new DocumentsService("MyDocsTest");
docService.setUserCredentials("w****", "*****");
DocumentsListQuery docQuery = new DocumentsListQuery();
DocumentsFeed docFeed = docService.Query(docQuery);
foreach (DocumentEntry entry in docFeed.Entries)
{
Console.WriteLine(entry.Title.Text);
}
Console.ReadKey();
Console.WriteLine();
if (File.Exists(#"testDoc.txt") == false)
{
File.WriteAllText(#"testDoc.txt", "test");
}
docService.UploadDocument(#"testDoc.txt", null); // Works Fine
docService.UploadFile(#"testDoc.txt", null, #"text/plain", false); // Throws Error
The above code will throw a GDataRequestException:
Execution of request failed: https://docs.google.com/feeds/default/private/full?convert=false
This is kind of aggrivating, seeing as this API could be so insanely helpful. Does anyone know what I am doing wrong?
After a lot of experimentation and research, I got it to work. Gonna leave this here for others in my predicament. I will leave in the using shorthands for reference.
// Start the service and set credentials
Docs.DocumentsService service = new Docs.DocumentsService("GoogleApiTest");
service.setUserCredentials("username", "password");
// Initialize the DocumentEntry
Docs.DocumentEntry newEntry = new Docs.DocumentEntry();
newEntry.Title = new Client.AtomTextConstruct(Client.AtomTextConstructElementType.Title, "Test Upload"); // Set the title
newEntry.Summary = new Client.AtomTextConstruct(Client.AtomTextConstructElementType.Summary ,"A summary goes here."); // Set the summary
newEntry.Authors.Add(new Client.AtomPerson(Client.AtomPersonType.Author, "A Person")); // Add a main author
newEntry.Contributors.Add(new Client.AtomPerson(Client.AtomPersonType.Contributor, "Another Person")); // Add a contributor
newEntry.MediaSource = new Client.MediaFileSource("testDoc.txt", "text/plain"); // The actual file to be uploading
// Create an authenticator
Client.ClientLoginAuthenticator authenticator = new Client.ClientLoginAuthenticator("GoogleApiTest", Client.ServiceNames.Documents, service.Credentials);
// Setup the uploader
Client.ResumableUpload.ResumableUploader uploader = new Client.ResumableUpload.ResumableUploader(512);
uploader.AsyncOperationProgress += (object sender, Client.AsyncOperationProgressEventArgs e) =>
{
Console.WriteLine(e.ProgressPercentage + "%"); // Progress updates
};
uploader.AsyncOperationCompleted += (object sender, Client.AsyncOperationCompletedEventArgs e) =>
{
Console.WriteLine("Upload Complete!"); // Progress Completion Notification
};
Uri uploadUri = new Uri("https://docs.google.com/feeds/upload/create-session/default/private/full?convert=false"); // "?convert=false" makes the doc be just a file
Client.AtomLink link = new Client.AtomLink(uploadUri.AbsoluteUri);
link.Rel = Client.ResumableUpload.ResumableUploader.CreateMediaRelation;
newEntry.Links.Add(link);
uploader.InsertAsync(authenticator, newEntry, new object()); // Finally upload the bloody thing
Can you check the ResponseString property of the GDataRequestException that is being thrown in order to get a detailed error message?
Capturing your requests with a tool like Fiddler will also help you a lot when trying to debug this kind of issues.
Related
I am uploading files to dropbox using the following code.
I am using the nuget package Dropbox.Api and getting the exception System.Threading.Tasks.TaskCanceledException("A task was canceled.")
From this SO Question it appears to be a timeout issue.
So how do I modify the following code to set the timeout.
public async Task<FileMetadata> UploadFileToDropBox(string fileToUpload, string folder)
{
DropboxClient client = new DropboxClient(GetAccessToken());
using (var mem = new MemoryStream(File.ReadAllBytes(fileToUpload)))
{
string filename = Path.GetFileName(fileToUpload);
try
{
string megapath = GetFullFolderPath(folder);
string megapathWithFile = Path.Combine(megapath, Path.GetFileName(Path.GetFileName(filename))).Replace("\\", "/");
var updated = client.Files.UploadAsync(megapathWithFile, WriteMode.Overwrite.Instance, body: mem);
await updated;
return updated.Result;
}
catch (Exception ex)
{
return null;
}
}
}
Try creating and initializing the client like this:
var config = new DropboxClientConfig();
config.HttpClient.Timeout = new TimeSpan(hr, min, sec); // choose values
var client = DropboxClient(GetAccessToken(), config);
Reference:
http://dropbox.github.io/dropbox-sdk-dotnet/html/M_Dropbox_Api_DropboxClient__ctor_1.htm
One more thing to keep in mind is UploadAsync will not work for files larger than 150MB as per documentation. One will have to use UploadSessionStartAsync based implementation for it. I was making the mistake without realizing it and it took ages for me to fish the problem out.
Given the following connection code:
var serviceUri = "http://machine.co.za/CRM/XRMServices/2011/Organization.svc";
var clientCredentials = new ClientCredentials
{
Windows =
{
ClientCredential = new System.Net.NetworkCredential("SOMEUSER", "SOMEPASS", "DOMAIN")
}
};
var organizationServiceProxy = new OrganizationServiceProxy(new Uri(serviceUri), null, clientCredentials, null);
// This line of code pops up a dialog?
var user = (WhoAmIResponse)organizationServiceProxy.Execute(new WhoAmIRequest());
if (user.UserId == Guid.Empty)
throw new InvalidOperationException(string.Format(#"connection to {0} cannot be established.", crmConnection.ServiceUri));
user.Dump();
If the supplied password is incorrect, the code pops up a credentials dialog.
Since the service does not have rights to interact with the desktop, the service halts as it cannot actually show a dialog.
How do I suppress the dialog, and have an exception get thrown instead. I am using dynamics 2011.
I am going to take it as a given that the CRM dynamics OrganizationServiceProxy is hardwired to pop up a dialog.
There are no configuration options or flags that turn this behavior off.
You may be mixing up usage of CrmConnection. It boils down to:
var conn = new ConnectionStringSettings("CRM", "Url=http://machine.co.za/CRM; Username=SOMEUSER; Password=SOMEPASS; Domain=SOMEDOMAIN")
var crmConnection = new CrmConnection(conn);
var crmService = new OrganizationService(crmConnection);
try
{
// connection will actually happen here. anything goes wrong, exceptions will be thrown
var user = crmService.Execute<WhoAmIResponse>(new WhoAmIRequest());
user.Dump();
}
catch (Exception ex)
{
// just a proof of concept
// ex is of type MessageSecurityException if credentials are invalid
throw new InvalidOperationException(string.Format(#"connection to {0} cannot be established.", crmConnection.ServiceUri), ex);
}
I'm trying to upload large video files to youtube via the C# API using the ResumableUploader
The code looks like this:
var settings = new YouTubeRequestSettings(Configuration.YouTubeApplicationName, Configuration.YouTubeApplicationKey, Configuration.YouTubeUsername, Configuration.YouTubePassword);
settings.Timeout = int.MaxValue;
var newVideo = new Video();
newVideo.Title = title.Trim();
newVideo.Tags.Add(new MediaCategory("Games", YouTubeNameTable.CategorySchema));
newVideo.Keywords = keywords;
newVideo.Description = description;
newVideo.YouTubeEntry.Private = false;
newVideo.Tags.Add(new MediaCategory("StarCraft2, Replay", YouTubeNameTable.DeveloperTagSchema));
var contentType = MediaFileSource.GetContentTypeForFileName(filePathToUpload);
newVideo.YouTubeEntry.MediaSource = new MediaFileSource(filePathToUpload, contentType);
var link = new AtomLink("http://uploads.gdata.youtube.com/resumable/feeds/api/users/default/uploads");
link.Rel = ResumableUploader.CreateMediaRelation;
newVideo.YouTubeEntry.Links.Add(link);
var resumableUploader = new ResumableUploader(256); //chunksize 256 kilobyte
resumableUploader.AsyncOperationCompleted += resumableUploader_AsyncOperationCompleted;
resumableUploader.AsyncOperationProgress += resumableUploader_AsyncOperationProgress;
var youTubeAuthenticator = new ClientLoginAuthenticator(Configuration.YouTubeApplicationName, ServiceNames.YouTube, Configuration.YouTubeUsername, Configuration.YouTubePassword);
youTubeAuthenticator.DeveloperKey = Configuration.YouTubeApplicationKey;
resumableUploader.InsertAsync(youTubeAuthenticator, newVideo.YouTubeEntry, new object());
I try to get the video ID when the async opertion is finished like this:
private static void resumableUploader_AsyncOperationCompleted(object sender, AsyncOperationCompletedEventArgs e)
{
try
{
var settings = new YouTubeRequestSettings(Configuration.YouTubeApplicationName, Configuration.YouTubeApplicationKey, Configuration.YouTubeUsername, Configuration.YouTubePassword);
var request = new YouTubeRequest(settings);
Video v = request.ParseVideo(e.ResponseStream);
}
catch (Exception ex)
{
//Upload has been disturbed.
}
}
The problem is. Sometime there is a problem with the upload, shaky connection or stuff like that. When an error occurs AsyncOperationCompleted is getting called.
Now the question is. How do I resume the upload? I can get the current position via the AsyncOperationProgress event. But how do I proceed to continue the upload?
I know this is an old question but I found it while trying to do the same thing with V3 of the YouTube API. This looks like code from an earlier version of the API so my question asking the same thing for V3 of the API may help if you upgrade.
I've pasted some older code of mine if anyone is struggling with this but I'm switching to the new version and replacing all this code. The youtube_upload object is my own rolled class and not part of the api. I'm also using ReSharper now and following their naming conventions.
//Grab the rendered YouTube video ready for upload
string content_type = MediaFileSource.GetContentTypeForFileName(youtube_upload.YouTubeFileName);
MediaFileSource media_file_source = new MediaFileSource(youtube_upload.YouTubeFileName, content_type);
//Generate a media stream and move to the currently uploaded position within it
media_stream_resume = media_file_source.GetDataStream();
media_stream_resume.Seek(youtube_upload.CurrentPosition, SeekOrigin.Begin);
youtube_uploading_id = youtube_upload.YouTubeID;
//Attempt to resume the upload
resumable_uploader.ResumeAsync(youtube_authenticator, youtube_upload.ResumeUri,
youtube_upload.httpVerb, media_stream_resume, content_type, youtube_upload);
youtube_upload.ErrorText = Constants.YouTubeStatusResuming;
youtube_upload.SaveYouTube();
I have the following code where I'm trying to download 3 different files from the users SkyDrive Account.
I'm using the SkyDrive API for Windows Phone development.
client.DownloadCompleted += new EventHandler<LiveDownloadCompletedEventArgs>(OnDownloadCompletedVI);
client.DownloadAsync(fileIdVehicleItems);
client.DownloadCompleted += new EventHandler<LiveDownloadCompletedEventArgs>(OnDownloadCompletedHI);
client.DownloadAsync(fileIdHistoryItems);
client.DownloadCompleted += new EventHandler<LiveDownloadCompletedEventArgs>(OnDownloadCompletedRI);
client.DownloadAsync(fileIdRepairItems);
When I run this, the only method that gets called is the OnDownloadCompletedVI. All the files that are being downloaded are running through this method which is causing an error.
What am I doing incorrectly?
Update
I have the following method, but I have 2 other similar methods that do the exact same thing except it loads different objects (based off of the downloaded files).
The error I'm currently receiving:
An exception of type 'System.ArgumentException' occurred in
mscorlib.ni.dll but was not handled in user code
void OnDownloadCompletedVI(object sender, LiveDownloadCompletedEventArgs e)
{
if (e.Result != null)
{
using (var stream_vi = e.Result)
{
StreamReader SRVI = new StreamReader(stream_vi);
string contentVI = "";
contentVI = SRVI.ReadToEnd();
StringReader rdr_vi = new StringReader(contentVI);
XmlSerializer serializer = new XmlSerializer(typeof(ObservableCollection<vehicle>));
ObservableCollection<vehicle> importedVehicles = new ObservableCollection<vehicle>();
importedVehicles = (ObservableCollection<vehicle>)serializer.Deserialize(rdr_vi);
StorageHelper.Save<ObservableCollection<vehicle>>(App.vehicleData, importedVehicles);
}
//e.Result.Close();
}
else
{
infoTextBlock.Text = "Error downloading file: " + e.Error.ToString();
}
}
Actually all three methods should be called. Of course, if the first method is called and throws an exception the other two won't trigger.
What you can do is either create a new client for each call, or download them in order, so when the OnDownloadCompletedVI method is complete, remove the event handler for OnDownloadCompletedVI and add the one for OnDownloadCompletedHI and then trigger the client.DownloadAsync(fileIdHistoryItems); at the end of the method.
I'm having a little difficulty figuring out what the cause of this error is. I've added FilePicker capabilities in the Manifest, and it's not like I'm trying to do anything crazy; just trying to save to a sub folder within the Documents folder...
Error: "An unhandled exception of type
'System.UnauthorizedAccessException' occurred in mscorlib.dll
Additional information: Access is denied. (Exception from HRESULT:
0x80070005 (E_ACCESSDENIED))"
I have confirmed that my User Account is Admin and that it has Full Control over folders and files. But I'm not sure what else I can try.
public void NewBTN_Click(object sender, RoutedEventArgs e)
{
var mbox = new MessageDialog("Would you like to save changes before creating a new Note?", "Note+ Confirmation");
UICommand YesBTN = new UICommand("Yes", new UICommandInvokedHandler(OnYesBTN));
UICommand NoBTN = new UICommand("No", new UICommandInvokedHandler(OnNoBTN));
mbox.Commands.Add(YesBTN);
mbox.Commands.Add(NoBTN);
mbox.DefaultCommandIndex = 1;
mbox.ShowAsync().Start();
}
async void OnYesBTN(object command)
{
this.Dispatcher.Invoke(Windows.UI.Core.CoreDispatcherPriority.Normal, (s, a) =>
{
// User clicked yes. Show File picker.
HasPickedFile = true;
}, this, null);
if (HasPickedFile)
{
FileSavePicker savePicker = new FileSavePicker();
savePicker.SuggestedStartLocation = PickerLocationId.DocumentsLibrary;
// Dropdown of file types the user can save the file as
savePicker.FileTypeChoices.Add("Cascading Stylesheet", new List<string>() { ".css" });
savePicker.FileTypeChoices.Add("Hypertext Markup Language", new List<string>() { ".html" });
savePicker.FileTypeChoices.Add("Plain Text", new List<string>() { ".txt" });
// Default extension if the user does not select a choice explicitly from the dropdown
savePicker.DefaultFileExtension = ".txt";
// Default file name if the user does not type one in or select a file to replace
savePicker.SuggestedFileName = "New Note";
StorageFile savedItem = await savePicker.PickSaveFileAsync();
if (null != savedItem)
{
// Application now has read/write access to the saved file
StorageFolder sFolder = await StorageFolder.GetFolderFromPathAsync(savedItem.Path);
try
{
StorageFile sFile = await sFolder.GetFileAsync(savedItem.FileName);
IRandomAccessStream writeStream = await sFile.OpenAsync(FileAccessMode.ReadWrite);
IOutputStream oStream = writeStream.GetOutputStreamAt(0);
DataWriter dWriter = new DataWriter(oStream);
dWriter.WriteString(Note.Text);
await dWriter.StoreAsync();
oStream.FlushAsync().Start();
// Should've successfully written to the file that Windows FileSavePicker had created.
}
catch
{
var mbox = new MessageDialog("This file does not exist.", "Note+ Confirmation");
UICommand OkBTN = new UICommand("Ok", new UICommandInvokedHandler(OnOkBTN));
mbox.Commands.Add(OkBTN);
mbox.DefaultCommandIndex = 1;
mbox.ShowAsync().Start();
}
}
}
}
public void OnOkBTN(object command)
{
this.Dispatcher.Invoke(Windows.UI.Core.CoreDispatcherPriority.Normal, (s, a) =>
{
// Do something here.
}, this, null);
}
public void OnNoBTN(object command)
{
this.Dispatcher.Invoke(Windows.UI.Core.CoreDispatcherPriority.Normal, (s, a) =>
{
// Don't save changes. Just create a new blank Note.
Note.Text = String.Empty;
}, this, null);
}
How can I write to a file that was created by the FileSavePicker?
You don't need to call StorageFolder.GetFolderFromPathAsync(savedItem.Path) and sFolder.GetFileAsync(savedItem.FileName). You must remove these two lines because they throw exception.
You should use the StorageFile object which has been returned by method savePicker.PickSaveFileAsync(), because that object has all permissions. Then you can simply call savedItem.OpenAsync(FileAccessMode.ReadWrite).
You probably do not have "Document Library Access" enabled in the capabilities portion of the appxmanifest of your app. Without this capability, windows will restrict access to the file system. There are similar capabilities for music, video, and picture libraries.
You have already added "File Picker" to the declarations portion, which is probably not what you want. The "File Picker" declaration indicates that if some other application invokes the file picker, your app will be listed as a possible source of files.
I've also found that adding Video or Picture Libraries access capability in Manifest only takes effect after restarting Windows 10.
Maybe it is an issue with my computer, but I think it is worth to share.