Resuming interrupted upload using Google drive v3 C# sdk - c#

I want to resume interrupted resumable upload using Google Drive v3 C# SDK.
The reason why I want this is to create resumable upload in Restful Web API.
There is google drive api instance in this RestAPI, so this is relaying chunk data from client program to google drive.
As you know, client program cannot upload whole file data at one time to Web API, so we need to resume interrupted resumable upload.
So my plan is here.
First, we need to create upload session and receive Session URI.
Second, Create Upload instance every time from returned URI and add chunk data.
Third, repeat 2nd process until EOF.
For this, I made test code, but it does not work at all.
var uploadStream = new System.IO.FileStream(UploadFileName, System.IO.FileMode.Open,
System.IO.FileAccess.Read);
var insert = service.Files.Create(new Google.Apis.Drive.v3.Data.File { Name = title }, uploadStream, ContentType);
Uri uploadUri = insert.InitiateSessionAsync().Result;
int chunk_size = ResumableUpload.MinimumChunkSize;
while (uploadStream.Length != uploadStream.Position)
{
byte[] temp = new byte[chunk_size];
uploadStream.Read(temp, 0, temp.Length);
MemoryStream stream = new MemoryStream(temp);
ResumableUpload resume_uploader = ResumableUpload.CreateFromUploadUri(uploadUri, stream);
resume_uploader.ChunkSize = chunk_size;
IUploadProgress ss = resume_uploader.Resume();
Console.WriteLine("Uploaded " + ss.BytesSent.ToString());
}
Frankly, I expected to receive 308 Resume Incomplete Code, but the result is different.
"Invalid request. According to the Content-Range header, the final size of the upload is 262144 byte(s). This does not match the expected size of 1193188 byte(s), which was specified in an earlier request."
This means that I need to create code that resumes interrupted resumable upload using Google Drive C# SDK.
Anybody can help me?

Finally, I solved issue. Exact code is below. Actually, I could not find any source code on Google, so I was so sad. Every developer who wants to solve this issue, use my code please. Hope you are fine. :)
public static async Task<Google.Apis.Drive.v3.Data.File> UploadSync(DriveService driveService, string filepath)
{
string destfilename = Path.GetFileName(filepath);
List<string> parents = new List<string>();
parents.Add("root");
// Prepare the JSON metadata
string json = "{\"name\":\"" + destfilename + "\"";
if (parents.Count > 0)
{
json += ", \"parents\": [";
foreach (string parent in parents)
{
json += "\"" + parent + "\", ";
}
json = json.Remove(json.Length - 2) + "]";
}
json += "}";
Debug.WriteLine(json);
Google.Apis.Drive.v3.Data.File uploadedFile = null;
try
{
System.IO.FileInfo info = new System.IO.FileInfo(filepath);
ulong fileSize = (ulong)info.Length;
var uploadStream = new System.IO.FileStream(filepath, System.IO.FileMode.Open, System.IO.FileAccess.Read);
var insert = driveService.Files.Create(new Google.Apis.Drive.v3.Data.File { Name = destfilename, Parents = new List<string> { "root" } }, uploadStream, "application/octet-stream");
Uri uploadUri = insert.InitiateSessionAsync().Result;
int chunk_size = ResumableUpload.MinimumChunkSize;
int bytesSent = 0;
while (uploadStream.Length != uploadStream.Position)
{
byte[] temp = new byte[chunk_size];
int cnt = uploadStream.Read(temp, 0, temp.Length);
if (cnt == 0)
break;
HttpWebRequest httpRequest = (HttpWebRequest)WebRequest.Create(uploadUri);
httpRequest.Method = "PUT";
httpRequest.Headers["Authorization"] = "Bearer " + ((UserCredential)driveService.HttpClientInitializer).Token.AccessToken;
httpRequest.ContentLength = (long)cnt;
httpRequest.Headers["Content-Range"] = string.Format("bytes {0}-{1}/{2}", bytesSent, bytesSent + cnt - 1, fileSize);
using (System.IO.Stream requestStream = httpRequest.GetRequestStreamAsync().Result)
{
requestStream.Write(temp, 0, cnt);
}
HttpWebResponse httpResponse;
try
{
httpResponse = (HttpWebResponse)httpRequest.GetResponse();
}
catch (WebException ex)
{
httpResponse = (HttpWebResponse)ex.Response;
}
if (httpResponse.StatusCode == HttpStatusCode.OK)
{ }
else if ((int)httpResponse.StatusCode != 308)
break;
bytesSent += cnt;
Console.WriteLine("Uploaded " + bytesSent.ToString());
}
if (bytesSent != uploadStream.Length)
{
return null;
}
// Try to retrieve the file from Google
FilesResource.ListRequest request = driveService.Files.List();
if (parents.Count > 0)
request.Q += "'" + parents[0] + "' in parents and ";
request.Q += "name = '" + destfilename + "'";
FileList result = request.Execute();
if (result.Files.Count > 0)
uploadedFile = result.Files[0];
}
catch (Exception ex)
{
Debug.WriteLine(ex.Message);
}
return uploadedFile;
}

Related

Write content to a file on azure storage with using PUT request in C#

I am trying to make a put request to Azure storage file, where I want to add some simple contents. I change the URL and add ?comp=range at the end of the url but I get 403 error in response. I have created a basic console application in .net.
My Header is :
const string requestMethod = "PUT";
string urlPath = strShareName + "/" + "rahila.csv?comp=range";//+ "?comp=range HTTP/1.1";
String canonicalizedResource = String.Format("/{0}/{1}/{2}", StorageAccountName, strShareName, strFileName);
try
{
//GetWebRequest(requestMethod, urlPath, canonicalizedResource, "CreateFile");
HttpWebRequest request = null;
try
{
const string type = "file";
string MethodType = "CreateFile";
const string msVersion = "2015-04-05";
String dateInRfc1123Format = DateTime.UtcNow.ToString("R", CultureInfo.InvariantCulture);
String canonicalizedHeaders = "";
string data = "rahila sted";
canonicalizedHeaders = String.Format("x-ms-date:{0}\nx-ms-version:{1}", dateInRfc1123Format, msVersion);
if (MethodType == "CreateFile")
{
canonicalizedHeaders = String.Format("x-ms-content-length:65536\nx-ms-date:{0}\nx-ms-type:file\nx-ms-version:{1}", dateInRfc1123Format, msVersion);
}
String stringToSign = "";
stringToSign = String.Format("{0}\n\n\n\n\n\n\n\n\n\n\n\n{1}\n{2}", requestMethod, canonicalizedHeaders, canonicalizedResource);
if (String.IsNullOrEmpty(stringToSign))
{
throw new ArgumentNullException("canonicalizedString");
}
String signature;
if (String.IsNullOrEmpty(stringToSign))
{
throw new ArgumentNullException("unsignedString");
}
if (Convert.FromBase64String(StorageKey) == null)
{
throw new ArgumentNullException("key");
}
Byte[] dataToHmac = System.Text.Encoding.UTF8.GetBytes(stringToSign);
using (HMACSHA256 hmacSha256 = new HMACSHA256(Convert.FromBase64String(StorageKey)))
{
signature = Convert.ToBase64String(hmacSha256.ComputeHash(dataToHmac));
}
String authorizationHeader = String.Format(CultureInfo.InvariantCulture, "{0} {1}:{2}",
StorageScheme,
StorageAccountName, signature);
Uri uri = new Uri(FileEndPoint + urlPath);
request = (HttpWebRequest)WebRequest.Create(uri);
if (requestMethod != "Get")
{
request.ContentLength = data.Length;
}
// string data = "Hello testing";
//int a= ((data.Length) + 1);
request.Method = "PUT";//requestMethod;
request.Headers.Add("x-ms-write", "update");
request.Headers.Add("x-ms-date", dateInRfc1123Format);
request.Headers.Add("x-ms-version", msVersion);
request.Headers.Add("x-ms-range", "bytes=0-65535"); // + ((data.Length) - 1));
request.Headers.Add("Authorization", authorizationHeader);
the line where i get the exception is in the bold format.
HttpWebResponse response = null;
response = (HttpWebResponse)request.GetResponse();
string returnString = response.StatusCode.ToString();
Can anyone help me to resolve this issue or just guide me how to write content to a simple file on azure storage without using the azure client API.
update 12/19:
When using Put Range to upload content to azure file, you can follow the following code(I assume you have already created a file on the azure file share, and it's content length is larger than the content being uploaded):
static void UploadText()
{
string Account = "xxxx";
string Key = "xxxx";
string FileShare = "test1";
string FileName = "11.txt";
string apiversion = "2019-02-02";
//the string to be uploaded to azure file, note that the length of the uploaded string should less than the azure file length
string upload_text = "bbbbbbbbbbbbbbbbbbbbbbbb.";
Console.WriteLine("the string length: " + upload_text.Length);
DateTime dt = DateTime.UtcNow;
string StringToSign = String.Format("PUT\n"
+ "\n" // content encoding
+ "\n" // content language
+ upload_text.Length + "\n" // content length
+ "\n" // content md5
+ "\n" // content type
+ "\n" // date
+ "\n" // if modified since
+ "\n" // if match
+ "\n" // if none match
+ "\n" // if unmodified since
+ "\n"//+ "bytes=0-" + (upload_text.Length - 1) + "\n" // range
+"x-ms-date:" + dt.ToString("R") + "\nx-ms-range:bytes=0-"+(upload_text.Length-1) + "\nx-ms-version:" + apiversion + "\nx-ms-write:update\n" // headers
+ "/{0}/{1}/{2}\ncomp:range", Account, FileShare, FileName);
string auth = SignThis(StringToSign, Key, Account);
string method = "PUT";
string urlPath = string.Format("https://{0}.file.core.windows.net/{1}/{2}?comp=range", Account, FileShare,FileName);
Uri uri = new Uri(urlPath);
HttpWebRequest request = (HttpWebRequest)WebRequest.Create(uri);
request.Method = method;
request.ContentLength = upload_text.Length;
request.Headers.Add("x-ms-range", "bytes=0-"+(upload_text.Length-1));
request.Headers.Add("x-ms-write", "update");
request.Headers.Add("x-ms-date", dt.ToString("R"));
request.Headers.Add("x-ms-version", apiversion);
request.Headers.Add("Authorization", auth);
//request.Headers.Add("Content-Length", upload_text.Length.ToString());
var bytes = System.Text.Encoding.ASCII.GetBytes(upload_text);
using (var requestStream = request.GetRequestStream())
{
requestStream.Write(bytes, 0, bytes.Length);
}
using (HttpWebResponse response = (HttpWebResponse)request.GetResponse())
{
//read the content
Console.WriteLine("the response is:" + response.StatusCode);
}
}
private static String SignThis(String StringToSign, string Key, string Account)
{
String signature = string.Empty;
byte[] unicodeKey = Convert.FromBase64String(Key);
using (HMACSHA256 hmacSha256 = new HMACSHA256(unicodeKey))
{
Byte[] dataToHmac = System.Text.Encoding.UTF8.GetBytes(StringToSign);
signature = Convert.ToBase64String(hmacSha256.ComputeHash(dataToHmac));
}
String authorizationHeader = String.Format(
CultureInfo.InvariantCulture,
"{0} {1}:{2}",
"SharedKey",
Account,
signature);
return authorizationHeader;
}
Then in the Main() method, you can call UploadText() method, it works at my side.
old:
guide me how to write content to a simple file on azure storage
without using the azure client API.
For this, you can directly use Azure File Storage SDK Microsoft.Azure.Storage.File, version 11.1.1. And we always recommend using SDK instead of using rest api, because the SDK is easy to use.
Here is an example of using this SDK.
First, create a console project of .NET framework in visual studio. Then install this nuget package Microsoft.Azure.Storage.File, version 11.1.1.
The code:
using Microsoft.Azure.Storage;
using Microsoft.Azure.Storage.Auth;
using Microsoft.Azure.Storage.File;
using System;
namespace AzureFileTest2
{
class Program
{
static void Main(string[] args)
{
string accountName = "xxx";
string accountKey = "xxx";
CloudStorageAccount storageAccount = new CloudStorageAccount(new StorageCredentials(accountName, accountKey), true);
CloudFileClient cloudFileClient = storageAccount.CreateCloudFileClient();
//make sure the file share named test1 exists.
CloudFileShare fileShare = cloudFileClient.GetShareReference("test1");
CloudFileDirectory fileDirectory = fileShare.GetRootDirectoryReference();
CloudFile myfile = fileDirectory.GetFileReference("test123.txt");
if (!myfile.Exists())
{
//if the file does not exists, then create the file and set the file max size to 100kb.
myfile.Create(100 * 1024 * 1024);
}
//upload text to the file
//Besides using UploadText() method to directly upload text, you can also use UploadFromFile() / UploadFromByteArray() / UploadFromStream() methods as per your need.
myfile.UploadText("hello, it is using azure storage SDK");
Console.WriteLine("**completed**");
Console.ReadLine();
}
}
}

Download Latest File in a SharePoint Folder

My current code downloads a SharePoint file from an absolute URL of the file and writes to local.
I want to change it to use the folder URL instead and downloads file in the folder base on some filter.
Can it be done?
Below is my current code snippet:
string fullFilePath = DownloadSPFile("http://MySharePointSite.com/sites/Collection1/Folder1/File1.docx/");
public static string DownloadSPFile(string urlPath)
{
string serverTempdocPath = "";
try
{
var request = (HttpWebRequest)WebRequest.Create(urlPath);
var credentials = new NetworkCredential("username", "password", "domain");
request.Credentials = credentials;
request.Timeout = 20000;
request.AllowWriteStreamBuffering = false;
using (HttpWebResponse response = (HttpWebResponse)request.GetResponse())
{
using (Stream stream = response.GetResponseStream())
{
serverTempdocPath = Path.Combine(AppConfig.EmailSaveFilePath + "_DOWNLOADED.eml");
using (FileStream fs = new FileStream(serverTempdocPath, FileMode.Create))
{
byte[] read = new byte[256];
int count = stream.Read(read, 0, read.Length);
while (count > 0)
{
fs.Write(read, 0, count);
count = stream.Read(read, 0, read.Length);
}
}
}
}
}
catch (Exception ex)
{
AppLogger.LogError(ex, "");
throw ex;
}
return serverTempDocPath;
}
If your sharepoint site enables sharepoint rest api, you can get the details very easy.
Get list of files
url: http://site url/_api/web/GetFolderByServerRelativeUrl('/Folder Name')/Files
method: GET
headers:
Authorization: "Bearer " + accessToken
accept: "application/json;odata=verbose" or "application/atom+xml"
and pass query for that
"?filter=$top=1&$orderby=Created desc"
More information
Has you try to format your urlPath ?
like:
string urlPath = "path/to/folder/";
string fileFilter = "Cat.png";
string finalPath= String.format("{0}{1}", urlPath, fileFilter);
(Or anything like this)
(Hope I understand your question and I was able to help you ^^)

Since Modified Header in c#

Am saving Webpages from webbrowser control to the directory like below code. Now i want to check all the webpages daily that is modified or not. if it is modified have to update or else leave it. here i tried something in console application.
static void Main(string[] args)
{
Uri myUri = new Uri("http://www.google.com");
// Create a new 'HttpWebRequest' object with the above 'Uri' object.
HttpWebRequest myHttpWebRequest = (HttpWebRequest)WebRequest.Create(myUri);
// Create a new 'DateTime' object.
DateTime targetDate = DateTime.Now;
// Set a target date of a week ago
targetDate.AddDays(-7.0);
myHttpWebRequest.IfModifiedSince = targetDate;
try
{
// Assign the response object of 'HttpWebRequest' to a 'HttpWebResponse' variable.
HttpWebResponse myHttpWebResponse = (HttpWebResponse)myHttpWebRequest.GetResponse();
Console.WriteLine("Response headers for recently modified page\n{0}\n", myHttpWebResponse.Headers);
Stream streamResponse = myHttpWebResponse.GetResponseStream();
StreamReader streamRead = new StreamReader(streamResponse);
Char[] readBuff = new Char[256];
int count = streamRead.Read(readBuff, 0, 256);
Console.WriteLine("\nThe contents of Html Page are : \n");
while (count > 0)
{
String outputData = new String(readBuff, 0, count);
Console.Write(outputData);
count = streamRead.Read(readBuff, 0, 256);
}
// Close the Stream object.
streamResponse.Close();
streamRead.Close();
// Release the HttpWebResponse Resource.
myHttpWebResponse.Close();
Console.WriteLine("\nPress 'Enter' key to continue.................");
Console.Read();
}
catch (WebException e)
{
if (e.Response != null)
{
if (((HttpWebResponse)e.Response).StatusCode == HttpStatusCode.NotModified)
{
Console.WriteLine("\nThe page has not been modified since " + targetDate);
Console.ReadLine();
}
else
Console.WriteLine("\nUnexpected status code = " + ((HttpWebResponse)e.Response).StatusCode);
Console.ReadLine();
}
else
Console.WriteLine("\nUnexpected Web Exception " + e.Message);
Console.ReadLine();
}
}
I tried this as console application and here i gave www.google.com straightly. but i want to check from my directory which is i saved from web browser control.
var filename1 = webBrowser1.Document.Title;
var path1 = (#"D:\Cache\" + filename1 + ".html");
if (mb != 1)
{
if (File.Exists(path1))
{
MessageBox.Show("Exist");
}
else
{
File.WriteAllText(path1, webBrowser1.Document.Body.Parent.OuterHtml, Encoding.GetEncoding(webBrowser1.Document.Encoding));
MessageBox.Show("Saved");
}
}
Anyone help me to finish this application. Thanks in Advance.

Create file to Onedrive programmatically from C#?

I want to create a doc, docx, pptx or excel file from C# direct to my Onedrive account.
I have try this but it's not working for me. Anybody have any idea what I did wrong ? Thanks
public async Task<ActionResult> CreateWordFile()
{
LiveLoginResult loginStatus = await authClient.InitializeWebSessionAsync(HttpContext);
if (loginStatus.Status == LiveConnectSessionStatus.Connected)
{
var fileData = new Dictionary<string, object>();
fileData.Add("name", "Document.docx");
fileData.Add("Content-Type", "multipart/form-data; boundary=A300x");
fileData.Add("type", "file");
LiveOperationResult getResult = await connectedClient.PostAsync("me/skydrive/files", fileData);
}
return View();
}
EDITED:
The error that I get is this one:
"The header 'Content-Type' is missing the required parameter: 'boundary'.
Description: An unhandled exception occurred during the execution of the current web request. Please review the stack trace for more information about the error and where it originated in the code.
Exception Details: Microsoft.Live.LiveConnectException: The header 'Content-Type' is missing the required parameter: 'boundary'."
A couple of things:
The dictionary provided to PostAsync only populates fields in the request body, and so adding Content-Type in there doesn't have any effect
File resources are mean to be created using the UploadAsync method, which requires content. I don't believe there's an API you can call to tell the service to create a blank Office document.
I have something else. I created an HttpWebRequest and I set some parameters. Now it create the file to my onedrive account as a docx but when I try to open the file from my account an error message appear and it's saying something like "Something wrong has happened. We could not open the file". The file exist but it can't be open.
The code that I wrote is this. Any suggestions ?
public async Task<ActionResult> CreateWordFile()
{
string body = "--A300x\r\n"
+ "Content-Disposition: form-data; name=\"file\"; filename=\"csm.docx\"\r\n"
+ "Content-Type: application/octet-stream\r\n"
+ "\r\n"
+ "This is some content\r\n"
+ "\r\n"
+ "--A300x--\r\n";
byte[] fileBytes = System.Text.Encoding.UTF8.GetBytes(body);
Stream stream = new MemoryStream(fileBytes);
LiveLoginResult loginStatus = await authClient.InitializeWebSessionAsync(HttpContext);
if (loginStatus.Status == LiveConnectSessionStatus.Connected)
{
connectedClient = new LiveConnectClient(this.authClient.Session);
string url = "https://apis.live.net/v5.0/me/skydrive/files?access_token=" + this.authClient.Session.AccessToken;
HttpWebRequest httpWebRequest2 = (HttpWebRequest)WebRequest.Create(url);
httpWebRequest2.ContentType = "multipart/form-data; boundary=A300x";
httpWebRequest2.Method = "POST";
httpWebRequest2.KeepAlive = true;
httpWebRequest2.Credentials = System.Net.CredentialCache.DefaultCredentials;
httpWebRequest2.ContentLength = fileBytes.Length;
Stream stream2 = httpWebRequest2.GetRequestStream();
stream2.Write(fileBytes, 0, fileBytes.Length);
WebResponse webResponse2 = httpWebRequest2.GetResponse();
}
return View();
}
Finally I create a docx file from c#. I put here the solution (the code from the method is not refactored so it can be split in a severeal methods).
public async Task<ActionResult> CreateWordFile()
{
LiveLoginResult loginStatus = await authClient.InitializeWebSessionAsync(HttpContext);
if (loginStatus.Status == LiveConnectSessionStatus.Connected)
{
connectedClient = new LiveConnectClient(this.authClient.Session);
string url = "https://apis.live.net/v5.0/me/skydrive/files?access_token=" + this.authClient.Session.AccessToken;
MemoryStream streamDoc = new MemoryStream();
DocX doc = DocX.Create(streamDoc);
string headlineText = "Constitution of the United States";
string paraOne = ""
+ "We the People of the United States, in Order to form a more perfect Union, "
+ "establish Justice, insure domestic Tranquility, provide for the common defence, "
+ "promote the general Welfare, and secure the Blessings of Liberty to ourselves "
+ "and our Posterity, do ordain and establish this Constitution for the United "
+ "States of America.";
// A formatting object for our headline:
var headLineFormat = new Formatting();
headLineFormat.FontFamily = new System.Drawing.FontFamily("Arial Black");
headLineFormat.Size = 18D;
headLineFormat.Position = 12;
// A formatting object for our normal paragraph text:
var paraFormat = new Formatting();
paraFormat.FontFamily = new System.Drawing.FontFamily("Calibri");
paraFormat.Size = 10D;
doc.InsertParagraph(headlineText, false, headLineFormat);
doc.InsertParagraph(paraOne, false, paraFormat);
doc.Save();
var docFile = File(streamDoc, "application/octet-stream", "FileName.docx");
MemoryStream streamFile = new MemoryStream();
docFile.FileStream.Position = 0;
docFile.FileStream.CopyTo(streamFile);
var bites = streamFile.ToArray();
Stream stream2 = new MemoryStream(bites);
try
{
LiveOperationResult getResult = await connectedClient.UploadAsync("me/skydrive", docFile.FileDownloadName, stream2, OverwriteOption.Overwrite);
}
catch(WebException ex)
{
}
}
return View("~/Views/Auth/EditFile.cshtml");
}
I also foud the answer to create an xlsx file.
public async Task<ActionResult> CreateExcelFile()
{
LiveLoginResult loginStatus = await authClient.InitializeWebSessionAsync(HttpContext);
if (loginStatus.Status == LiveConnectSessionStatus.Connected)
{
connectedClient = new LiveConnectClient(this.authClient.Session);
string url = "https://apis.live.net/v5.0/me/skydrive/files?access_token=" + this.authClient.Session.AccessToken;
XSSFWorkbook wb = new XSSFWorkbook();
// create sheet
XSSFSheet sh = (XSSFSheet)wb.CreateSheet("Sheet1");
// 10 rows, 10 columns
for (int i = 0; i < 100; i++)
{
var r = sh.CreateRow(i);
for (int j = 0; j < 100; j++)
{
r.CreateCell(j);
}
}
MemoryStream stream = new MemoryStream();
wb.Write(stream);
stream.Dispose();
var arrBites = stream.ToArray();
MemoryStream newStream = new MemoryStream(arrBites);
var docFile = File(newStream, "application/octet-stream", "Excel.xlsx");
MemoryStream streamFile = new MemoryStream();
docFile.FileStream.Position = 0;
docFile.FileStream.CopyTo(streamFile);
var bites = streamFile.ToArray();
Stream stream2 = new MemoryStream(bites);
try
{
LiveOperationResult getResult = await connectedClient.UploadAsync("me/skydrive", docFile.FileDownloadName, stream2, OverwriteOption.Overwrite);
}
catch (WebException ex)
{
}
}
return View();
}

Http multipart request from windows phone 8 to send an text and an image using C# in WP8

I need make a multipart post request to a Rest service to send an image and a string but I can't do the code work. this is the code and I make a comment with capital letters where I get the exception and the exception message in the catch block.
public async Task<bool> addImages(Project project)
{
bool success = false;
string uuid = project.uuid;
if (uuid.Equals(""))
{
return success;
}
mUploadedImages = 0;
mProject = project;
string service = "service/imagen-project/add";
string serviceURL = mBaseURL + "/pwpcloud/" + service;
//build the REST request
// HTTP web request
string boundary = "---------------------------" + DateTime.Now.Ticks.ToString("x");
var httpWebRequest = (HttpWebRequest)WebRequest.Create(serviceURL);
httpWebRequest.ContentType = string.Format("multipart/form-data; boundary={0}", boundary);
httpWebRequest.Method = "POST";
httpWebRequest.AllowWriteStreamBuffering = false;
//Calculate the total size of the upload content.
string boundaryStringLine = "\r\n--" + boundary + "\r\n";
byte[] boundaryStringLineBytes = Encoding.UTF8.GetBytes(boundaryStringLine);
string lastBoundaryStringLine = "\r\n--" + boundary + "--\r\n";
byte[] lastBoundaryStringLineBytes = Encoding.UTF8.GetBytes(lastBoundaryStringLine);
// Get the byte array of the myFileDescription content disposition
string myFileDescriptionContentDisposition = String.Format(
"Content-Dis-data; name=\"{0}\"\r\n\r\n","project");
byte[] myFileDescriptionContentDispositionBytes = Encoding.UTF8.GetBytes(myFileDescriptionContentDisposition);
byte[] uuidBytes = Encoding.UTF8.GetBytes(project.uuid);
string fileUrl = "isostore:/" + project.Name + "_ID" + project.ID + "_Pictures/Pic_1.jpg";
string fileName = project.Name + "_ID" + project.ID + "_Pictures/Pic_1.jpg";
string myFileContentDisposition = String.Format("Content-Dis-data;name=\"{0}\"; " +
"filename=\"{1}\"\r\nContent-Type: {2}\r\n\r\n", "myFile", Path.GetFileName(fileUrl), "image/png");
byte[] myFileContentDispositionBytes = Encoding.UTF8.GetBytes(myFileContentDisposition);
IsolatedStorageFile isoStore = IsolatedStorageFile.GetUserStoreForApplication();
var fileStream = isoStore.OpenFile(fileName, FileMode.Open, FileAccess.Read);
byte[] imageBytes = new byte[fileStream.Length];
// Calculate the total size of the HTTP request
long totalRequestBodySize = boundaryStringLineBytes.Length * 2 + lastBoundaryStringLineBytes.Length + myFileDescriptionContentDispositionBytes.Length + uuidBytes.Length +
+myFileContentDispositionBytes.Length + imageBytes.Length;
httpWebRequest.ContentLength = totalRequestBodySize;
//Set cripted authorization -- WORKS FINE
setAuthorization(httpWebRequest, service, WEBSERVICE_REQUEST_TYPE_POST);
// Write the request Asynchronously
using (var stream = await Task.Factory.FromAsync<Stream>(httpWebRequest.BeginGetRequestStream, httpWebRequest.EndGetRequestStream, null))
{
// Send the file description content disposition over to the server
await stream.WriteAsync(boundaryStringLineBytes, 0, boundaryStringLineBytes.Length);
await stream.WriteAsync(myFileDescriptionContentDispositionBytes, 0, myFileDescriptionContentDisposition.Length);
await stream.WriteAsync(uuidBytes, 0, uuidBytes.Length);
// Send the file content disposition over to the server
await stream.WriteAsync(boundaryStringLineBytes, 0, boundaryStringLineBytes.Length);
await stream.WriteAsync(myFileContentDispositionBytes, 0, myFileContentDispositionBytes.Length);
fileStream.Read(imageBytes, 0, imageBytes.Length);
await stream.WriteAsync(imageBytes, 0, imageBytes.Length);
fileStream.Close();
// Send the last part of the HTTP request body
await stream.WriteAsync(lastBoundaryStringLineBytes, 0, lastBoundaryStringLineBytes.Length);
}
try
{
var responseTask = Task.Factory.FromAsync<WebResponse>(httpWebRequest.BeginGetResponse, httpWebRequest.EndGetResponse, null);
using (var response = (HttpWebResponse)await responseTask) //I GET THE EXCEPCION HERE (
{
string data;
// Read the response into a Stream object.
Stream responseStream = response.GetResponseStream();
using (var reader = new StreamReader(responseStream))
{
data = reader.ReadToEnd();
}
responseStream.Close();
}
}
catch (Exception e)
{
string err = e.Message; // err = "The remote server returned an error: NotFound" but the ServiceURL is ok
throw;
}
return success;
}
I could run this in a desktop program using C++ but I couldn't find any class to do it in C# using the same "sctructure". This is the C++ code:
void WebServicesClient::addImages(PW::Project *project){
QString uuid = project->getCloudUUID();
if (uuid.isEmpty()) /// !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
return;
mUploadedImages = 0;
mProject = project;
QNetworkRequest request;
QString serviceURL = mBaseURL+"/service/imagen-project/add";
request.setUrl(QUrl(serviceURL));
// request.setHeader(QNetworkRequest::ContentTypeHeader, "multipart/form-data");
QHttpMultiPart *multiPart = new QHttpMultiPart(QHttpMultiPart::FormDataType);
QHttpPart textPart;
textPart.setHeader(QNetworkRequest::ContentDispositionHeader, QVariant("form-data; name=\"project\""));
textPart.setBody(uuid.toAscii());
QHttpPart imagePart;
imagePart.setHeader(QNetworkRequest::ContentTypeHeader, QVariant("image/png"));
QString fileName = project->getImages().at(0)->getFileName();
QString header = "form-data; name=\"file\"";
header += "; filename=\"" + fileName + "\"";
imagePart.setHeader(QNetworkRequest::ContentDispositionHeader, QVariant(header));
QFile *file = new QFile(project->getImages().at(0)->getFullPath());
file->open(QIODevice::ReadOnly);
imagePart.setBodyDevice(file);
file->setParent(multiPart); // we cannot delete the file now, so delete it with the multiPart
multiPart->append(textPart);
multiPart->append(imagePart);
setAuthorization(request, "service/imagen-project/add", WEBSERVICE_REQUEST_TYPE_POST);
QObject::connect(mNetwork, SIGNAL(finished(QNetworkReply *)),
this, SLOT(onAddImageFinished(QNetworkReply*)));
emit statusChanged(0, "Uploading " + project->getImages().at(0)->getFileName());
QNetworkReply *reply = mNetwork->post(request,multiPart);
}
I hope someone can help me.
Thanks everyone!

Categories