How to upload to OneDrive using Microsoft Graph Api in c# - c#

I have been trying to upload to a OneDrive account and I am hopelessly stuck not being able to upload neither less or greater than 4MB files. I have no issues accessing the drive at all, since I have working functions that create a folder, rename files/folders, and a delete files/folders.
https://learn.microsoft.com/en-us/graph/api/driveitem-put-content?view=graph-rest-1.0&tabs=csharp
This documentation on Microsoft Graph API is very friendly to HTTP code, and I believe I am able to fairly "translate" the documentation to C#, but still fail to grab a file and upload to OneDrive. Some places online seem to be using byte arrays? Which I am completely unfamiliar with since my primary language is C++ and we just use ifstream/ofstream. Anyways, here is the portion of code in specific (I hope this is enough):
var item = await _client.Users[userID].Drive.Items[FolderID]//"01YZM7SMVOQ7YVNBXPZFFKNQAU5OB3XA3K"].Content
.ItemWithPath("LessThan4MB.txt")//"D:\\LessThan4MB.txt")
.CreateUploadSession()
.Request()
.PostAsync();
Console.WriteLine("done printing");
As it stands, it uploads a temporary file that has a tilde "~" in the OneDrive (like as if I was only able to open but not import any data from the file onto it). If I swap the name of the file so it includes the file location it throws an error:
Message: Found a function 'microsoft.graph.createUploadSession' on an open property. Functions on open properties are not supported.

Try this approach with memory stream and PutAsync<DriveItem> request:
string path = "D:\\LessThan4MB.txt";
byte[] data = System.IO.File.ReadAllBytes(path);
using (Stream stream = new MemoryStream(data))
{
var item = await _client.Me.Drive.Items[FolderID]
.ItemWithPath("LessThan4MB.txt")
.Content
.Request()
.PutAsync<DriveItem>(stream);
}
I am assuming you have already granted Microsoft Graph Files.ReadWrite.All permission. Check your API permission. I tested this code snippet with pretty old Microsoft.Graph library version 1.21.0. Hopefully it will work for you too.

Related

SharePoint file size is different than source file after uploading

We are developing a WinForms (desktop) application in .Net framework 4.5.2 with C# language.
Using Microsoft.Graph library 1.21.0 and Micorosft.Graph.Core 1.19.0 version to copy files from windows local machine to SharePoint/OneDrive cloud storage.
I tried with Microsoft.Graph library 3.18.0 and Micorosft.Graph.Core 1.22.0 and .Net 4.6.2 framework but same issue.
We are copy files less than 4 MB using following method
uploadedItem = await
MainDrive.Root.ItemWithPath(Uri.EscapeDataString(targetFilePath)).Content.Request().PutAsync(stream,
cancellationToken);
Files larger than 4 MB are being copied using ChunkUpload
var session = await MainDrive.Root.ItemWithPath(targetFilePath).CreateUploadSession().Request().PostAsync(cancellationToken);
var provider = new ChunkedUploadProvider(session, graphClient, stream, OneDriveChunkSize);
var chunkRequests = provider.GetUploadChunkRequests();
var trackedExceptions = new List<Exception>();
foreach (UploadChunkRequest request in chunkRequests)
{
await CheckforBandwidthThrotelling(fileInfo.Name, fp, cancellationToken);
UploadChunkResult result = await provider.GetChunkRequestResponseAsync(request, trackedExceptions);
if (result.UploadSucceeded)
{
uploadedItem = result.ItemResponse;
}
}
Issue: We are getting the file size larger than source after copying files to SharePoint. It works well in case of OneDrive personal using same api's and method.
I found that it's due to Metadata get added to file. We are not maintaining any multiple version of files on SharePoint.
This issue is mostly with office files (docs, xlsx and ppt) but not with txt files of any size.
The application differentiate the files mismatch on source and destination based upon timestamp and file size. As file found different size in next run, it copies the file again.
The same issue is reported on github
Some more description about issue
I am looking for a workaround to compare file size between source and destination to decide whether file need to copy again.

c# file upload to AWS

Hello and apologies in advance for the noob question. I'm also relatively new to c#. In ASP.NET core, I can save files via the file upload control to AWS S3. However, this relies on me saving the files first to a location on my hard drive and then I can send in the path for the AWS code to pick it up from there. I'm sure it will be a simple answer but I can't find this after a few days' searching. As anyone who uses my site can upload (and later download) pdfs and jpegs, how do I either (1) save the file to a temporary location on their machine or phone, or, preferably, (2) 'somehow' send in the path so the AWS code can pick it up? There are many posts stating how you can't get at the path for security reasons but as far as I can tell, the AWS code relies on it.
Here's the AWS code I'm using (from their documentation). It works for me (overwrites the last file and there's no error handling yet, but one thing at once for me). The bucketName and keyName are set up elsewhere.
It's how to send in the filePath without saving it anywhere that I can't get to work. The error just says that it can't find the file, understandably.
public void FileProcess(string filePath)
{
client = new AmazonS3Client(Amazon.RegionEndpoint.EUWest2);
Amazon.S3.Model.PutObjectRequest request = new Amazon.S3.Model.PutObjectRequest()
{
BucketName = bucketName,
Key = keyName,
FilePath = filePath
};
PutObjectResponse response2 = client.PutObject(request);
}

ASP.NET Core - How to upload a zip file if there does not exist a client-side UI for file selection

I have a unique scenario in which I'd like the end result to help me upload a zip file. Here is what is happening in my workflow:
Our user is given an application on their local machine. With a click of a button, it will copy files and a zip file to remote-machine-1.
On remote-machine-2, it is running a .NET Core web app.
On remote-machine-1, I'd like to ping an endpoint off the web app in order to upload the zip file to remote-machine-2. However, the caveat is that the user will not be able to specify where this zip file is - the location of the zip file already known due to the structure of how the files and zip file are copied over in the first place.
So the question remains, with the code below - how do I pass in an IFormFile object when I call the endpoint localhost:5000/PublishTargetAsync?file=[???]? Or is there another workaround?
public async Task<bool> PublishTargetAsync(IFormFile file)
{
if (file != null)
{
using (var fileStream = new FileStream(Path.Combine(_targetOutputDirectory.ToFileSystemPath(), file.Name), FileMode.Create))
{
await file.CopyToAsync(fileStream);
}
}
return true;
}
A simple, but non optimized approach would be to use HttpClient and post the file contents as a base64 encoded string as Json using sample code similar to what is in my link. From there you could work your way back to using HttpWebRequests and a network stream and crafting the Http request by hand if necessary for performance, but the above approach should work for most small files. You'll have to modify your PublishTargetAsync endpoint to handle a post request with the right type.

WP8.1: Exporting data to "reachable" .txt file

I am creating an app that is tracking GPS data (latitude, longitude, altitude). So far I've managed to create a listbox that gets an extra line everytime another set of coordinates is made.
I tried writing it to file with this function.
private async Task WriteToFile()
{
string ResultString = string.Join("\n", locationData.ToArray());
byte[] fileBytes = System.Text.Encoding.UTF8.GetBytes(ResultString);
StorageFolder local = Windows.Storage.ApplicationData.Current.LocalFolder;
var dataFolder = await local.CreateFolderAsync("DataFolder", CreationCollisionOption.OpenIfExists);
var file = await dataFolder.CreateFileAsync("DataFile.txt", CreationCollisionOption.ReplaceExisting);
using (var s = await file.OpenStreamForWriteAsync())
{
s.Write(fileBytes, 0, fileBytes.Length);
}
}
I can read this file, but I can't view this "DataFile.txt" anywhere in Files app.
I tried using WP Power Tools, but it doesn't work with 8.1, I am unable to update Visual Studio 2013 in order to get ISExplorer.exe working and
IsoStoreSpy keeps crashing everytime I try to connect my Lumia 620.
But all of this looks too complitated to me. Is there any other way of getting this .txt file without messing with IsolatedStorage? I feel like I'm missing out on something so simple here, I just can't believe that such basic thing as writing output to .txt, that can be later used by PC, couldn't be available.
You're storing the file in your app's local storage (Windows.Storage.ApplicationData.Current.LocalFolder), which is the same as Isolated Storage.
The Files app can see only public locations not app-specific locations.
There are several ways your app can share this file more globally:
Use the share contract to let the user share the file to wherever they'd like (OneNote, Email, etc.). See Sharing and exchanging data
Let the user choose where to save the file with a FileSavePicker. See How to save files through file pickers
Save the file on the SD card. See Access the SD card in Windows Phone apps.
Save the file to the user's OneDrive. See Guidelines for accessing OneDrive from an app
Save to a RoamingFolder so the file can be read by the same app on a Windows PC, which can then export using similar methods (especially a file picker) but on the desktop device. See Quickstart: Roaming app data

Get last modified date of a remote file

I have an app with which at startup it downloads a file from a remote location (through the net) and parses it's contents.
I am trying to speed up the process of startup as the bigger the file gets the slower the app starts.
As a way to speed up the process I thought of getting the last modified date of the file and if it is newer from the file on the user's pc then and only then download it.
I have found many ways to do it online but none of them are in C# (for windows store apps). Does anybody here know of a way of doing this without the need to download the file? If I am to download the file then the process is sped up at all.
My C# code for downloading the file currently is this
const string fileLocation = "link to dropbox";
var uri = new Uri(fileLocation);
var downloader = new BackgroundDownloader();
StorageFile file = await ApplicationData.Current.LocalFolder.CreateFileAsync("feedlist.txt",CreationCollisionOption.ReplaceExisting);
DownloadOperation download = downloader.CreateDownload(uri, file);
await download.StartAsync();
If it helps the file is stored in dropbox but if any of you guys have a suggestion for another free file hosting service I am open to suggestions
Generally, you can check the file time by sending HEAD request and parsing/looking HTTP header response for a Last-Modified filed. The remote server should support it and DropBox does not support this feature for direct links (only via API). But DropBox have another feature, the headers have the etag field. You should store it and check in the next request. If it changed - the file has been changed too. You can use this tool to check the remote file headers.

Categories