Rediret Uri changes automatically - c#

I am using the below code to integrate google drive with my C# example:
protected void Button1_Click(object sender, EventArgs e)
{
UserCredential credential = GoogleWebAuthorizationBroker.AuthorizeAsync(
new ClientSecrets
{
ClientId = "********************",
ClientSecret = "********************"
},
new[] { DriveService.Scope.DriveFile },
"user",
CancellationToken.None).Result;
// Create the service.
var service = new DriveService(new BaseClientService.Initializer()
{
HttpClientInitializer = credential,
ApplicationName = "Drive API Sample",
});
File body = new File();
body.Title = "My document";
body.Description = "A test document";
body.MimeType = "image/jpeg";
string path = "";
byte[] byteArray = System.IO.File.ReadAllBytes("D:\\babita_backup\\Babita\\GoogledriveIntegration\\Koala.jpg");
System.IO.MemoryStream stream = new System.IO.MemoryStream(byteArray);
try
{
FilesResource.InsertMediaUpload request = service.Files.Insert(body, stream, "image/jpeg");
request.Upload();
File file = request.ResponseBody;
// Label1.Text = file.Id;
}
catch { }
}
And I have:
redirect uri as:
https://localhost:50027/GoogleAPI/callback.aspx
javascript origins as:
https://localhost:50027/
But every time when I try to login with the promt I am getting the error:
400 That’s an error.
Error: redirect_uri_mismatch
The redirect URI in the request: http://localhost:50804/authorize/ did not match a registered redirect URI.
Please note that here the port number changes automatically every time, no matter how many times I change it. Its not picking up the redirect uri that I mentioned in the app console.

you need to specify a fix port for the ASP.NET development server like How to fix a port number in asp.NET development server and add this url with the fix port to the allowed urls.

Related

Export / download file from Google Drive using C# produces an empty, zero-byte file

I'm attempting to download a file from Google Drive using C# & Google.Apis.Drive.v3 and I'm getting an empty, zero-byte file (see code below). I'm uploading files OK, but can't get the download to work. Any help would be greatly appreciated.
code
static string[] Scopes = { DriveService.Scope.Drive };
static string ApplicationName = "Test001";
private DriveService _service = null;
public async Task downloadFile(string url, string lstrDownloadFile)
{
// Authorize API access
UserCredential credential;
using (var stream = new FileStream("credentials.json", FileMode.Open, FileAccess.Read))
{
// The file token.json stores the user's access and refresh tokens, and is created
// automatically when the authorization flow completes for the first time.
string credPath = "token.json";
credential = GoogleWebAuthorizationBroker.AuthorizeAsync(
GoogleClientSecrets.Load(stream).Secrets,
Scopes,
"user",
CancellationToken.None,
new FileDataStore(credPath, true)).Result;
Debug.WriteLine("Credential file saved to: " + credPath);
}
// Create Drive API service.
_service = new DriveService(new BaseClientService.Initializer()
{
HttpClientInitializer = credential,
ApplicationName = ApplicationName,
});
// Attempt download
// Iterate through file-list and find the relevant file
FilesResource.ListRequest listRequest = _service.Files.List();
listRequest.Fields = "nextPageToken, files(id, name, mimeType, originalFilename, size)";
Google.Apis.Drive.v3.Data.File lobjGoogleFile = null;
foreach (var item in listRequest.Execute().Files)
{
if (url.IndexOf(string.Format("id={0}", item.Id)) > -1)
{
Debug.WriteLine(string.Format("{0}: {1}", item.OriginalFilename, item.MimeType));
lobjGoogleFile = item;
break;
}
}
FilesResource.ExportRequest request = _service.Files.Export(lobjGoogleFile.Id, lobjGoogleFile.MimeType);
Debug.WriteLine(request.MimeType);
MemoryStream lobjMS = new MemoryStream();
await request.DownloadAsync(lobjMS);
// At this point the MemoryStream has a length of zero?
lobjMS.Position = 0;
var lobjFS = new System.IO.FileStream(lstrDownloadFile, System.IO.FileMode.Create, System.IO.FileAccess.Write);
await lobjMS.CopyToAsync(lobjFS);
}
It's possible that it's something as simple as not having enabled the Drive API on your project.
I recommend you add the following code. There's likely a download error which is preventing the stream from being filled.
FilesResource.ExportRequest request = ...
request.MediaDownloader.ProgressChanged += progress =>
{
switch (progress.Status)
{
case DownloadStatus.Failed:
{
Console.WriteLine("Failed: " + progress.Exception?.Message);
break;
}
// other status case statements if you need them
}
};
MemoryStream lobjMS = ...
Then you can drop a breakpoint into the Failed case or look at the exception in the console.

File downloaded with Google Drive API v3 has different content

I'm working with the Google Drive API for the very first time and I need to download a simple txt file that has as only content a single line with a version number (like 2.5.1.0), but when I download the file and open it, I get something totally different.
Also, if I just download the file using any browser, it has the expected content, but not when I download it through my application.
I would appreciate any advice on this.
This is my code so far:
private void CheckForUpdates()
{
GoogleDrive drive = new GoogleDrive();
string url = drive.GetFileURL("current.txt");
HttpWebRequest request = (HttpWebRequest) WebRequest.Create(url);
string tmpPath = Path.Combine(Path.GetTempPath(), "current.txt");
request.Timeout = 5000;
WebClient response = new WebClient();
response.DownloadFile(url, tmpPath);
}
public string GetFileURL(string fileName)
{
DriveService service = GetDriveService();
// Define parameters of request.
FilesResource.ListRequest listRequest = service.Files.List();
listRequest.PageSize = 10;
listRequest.Fields = "nextPageToken, files(id, name, parents, properties, shared, webContentLink, webViewLink, fullFileExtension, capabilities)";
listRequest.Q = string.Format("(name contains '{0}')", fileName);
IList<Google.Apis.Drive.v3.Data.File> files = listRequest.Execute().Files;
if (files.Count > 0)
{
string url = files[0].WebContentLink;
string id = files[0].Id;
return url;
}
return "";
}
private DriveService GetDriveService()
{
UserCredential credential;
DriveService service;
using (var stream = new FileStream(_pathClave, FileMode.Open, FileAccess.Read))
{
string credPath = System.Environment.GetFolderPath(System.Environment.SpecialFolder.Personal);
credPath = _pathResult;
credential = GoogleWebAuthorizationBroker.AuthorizeAsync(
GoogleClientSecrets.Load(stream).Secrets,
Scopes,
"user",
CancellationToken.None,
new FileDataStore(credPath, true)).Result;
}
// Create Drive API service.
service = new DriveService(new BaseClientService.Initializer()
{
HttpClientInitializer = credential,
ApplicationName = ApplicationName,
});
return service;
}
This is the link: https://drive.google.com/uc?id=0B3P8S21qYracclVaamM2Skp4bzA&export=download
Imports System.Net
Imports System.ComponentModel
Dim Str As IO.Stream
Dim srRead As IO.StreamReader
Dim NewVer As String = ""
Dim req As WebRequest = WebRequest.Create("WebContentLink")
Dim resp As WebResponse = req.GetResponse
Str = resp.GetResponseStream
srRead = New IO.StreamReader(Str)
NewVer = srRead.ReadToEnd.Trim
vb code worked good for me may help

Cannot Upload to Google Drive

I am trying to upload a JSON file to the root folder in whoever's GDrive. I've search all through Google for an answer while trying to fix it myself. No matter what I've done request.Responsebody always returns null. Here I tried to do a blank .txt file (which still doesn't work).
This is the code to get the credentials and then it sets the resulting DeviceService to variable.
//GDrive Cred
public static void GetCred()
{
//Get Credential
UserCredential credential;
using (var stream =
new FileStream(Path + "\\client_secret.json", FileMode.Open, FileAccess.Read))
{
string credPath = System.Environment.GetFolderPath(
System.Environment.SpecialFolder.Personal);
credPath = System.IO.Path.Combine(credPath, ".credentials/drive-dotnet-quickstart");
credential = GoogleWebAuthorizationBroker.AuthorizeAsync(
GoogleClientSecrets.Load(stream).Secrets,
Scopes,
"user",
CancellationToken.None,
new FileDataStore(credPath, true)).Result;
Console.WriteLine("Credential file saved to: " + credPath);
}
// Create Drive API service.
var service = new DriveService(new BaseClientService.Initializer()
{
HttpClientInitializer = credential,
ApplicationName = ApplicationName,
});
mService = service;
}
and this is the code to upload the file.
//Save JSON to GDrive
public static void SaveJSONtoDrive()
{
GetCred();
// File's metadata.
Google.Apis.Drive.v2.Data.File body = new Google.Apis.Drive.v2.Data.File();
body.Title = "ATGEntries.txt";
body.Description = "Database JSON for Adventurer's Tour Guide";
//body.MimeType = "application/json";
body.MimeType = "text/plain";
body.Parents = new List<ParentReference>() { new ParentReference() { Id = "root" } };
// File's content.
byte[] byteArray = System.IO.File.ReadAllBytes(Path + "\\ATGEntries.txt");
MemoryStream stream = new MemoryStream(byteArray);
try
{
FilesResource.InsertMediaUpload request = mService.Files.Insert(body, stream, "text/plain");
request.UploadAsync();
Google.Apis.Drive.v2.Data.File file = request.ResponseBody;
// Uncomment the following line to print the File ID.
Console.WriteLine("File ID: " + file.Id);
}
catch (Exception e)
{
Console.WriteLine("An error occurred: " + e.Message);
}
}
Can someone please attempt to help me fix this strange error?
I cannot believe this isn't anywhere so I will answer my own question in the hopes that it will help someone else along the way.
Pay attention to the line where you set the 'credPath' variable
credPath = System.IO.Path.Combine(credPath, ".credentials/drive-dotnet-quickstart");
make sure the part after ".credentials/" needs to be the same name as whatever you named your OAuth 2.0 client ID in the Google Developers Console. This should fix the problem.

I want to upload video on youtube using client side login. without open web page permission

When I upload video to YouTube using client side login. The first time redirect to UI for permissions.
I want upload without redirect to web page. I need to execute this code on server.
Here is my code.
private async Task<string> Run(string title, string description, string filepath)
{
var videoID = string.Empty;
try
{
logger.Info(string.Format("[uploading file on youTube Title: {0}, Description: {1}, filePath: {2}]", title, description, filepath));
UserCredential credential;
using (var stream = new FileStream("client_secret.json", FileMode.Open, FileAccess.Read))
{
logger.Info("[Load credentials from google start]");
credential = await GoogleWebAuthorizationBroker.AuthorizeAsync(
GoogleClientSecrets.Load(stream).Secrets,
// This OAuth 2.0 access scope allows an application to upload files to the
// authenticated user's YouTube channel, but doesn't allow other types of access.
new[] { YouTubeService.Scope.YoutubeUpload },
"user",
CancellationToken.None
);
logger.Info("[Load credentials from google end]");
}
logger.Info("YouTubeApiKey {0}", System.Configuration.ConfigurationManager.AppSettings["YoutubeApiKey"]);
var youtubeService = new YouTubeService(new BaseClientService.Initializer()
{
HttpClientInitializer = credential,
ApiKey = System.Configuration.ConfigurationManager.AppSettings["YoutubeApiKey"],
ApplicationName = System.Configuration.ConfigurationManager.AppSettings["ApplicationName"]
});
logger.Info("ApplicationName {0}", System.Configuration.ConfigurationManager.AppSettings["ApplicationName"]);
var video = new Video();
video.Snippet = new VideoSnippet();
video.Snippet.Title = title;
video.Snippet.Description = description;
//video.Snippet.Tags = new string[] { "tag1", "tag2" };
// video.Snippet.CategoryId = "22"; // See https://developers.google.com/youtube/v3/docs/videoCategories/list
video.Status = new VideoStatus();
video.Status.PrivacyStatus = "public"; // or "private" or "public"
var filePath = filepath; // Replace with path to actual movie file.
using (var fileStream = new FileStream(filePath, FileMode.Open))
{
var videosInsertRequest = youtubeService.Videos.Insert(video, "snippet,status", fileStream, "video/*");
videosInsertRequest.ProgressChanged += videosInsertRequest_ProgressChanged;
videosInsertRequest.ResponseReceived += videosInsertRequest_ResponseReceived;
await videosInsertRequest.UploadAsync();
}
return videoID;
}
catch (Exception e)
{
logger.ErrorException("[Error occurred in Run ]", e);
}
return videoID;
}
void videosInsertRequest_ProgressChanged(Google.Apis.Upload.IUploadProgress progress)
{
switch (progress.Status)
{
case UploadStatus.Uploading:
Console.WriteLine("{0} bytes sent.", progress.BytesSent);
break;
case UploadStatus.Failed:
Console.WriteLine("An error prevented the upload from completing.\n{0}", progress.Exception);
break;
}
}
void videosInsertRequest_ResponseReceived(Video video)
{
Console.WriteLine("Video id '{0}' was successfully uploaded.", video.Id);
}
Your code is doing is doing everything correctly. The YouTube API doesn't allow for pure server authentication (Service Account). The only option available to you to upload files will be to use Oauth2 and authenticate your code the first time.
I just sugest you make one small change add filedatastore. This will store the authentication for you. Once you have authenticated it via the web browser you wont need to do it again.
/// <summary>
/// Authenticate to Google Using Oauth2
/// Documentation https://developers.google.com/accounts/docs/OAuth2
/// </summary>
/// <param name="clientId">From Google Developer console https://console.developers.google.com</param>
/// <param name="clientSecret">From Google Developer console https://console.developers.google.com</param>
/// <param name="userName">A string used to identify a user.</param>
/// <returns></returns>
public static YouTubeService AuthenticateOauth(string clientId, string clientSecret, string userName)
{
string[] scopes = new string[] { YouTubeService.Scope.Youtube, // view and manage your YouTube account
YouTubeService.Scope.YoutubeForceSsl,
YouTubeService.Scope.Youtubepartner,
YouTubeService.Scope.YoutubepartnerChannelAudit,
YouTubeService.Scope.YoutubeReadonly,
YouTubeService.Scope.YoutubeUpload};
try
{
// here is where we Request the user to give us access, or use the Refresh Token that was previously stored in %AppData%
UserCredential credential = GoogleWebAuthorizationBroker.AuthorizeAsync(new ClientSecrets { ClientId = clientId, ClientSecret = clientSecret }
, scopes
, userName
, CancellationToken.None
, new FileDataStore("Daimto.YouTube.Auth.Store")).Result;
YouTubeService service = new YouTubeService(new YouTubeService.Initializer()
{
HttpClientInitializer = credential,
ApplicationName = "YouTube Data API Sample",
});
return service;
}
catch (Exception ex)
{
Console.WriteLine(ex.InnerException);
return null;
}
}
Call the above method like this:
// Authenticate Oauth2
String CLIENT_ID = "xxxxxx-d0vpdthl4ms0soutcrpe036ckqn7rfpn.apps.googleusercontent.com";
String CLIENT_SECRET = "NDmluNfTgUk6wgmy7cFo64RV";
var service = Authentication.AuthenticateOauth(CLIENT_ID, CLIENT_SECRET, "SingleUser");
Your code will need to be authenticated the first time. Once its authenticated filedatastore stores a file in %appData% on your machine. Every time it runs after that it will use the refresh token stored in %appData% to gain access again.
Code ripped from YouTube API Sample project

Google api authorization raises the browser

I'm writing a small desktop app that will upload file to google drive. So everything is fine when I'm sign in my google account, but when I'm not, program raises browser on this page "https://accounts.google.com/ServiceLogin". I'm using this code:
ClientSecrets secret = new ClientSecrets();
secret.ClientId = "my_client_id";
secret.ClientSecret = "my_client_secret";
UserCredential credential = GoogleWebAuthorizationBroker.AuthorizeAsync(secret, new[] { DriveService.Scope.Drive }, "user", CancellationToken.None).Result;
var service = new DriveService(new BaseClientService.Initializer() { HttpClientInitializer = credential, ApplicationName = "TestUpload" });
File body = new File();
body.Title = "Title123";
body.Description = "Decription123";
body.MimeType = "image/png";
byte[] arr = System.IO.File.ReadAllBytes(fileName);
System.IO.MemoryStream stream = new System.IO.MemoryStream(arr);
FilesResource.InsertMediaUpload request = service.Files.Insert(body, stream, "image/png");
request.Upload();
So how can I authorize programmatically with out raising the browser?
Most of your problem is the fact that you are not saving the Authentication. You are requesting access but not saving it. In the following example fileDataStore stores the authentication information in a file on your pc in %AppData% this way next time you run the program no authentication will be needed, and it also wont require that you are logged into Google at the time.
//Scopes for use with the Google Drive API
string[] scopes = new string[] { DriveService.Scope.Drive,
DriveService.Scope.DriveFile};
// here is where we Request the user to give us access, or use the Refresh Token that was previously stored in %AppData%
UserCredential credential =
GoogleWebAuthorizationBroker
.AuthorizeAsync(new ClientSecrets { ClientId = CLIENT_ID
, ClientSecret = CLIENT_SECRET }
,scopes
,Environment.UserName
,CancellationToken.None
,new FileDataStore("Daimto.GoogleDrive.Auth.Store")
).Result;
DriveService service = new DriveService(new BaseClientService.Initializer()
{
HttpClientInitializer = credential,
ApplicationName = "Drive API Sample",
});
public static File uploadFile(DriveService _service, string _uploadFile, string _parent) {
if (System.IO.File.Exists(_uploadFile))
{
File body = new File();
body.Title = System.IO.Path.GetFileName(_uploadFile);
body.Description = "File uploaded by Diamto Drive Sample";
body.MimeType = GetMimeType(_uploadFile);
body.Parents = new List<ParentReference>() { new ParentReference() { Id = _parent } };
// File's content.
byte[] byteArray = System.IO.File.ReadAllBytes(_uploadFile);
System.IO.MemoryStream stream = new System.IO.MemoryStream(byteArray);
try
{
FilesResource.InsertMediaUpload request = _service.Files.Insert(body, stream, GetMimeType(_uploadFile));
request.Upload();
return request.ResponseBody;
}
catch (Exception e)
{
Console.WriteLine("An error occurred: " + e.Message);
return null;
}
}
else {
Console.WriteLine("File does not exist: " + _uploadFile);
return null;
}
}
This code is ripped from the Google Drive C# upload tutorial, if you want more information on what its doing and how it works you may want to check that. There is also a working Sample project in the Google-Dotnet-Samples project on GitHub. The tutorial is based upon that sample project.

Categories

Resources