Using Google Drive V3 API and service account auth, WebViewLink is null - c#

I am using google drive v3 api to upload a file and then preview it in browser using web view link in the response. But web view link is coming null. When i was using v2, I was able to do it using alternate link.
I have not set the parent ref so I am assuming as per the documentation, the file is stored in my drive folder(root) of service account. As I couldn't login to service account, so I shared the file with my existing test gmail account and it was shared.
My question is how can I open the file in browser using System.Diagnostics.Process.Start(newFile.WebViewLink);
here is my code:
{
File fileInGoogleDrive = Utils.uploadToDrive(service, pathOfTheFileToBeUploaded, "root");
Permission toShare = new Permission();
toShare.EmailAddress = "xyz#gmail.com";
toShare.Type = "user";
toShare.Role = "reader";
PermissionsResource.CreateRequest createRequest = service.Permissions.Create(toShare, fileInGoogleDrive.Id);
createRequest.Execute();
return fileInGoogleDrive.WebViewLink; //THIS IS NULL
}
here is the upload code:
public static File uploadToDrive(DriveService _service, string _uploadFile, string _parent = "root")
{
if (!String.IsNullOrEmpty(_uploadFile))
{
File fileMetadata = new File();
fileMetadata.Name = System.IO.Path.GetFileName(_uploadFile);
fileMetadata.MimeType = GetMimeType(_uploadFile);
//fileMetadata.Parents = new List<FilesResource>() { new FilesResource() {}};
try
{
byte[] byteArray = System.IO.File.ReadAllBytes(_uploadFile);
System.IO.MemoryStream stream = new System.IO.MemoryStream(byteArray);
FilesResource.CreateMediaUpload request = _service.Files.Create(fileMetadata, stream, GetMimeType(_uploadFile));
request.Upload();
return request.ResponseBody;
}
catch (System.IO.IOException iox)
{
// Log
return null;
}
catch (Exception e) // any special google drive exceptions??
{
//Log
return null;
}
}
else
{
//Log file does not exist
return null;
}
}
Could anyone please guide me here?

Just wanted to post the syntax in C# for the above. From the google documentation, it says we have to do a get on files and then request using Fields property.
"Getting the fields in google drive v3 api for .net"
File resultFile = null;
FilesResource.ListRequest listRequest = _service.Files.List();
/* Specify camelCase format to specify fields. You can also check in debug mode the files properties before requesting which will be null. All properties will be capitalized so make th efirst letter as small(camel case standard)*/
listRequest.Fields = "files(id, webViewLink, size)";
var files = listRequest.Execute().Files;
if (files != null && files.Count > 0)
{
foreach (var file in files)
{
if (file.Id == _fileId)
{
Console.WriteLine("{0}, {1}, {2}", file.Id, file.WebViewLink, file.Size);
resultFile = file;
}
}
}

Related

How can I extract Metadata from StreamContent object that comes from Web API?

I have an application which you can upload Image. It sends the streamcontent via web api.
I'm using metadataextractor library and it works when I only use Stream object. but when it is streamcontent, reading metadata doesn't work.
This is my controller and client service code
[HttpPost]
public void UploadFile(IEnumerable<IFormFile> files)
{
if (!files.Any())
{
Response.StatusCode = (int)System.Net.HttpStatusCode.NoContent;
return;
}
foreach (var file in files)
{
using (Stream stream = file.OpenReadStream())
{
_clientService.UploadStip(stream);
}
}
}
public void UploadStip(Stream stream)
{
//I have removed some codes because sending data into the end point already works
var response = _client.PostAsync("uploadphoto", new StreamContent(stream));
response.Wait();
if (response.Result.StatusCode != System.Net.HttpStatusCode.OK)
{
throw new Exception("Error when uploading photo");
}
}
Now the challenge here is that I get an error when receiving and reading Metadata of the StreamContent object.
Here's my code for the end-point:
public void UploadPhoto(Stream content)
{
// Read all metadata from the image
var directories = ImageMetadataReader.ReadMetadata(content); //this part always throw
//System.ArgumentException: 'Must support seek
//Parameter name: stream'
// Find the so-called Exif "SubIFD" (which may be null)
var subIfdDirectory = directories.OfType<ExifSubIfdDirectory>().FirstOrDefault();
// Read the DateTime tag valueWW
var datetime = subIfdDirectory?.GetDateTime(ExifDirectoryBase.TagDateTimeOriginal);
var gps = directories.OfType<GpsDirectory>().FirstOrDefault();
var location = gps.GetGeoLocation();
var latitude = Math.Round(location.Latitude, 6);
var longtitude = Math.Round(location.Longitude, 6);
}
I'm not sure how to get metadata out of StreamContent.

Bot Builder SDK 4 How to work with attachments?

Bot Builder SDK 4 (dotnet) How to work with attachments ? I tried to use the example of BotBuilder-Samples 15.handling-attachments, but got 401 Unauthorized error with Skype channel.
foreach (var file in activity.Attachments)
{
// Determine where the file is hosted.
var remoteFileUrl = file.ContentUrl;
// Save the attachment to the system temp directory.
var localFileName = Path.Combine(Path.GetTempPath(), file.Name)
// Download the actual attachment
using (var webClient = new WebClient())
{
webClient.DownloadFile(remoteFileUrl, localFileName); <-- 401 here
}
I have discovered solution at github.com discussion Skype Can not receive attachment? #3623 which I also have just tested with success.
I see minimal modification to your code sample as follows:
string channelToken = null;
if ((activity.ChannelId.Equals("skype", StringComparison.InvariantCultureIgnoreCase))
{
var credentials = new MicrosoftAppCredentials(youBotAppId, yourBotAppPassword);
channelToken = await credentials.GetTokenAsync();
}
foreach (var file in activity.Attachments)
{
// Determine where the file is hosted.
var remoteFileUrl = file.ContentUrl;
// Save the attachment to the system temp directory.
var localFileName = Path.Combine(Path.GetTempPath(), file.Name)
// Download the actual attachment
using (var webClient = new WebClient())
{
if (!string.IsNullOrWhiteSpace(channelToken))
{
webClient.DefaultRequestHeaders.Authorization =
new AuthenticationHeaderValue("Bearer", channelToken);
}
webClient.DownloadFile(remoteFileUrl, localFileName);
}

Uploading to Azure File Share from a Razor Page

I am trying to find an example of uploading a file to an Azure file share from a razor page. I would like to be able to select a file and then have that file saved to the share. I am using Visual Studio 2017, .Net Core 2.0. The only examples I am finding are for Blob storage. Any help would be much appreciated.
[HttpPost]
public IActionResult Index(Microsoft.AspNetCore.Http.IFormFile files)
{
string storageConnectionString = "connectionstring to your azure file share";
CloudStorageAccount cloudStorageAccount = CloudStorageAccount.Parse(storageConnectionString);
CloudFileClient cloudFileClient = cloudStorageAccount.CreateCloudFileClient();
CloudFileShare cloudFileShare = cloudFileClient.GetShareReference("your file share name");
cloudFileShare.CreateIfNotExistsAsync();
CloudFileDirectory rootDirectory = cloudFileShare.GetRootDirectoryReference();
CloudFile file = rootDirectory.GetFileReference(files.FileName);
TransferManager.Configurations.ParallelOperations = 64;
// Setup the transfer context and track the upoload progress
SingleTransferContext context = new SingleTransferContext();
using (Stream s1 = files.OpenReadStream())
{
var task = TransferManager.UploadAsync(s1, file);
task.Wait();
}
return RedirectToPage("/Index");
}
Here is a simple method I'm using to upload a single file to an endpoint.
[HttpPost]
public async Task<IActionResult> Upload(IFormFile file)
{
if (file != null)
{
using (var stream = new MemoryStream())
{
try
{
// assume a single file POST
await file.CopyToAsync(stream);
stream.Seek(0, SeekOrigin.Begin);
// now send up to Azure
var filename = file.FileName;
var storageAccount = CloudStorageAccount.Parse(<YOUR CREDS HERE>);
var client = storageAccount.CreateCloudFileClient();
var shareref = client.GetShareReference("YOUR FILES SHARE");
var rootdir = shareref.GetRootDirectoryReference();
var fileref = rootdir.GetFileReference(filename);
await fileref.DeleteIfExistsAsync();
await fileref.UploadFromStreamAsync(stream);
return Ok(new { fileuploaded = true });
}
catch (Exception ex)
{
return BadRequest(ex);
}
}
}
else
{
return BadRequest(new { error = "there was no uploaded file" });
}
}

HttpGet return error 405

Using ASP Web API, I create a method that takes an ID then deliver a pdf file, then using Google docs viewer, or similar service, to view the file,
The code looks something like this,
[HttpGet]
public HttpResponseMessage GetAttachment(string id)
{
try {
string mapping = #"\\192.168.3.3\Archieve";
string sourcedir = #"\Digital\";
string filename = id + ".pdf";
string sourceFullPath = mapping + sourcedir + filename;
byte[] dataBytes = new byte[0];
// connect to other network using custom credential
var credential = new NetworkCredential("user", "pass", "192.168.3.3");
using (new NetworkConnection(mapping, credential)) {
dataBytes = File.ReadAllBytes(sourceFullPath);
}
HttpResponseMessage response = Request.CreateResponse(HttpStatusCode.OK);
response.Content = new StreamContent(new MemoryStream(dataBytes));
response.Content.Headers.ContentDisposition = new ContentDispositionHeaderValue("attachment");
response.Content.Headers.ContentDisposition.FileName = filename;
response.Content.Headers.ContentType = new MediaTypeHeaderValue("application/pdf");
return response;
}
catch (Exception ex) {
return Request.CreateResponse(HttpStatusCode.Gone, ex.Message);
}
}
With this code, I'm able to download the pdf file when I open the link on web browser, but when I try to display it using Google docs viewer, like this
https://docs.google.com/viewerng/viewer?url=http://myserver/webapi/api/File/GetAttachment/0317101532
Google failed to display the file without error,
And when I use other service like https://www.pdfescape.com/open/ the error is The remote server returned an error: (405) Method Not Allowed.
EDIT: I think both Google Docs viewer and pdfescape need direct link to the file, can I generate direct link on Web API controller?
Try to copy the file to local, and then return the file link, something like this
[HttpGet]
public IHttpActionResult GetAttachment(string id)
{
try {
string mapping = #"\\192.168.3.3\Archieve";
string sourcedir = #"\Digital\";
string filename = id + ".pdf";
string sourceFullPath = mapping + sourcedir + filename;
byte[] dataBytes = new byte[0];
// connect to other network using custom credential
var credential = new NetworkCredential("user", "pass", "192.168.3.3");
using (new NetworkConnection(mapping, credential)) {
dataBytes = File.ReadAllBytes(sourceFullPath);
}
// write file to local
string destFullPath = string.Format("{0}/Content/Data//{2}", HttpContext.Current.Server.MapPath("~"), filename);
File.WriteAllBytes(destFullPath, dataBytes);
// return the file name,
return Ok(filename);
// then you can view your docs using Google Viewer like this
// https://docs.google.com/viewer?url=http://[YOUR_SERVER_BASE_URL]/content/data/[FILENAME]
}
catch (Exception ex) {
return Content(HttpStatusCode.PreconditionFailed, ex.Message);
}
}
Don't forget to add required permission on 'Content' folder

Web service is not transferring photos successfully

I've implemented a web API (c#) to transfer photos captured or uploaded by users on mobiles (Android and iOS) using Apache cordova
--I'm consuming this web API in Apache cordova with file transfer plugin to transfer photo with is captured or uploaded from gallery to transfer it from mobile device to my server--
problem is the chance of delivering photo is 50/50 - meaning that every request I create -to be sent to the server- , It may some times be inserted successfully or might just like I haven't done anything and nothing would be inserted into the server.
here is the code :
public string Post()
{
try
{
HttpResponseMessage result = null;
string message = "";
var httpRequest = HttpContext.Current.Request;
if (httpRequest.Files.Count > 0)
{
var docfiles = new List<string>();
foreach (string file in httpRequest.Files)
{
var postedFile = httpRequest.Files[file];
var filePath = HttpContext.Current.Server.MapPath("~/TransientStorage/" + postedFile.FileName);
postedFile.SaveAs(filePath);
docfiles.Add(filePath);
}
result = Request.CreateResponse(HttpStatusCode.Created, docfiles);
message = "Success";
}
else
{
result = Request.CreateResponse(HttpStatusCode.BadRequest);
message = "failed";
}
return (message);
}
catch(Exception ex)
{
return ("");
}
}

Categories

Resources