I have the following code:
private static void Download(DropboxClient client, string dropboxfolder, string localfolder, FileMetadata file)
{
//Console.WriteLine("Download file...");
var task1 = client.Files.DownloadAsync(dropboxfolder + "/" + file.Name);
task1.Wait();
using (var response = task1.Result)
{
Console.WriteLine("Downloaded {0} Rev {1}", response.Response.Name, response.Response.Rev);
Console.WriteLine("------------------------------");
using (Stream output = File.OpenWrite(Path.Combine(localfolder, response.Response.Name)))
{
var task2 = response.GetContentAsStreamAsync();
task2.Wait();
using (Stream input = task2.Result)
{
input.CopyTo(output);
}
}
Console.WriteLine("------------------------------");
}
}
how do I modify it such that the output file will have the same timestamp as the file in dropbox.
[EDIT] I know how to set a date of a file in C#, but I don't know how to get that timestamp from dropbox in order to call that method. The question I am asking is more generic than that because perhaps there is an option on the dropbox API that allows the file to be set by dropbox.
When you use DownloadAsync to download a file, that also returns the FileMetadata for that file. You can check the FileMetadata.ServerModified or FileMetadata.ClientModified to get the modified time as desired.
You can find an example of getting the metadata here.
Related
my field is
public IFormFileCollection FileNames { get; set; }
i get multiple file from postman (form-data) and post
in api-controller i get fields of send with postman
my problem here,i need to path of files, how i can get path of FromFile?
updated code :
using (var fileStream = new FileStream(fileName.FileName, FileMode.Create,FileAccess.Write))
{
await fileName.CopyToAsync(fileStream);
fileStream.Dispose();
var request = MyOperationOnFile(fileStream.Name);
...
}
get this exception for second file(first file is ok):
"Cannot access a disposed object.\r\nObject name: 'FileBufferingReadStream'."
if dont use .dispose() get this exception for first file :
Failed to send: Microsoft.AspNetCore.Http.FormFile, with error:The process cannot access the file 'porjectLocation\file' because it is being used by another process
In fact, if you want to upload files, you do not need to know the original path of the files, but only need to create the path you need to upload.
The following is a case of uploading multiple files, please refer to it:
[HttpPost("UploadFile")]
public async Task<IActionResult> UploadFile(IFormFileCollection files)
{
foreach (var fileName in files)
{
var filesPath = Directory.GetCurrentDirectory() + "/Uploadfiles";
if (!System.IO.Directory.Exists(filesPath))//create path
{
Directory.CreateDirectory(filesPath);
}
var path = Path.Combine(filesPath, Path.GetFileName(fileName.FileName));//the path to upload
await fileName.CopyToAsync(new FileStream(path, FileMode.Create));
}
return Ok();
}
Here is the result:
The form file that you received from the request are actually the stream in memory of the files, you will need to save it on the disk or on your database. Check the examples in the documentation:
https://learn.microsoft.com/en-us/aspnet/core/mvc/models/file-uploads?view=aspnetcore-3.1
I need to maintain a historical record of certain documents, my initial solution was to copy them to a shared folder from .NET, but that doesn't seem so safe to me. Can I make the upload of those files to One Drive by using .NET with C#? If so, I would like documentation about it, I've already done a free search and I haven't found anything that could satisfy my needs. I apologize if the question is way too vague. Thank you.
Maybe this can help you out:
Using the code:
public string OneDriveApiRoot { get; set; } = "https://api.onedrive.com/v1.0/";
Upload file to OneDrive
//this is main method of upload file to OneDrive
public async Task<string> UploadFileAsync(string filePath, string oneDrivePath)
{
//get the upload session,we can use this session to upload file resume from break point
string uploadUri = await GetUploadSession(oneDrivePath);
//when file upload is not finish, the result is upload progress,
//When file upload is finish, the result is the file information.
string result = string.Empty;
using (FileStream stream = File.OpenRead(filePath))
{
long position = 0;
long totalLength = stream.Length;
int length = 10 * 1024 * 1024;
//In one time, we just upload a part of file
//When all file part is uploaded, break out in this loop
while (true)
{
//Read a file part
byte[] bytes = await ReadFileFragmentAsync(stream, position, length);
//check if arrive file end, when yes, break out with this loop
if (position >= totalLength)
{
break;
}
//Upload the file part
result = await UploadFileFragmentAsync(bytes, uploadUri, position, totalLength);
position += bytes.Length;
}
}
return result;
}
private async Task<string> GetUploadSession(string oneDriveFilePath)
{
var uploadSession = await AuthRequestToStringAsync(
uri: $"{OneDriveApiRoot}drive/root:/{oneDriveFilePath}:/upload.createSession",
httpMethod: HTTPMethod.Post,
contentType: "application/x-www-form-urlencoded");
JObject jo = JObject.Parse(uploadSession);
return jo.SelectToken("uploadUrl").Value<string>();
}
private async Task<string> UploadFileFragmentAsync(byte[] datas, string uploadUri, long position, long totalLength)
{
var request = await InitAuthRequest(uploadUri, HTTPMethod.Put, datas, null);
request.Request.Headers.Add("Content-Range", $"bytes {position}-{position + datas.Length - 1}/{totalLength}");
return await request.GetResponseStringAsync();
}
Get Share Link: ( Javascript )
//This method use to get ShareLink, you can use the link in web or client terminal
public async Task<string> GetShareLinkAsync(string fileID, OneDriveShareLinkType type, OneDrevShareScopeType scope)
{
string param = "{type:'" + type + "',scope:'" + scope + "'}";
string result = await AuthRequestToStringAsync(
uri: $"{OneDriveApiRoot}drive/items/{fileID}/action.createLink",
httpMethod: HTTPMethod.Post,
data: Encoding.UTF8.GetBytes(param),
contentType: "application/json");
return JObject.Parse(result).SelectToken("link.webUrl").Value<string>();
}
From: https://code.msdn.microsoft.com/office/How-to-upload-file-to-21125137
An easy solution for beginners:
Install OneDrive app on your computer then login to your account and set a folder to it.
Then you just need to copy your files in the folder you set in the last step. It would be synced automatically by OneDrive application.
File.Copy(sourceFileFullPath,OneDriveFileFullPath);
I have a web API function that successfully upload files to Dropbox (using their new .NET SDK) and then gets shared links to the uploaded files (each document a time).
private async Task<string> Upload(DropboxClient dbx, string localPath, string remotePath)
{
const int ChunkSize = 4096 * 1024;
using (var fileStream = File.Open(localPath, FileMode.Open))
{
if (fileStream.Length <= ChunkSize)
{
WriteMode mode = new WriteMode();
FileMetadata fileMetadata = await dbx.Files.UploadAsync(remotePath, body: fileStream, mode: mode.AsAdd, autorename: true);
//set the expiry date
var settings = new SharedLinkSettings(expires: DateTime.Today.AddDays(7));
SharedLinkMetadata sharedLinkMetadata = await dbx.Sharing.CreateSharedLinkWithSettingsAsync(fileMetadata.PathLower, settings);
return sharedLinkMetadata.Url;
}
else
{
await this.ChunkUpload(dbx, remotePath, fileStream, ChunkSize);
}
return "error";
}
}
That usually works fine but when I upload the exact same document (name and content) twice, nothing happens and I do need to have both files stored in my Dropbox account.
It can be as much same documents as needed (not only two), my best scenario would be to have the second document (and third etc..) automatically renamed and uploaded to Dropbox.
Any idea on how to accomplish that?
I post the answer, maybe it will help someone.. I spent long time till I figure it out.
This is the code that checks if a file already exists in Dropbox.
If the file exists it checks if a link was shared for this file and based on the result it generates/retrieves a/the shared link.
private async Task<string> Upload(DropboxClient dbx, string localPath, string remotePath)
{
const int ChunkSize = 4096 * 1024;
using (var fileStream = File.Open(localPath, FileMode.Open))
{
if (fileStream.Length <= ChunkSize)
{
WriteMode mode = new WriteMode();
FileMetadata fileMetadata = await dbx.Files.UploadAsync(remotePath, body: fileStream, mode: mode.AsAdd, autorename: true);
//set the expiry date
var existingDoc = await dbx.Files.GetMetadataAsync(remotePath);
if (existingDoc.IsFile)
{
var sharedLink = await dbx.Sharing.ListSharedLinksAsync(remotePath);
var settings = new ListSharedLinksArg(remotePath);
ListSharedLinksResult listSharedLinksResult = await dbx.Sharing.ListSharedLinksAsync(remotePath);
if (listSharedLinksResult.Links.Count > 0)
{
return listSharedLinksResult.Links[0].Url;
}
else
{
var sharedLinkSettings = new SharedLinkSettings(expires: DateTime.Today.AddDays(7));
SharedLinkMetadata sharedLinkMetadata = await dbx.Sharing.CreateSharedLinkWithSettingsAsync(remotePath, sharedLinkSettings);
return sharedLinkMetadata.Url;
}
}
else
{
var settings = new SharedLinkSettings(expires: DateTime.Today.AddDays(7));
SharedLinkMetadata sharedLinkMetadata = await dbx.Sharing.CreateSharedLinkWithSettingsAsync(fileMetadata.PathLower, settings);
return sharedLinkMetadata.Url;
}
}
else
{
var sharedLink = await this.ChunkUpload(dbx, remotePath, fileStream, ChunkSize);
return sharedLink;
}
}
When you upload the same exact content to the same path again, the Dropbox API won't produce a conflict or another copy of the file, as nothing changed. (Edit: you can force a conflict even for identical contents by using strictConflict=true, e.g., on UploadAsync).
If you want another copy of the same data in your account, you can specify the different desired path when calling UploadAsync the second time.
Or, more efficiently, you can use CopyAsync to make a copy of the file already on Dropbox.
I try to upload a text file to my skydrive or at least create new text file in SD and edit it's content, through SkyDrive API in my Windows 8 application.
How can I do that?
I tried to do something like that:
LiveConnectClient client = new LiveConnectClient(session);
var fileData = new Dictionary<string, object>();
fileData.Add("name", "new_file.txt");
try
{
LiveOperationResult fileOperationResult = await client.PutAsync("me/skydrive", fileData);
this.infoTextBlock.Text = fileOperationResult.ToString();
}
catch (LiveConnectException exception)
{
this.infoTextBlock.Text = exception.Message;
}
but I get error
"The provided request is not valid. The root SkyDrive folder cannot be updated."
If I write something like "me/skydrive/" I get
"The provided URL is not valid. The requested path '' is not supported".
Method LiveConnectClient.PutAsync allows me only to update existing properties (but not it's content).
How it should be done properly?
Btw - Is content on LCDC(http://msdn.microsoft.com/en-us/library/live/hh826531.aspx) updated? I'm asking because some methods, which are in documentation, doesn't exist in dlls (f.e. LiveConnectClient.Upload. There's only BackgroundUploadAsync).
Thanks for help in advance,
Micheal
Close but as I wrote: I can't use client.upload method because LiveConnectClient class doesn't contain it. That's why I asked about site content update.
Anyway - I've got an answer:
//create a StorageFile (here is one way to do that if it is stored in your ApplicationData)
StorageFile file = awaitApplicationData.Current.LocalFolder.GetFileAsync("yourfilename.txt");
try {
client = new LiveConnectClient(session);
LiveOperationResult operationResult = await client.BackgroundUploadAsync("me/skydrive", file.Name, file, OverwriteOption.Overwrite);
}
catch (LiveConnectException exception) {
//handle exception
}
You should use the Upload method on LiveConnectionClient. For example, see the Uploading Files example in the Live SDK. Something like ...
LiveOperationResult fileOperationResult =
await client.Upload("me/skydrive", /*file name here*/, /*file stream here*/);
Here's another way to upload a file from a console application using a SkyDriveApiClient downloaded from http://skydriveapiclient.codeplex.com/releases/view/103081
static void Main(string[] args)
{
var client = new SkyDriveServiceClient();
client.LogOn("YourEmail#hotmail.com", "password");
WebFolderInfo wfInfo = new WebFolderInfo();
WebFolderInfo[] wfInfoArray = client.ListRootWebFolders();
wfInfo = wfInfoArray[0];
client.Timeout = 1000000000;
string fn = #"test.txt";
if (File.Exists(fn))
{
client.UploadWebFile(fn, wfInfo);
}
}
HI All,
I am trying to zip up an Epub file i have made using c#
Things I have tried
Dot Net Zip http://dotnetzip.codeplex.com/
- DotNetZip works but epubcheck fails the resulting file (**see edit below)
ZipStorer zipstorer.codeplex.com
- creates an epub file that passes validation but the file won't open in Adobe Digital Editions
7 zip
- I have not tried this using c# but when i zip the file using there interface it tells me that the mimetype file name has a length of 9 and it should be 8
In all cases the mimetype file is the first file added to the archive and is not compressed
The Epub validator that I'am using is epubcheck http://code.google.com/p/epubcheck/
if anyone has succesfully zipped an epub file with one of these libraries please let me know how or if anyone has zipped an epub file successfully with any other open source zipping api that would also work.
EDIT
DotNetZip works, see accepted answer below.
If you need to control the order of the entries in the ZIP file, you can use DotNetZip and the ZipOutputStream.
You said you tried DotNetZip and it (the epub validator) gave you an error complaining about the mime type thing. This is probably because you used the ZipFile type within DotNetZip. If you use ZipOutputStream, you can control the ordering of the zip entries, which is apparently important for epub (I don't know the format, just surmising).
EDIT
I just checked, and the epub page on Wikipedia describes how you need to format the .epub file. It says that the mimetype file must contain specific text, must be uncompressed and unencrypted, and must appear as the first file in the ZIP archive.
Using ZipOutputStream, you would do this by setting CompressionLevel = None on that particular ZipEntry - that value is not the default.
Here's some sample code:
private void Zipup()
{
string _outputFileName = "Fargle.epub";
using (FileStream fs = File.Open(_outputFileName, FileMode.Create, FileAccess.ReadWrite ))
{
using (var output= new ZipOutputStream(fs))
{
var e = output.PutNextEntry("mimetype");
e.CompressionLevel = CompressionLevel.None;
byte[] buffer= System.Text.Encoding.ASCII.GetBytes("application/epub+zip");
output.Write(buffer,0,buffer.Length);
output.PutNextEntry("META-INF/container.xml");
WriteExistingFile(output, "META-INF/container.xml");
output.PutNextEntry("OPS/"); // another directory
output.PutNextEntry("OPS/whatever.xhtml");
WriteExistingFile(output, "OPS/whatever.xhtml");
// ...
}
}
}
private void WriteExistingFile(Stream output, string filename)
{
using (FileStream fs = File.Open(fileName, FileMode.Read))
{
int n = -1;
byte[] buffer = new byte[2048];
while ((n = fs.Read(buffer,0,buffer.Length)) > 0)
{
output.Write(buffer,0,n);
}
}
}
See the documentation for ZipOutputStream here.
Why not make life easier?
private void IonicZip()
{
string sourcePath = "C:\\pulications\\";
string fileName = "filename.epub";
// Creating ZIP file and writing mimetype
using (ZipOutputStream zs = new ZipOutputStream(sourcePath + fileName))
{
var o = zs.PutNextEntry("mimetype");
o.CompressionLevel = CompressionLevel.None;
byte[] mimetype = System.Text.Encoding.ASCII.GetBytes("application/epub+zip");
zs.Write(mimetype, 0, mimetype.Length);
}
// Adding META-INF and OEPBS folders including files
using (ZipFile zip = new ZipFile(sourcePath + fileName))
{
zip.AddDirectory(sourcePath + "META-INF", "META-INF");
zip.AddDirectory(sourcePath + "OEBPS", "OEBPS");
zip.Save();
}
}
For anyone like me who's searching for other ways to do this, I would like to add that the ZipStorer class from Jaime Olivares is a great alternative. You can copy the code right into your project, and it's very easy to choose between 'deflate' and 'store'.
https://github.com/jaime-olivares/zipstorer
Here's my code for creating an EPUB:
Dictionary<string, string> FilesToZip = new Dictionary<string, string>()
{
{ ConfigPath + #"mimetype", #"mimetype"},
{ ConfigPath + #"container.xml", #"META-INF/container.xml" },
{ OutputFolder + Name.Output_OPF_Name, #"OEBPS/" + Name.Output_OPF_Name},
{ OutputFolder + Name.Output_XHTML_Name, #"OEBPS/" + Name.Output_XHTML_Name},
{ ConfigPath + #"style.css", #"OEBPS/style.css"},
{ OutputFolder + Name.Output_NCX_Name, #"OEBPS/" + Name.Output_NCX_Name}
};
using (ZipStorer EPUB = ZipStorer.Create(OutputFolder + "book.epub", ""))
{
bool First = true;
foreach (KeyValuePair<string, string> File in FilesToZip)
{
if (First) { EPUB.AddFile(ZipStorer.Compression.Store, File.Key, File.Value, ""); First = false; }
else EPUB.AddFile(ZipStorer.Compression.Deflate, File.Key, File.Value, "");
}
}
This code creates a perfectly valid EPUB file. However, if you don't need to worry about validation, it seems most eReaders will accept an EPUB with a 'deflate' mimetype. So my previous code using .NET's ZipArchive produced EPUBs that worked in Adobe Digital Editions and a PocketBook.