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();
}
Related
I am trying to use HttpClient with putasync to send file to server. The function looks like:
public async Task SendCsvFile(string path,string apiKey)
{
try
{
string clientKey = "";
LoggerService.Logger.CreateLog("Log");
LoggerService.Logger.Info("Start:SendCsvFile");
FileStream fileStream = null;
HttpClientHandler clientHandler = new HttpClientHandler();
clientHandler.ServerCertificateCustomValidationCallback = (sender, cert, chain, sslPolicyErrors) => { return true; };
HttpClient httpClient = new HttpClient(clientHandler);
httpClient.DefaultRequestHeaders.Accept.Clear();
httpClient.DefaultRequestHeaders.Add("x-api-key", clientKey);
string url = "https://test.csv";
var content = new MultipartFormDataContent();
var fileName = Path.GetFileName(path);
fileStream = File.OpenRead(path);
StreamContent streamContent = new StreamContent(fileStream);
content.Add(new StreamContent(fileStream), fileName, fileName);
var response = await httpClient.PutAsync(url, content);
if (response.IsSuccessStatusCode == true)
{
LoggerService.Logger.Info("File sent correctly.");
}
else
{
LoggerService.Logger.Error("Error during sending." + response.StatusCode + ";" + response.ReasonPhrase + ";");
}
fileStream.Close();
LoggerService.Logger.Info("End:SendCsvFile");
}
catch (Exception ex)
{
LoggerService.Logger.Error(ex.ToString());
//return 0;
}
//return 1;
}
File is send fine and it works however Content-disposition header is added to the file to the first line, and client doesn't want that. It's the first time I am doing anything with services and I read through a lot but still I don't know what can i change to not alter the content of csv file.
EDIT.
After I send the file header is added to the content so the file looks like that.
Screenshot from client server
All the data is fine, though the client server processes the data in a way that it should start from column names. So my question really is what can I can change to omit that first line and is it even possible. Maybe thats something obvious but i' m just a newbie in this stuff.
Changing to MultipartContent and Clearing Headers almost work but left me with boundary still visible in a file. Eventually I changed to RestSharp and adding content this way got rid of the problem.
public async Task SendCsvFile(string path, string apiKey)
{
try
{
string clientKey = "";
string url = "";
LoggerService.Logger.CreateLog("CreationAndDispatchStatesWithPrices");
LoggerService.Logger.Info("Start:SendCsvFile");
FileStream fileStream = null;
var fileName = Path.GetFileName(path);
fileStream = File.OpenRead(path);
var client = new RestClient(url);
// client.Timeout = -1;
var request = new RestRequest();
request.AddHeader("x-api-key", clientKey);
request.AddHeader("Content-Type", "text/csv");
request.AddParameter("text/csv", File.ReadAllBytes(path), ParameterType.RequestBody);
RestResponse response = client.Put(request);
if (response.IsSuccessful == true)
{
LoggerService.Logger.Info("File sent correctly.");
}
else
{
LoggerService.Logger.Error("Error sending file." + response.StatusCode + ";" + response.ErrorMessage + ";");
}
fileStream.Close();
LoggerService.Logger.Info("End:SendCsvFile");
}
catch (Exception ex)
{
LoggerService.Logger.Error(ex.ToString());
//return 0;
}
//return 1;
}
We have a POST method in the the Microsoft .NET Web API. That post method processes PDF file into a Sharepoint Site. We did test this method in Postman, and this method works accordingly
However, we are trying to execute this method via the submit button on the PDF itself with the action URL specific for the Post method in the Web Api, the very same URL that properly works in the postman
When I try to execute that action/clicking the Submit button, I get a following error
Is there any specific strategy to execute the Web Api POST method directly through the PDF submit button
Thank you in advance
Here is my Web Api Post method
[HttpPost]
[Route("SubmitForm")]
public async Task<IActionResult> SubmitForm()
{
var file = Request.Form.Files[0];
HttpClient client = GetBinaryRequestClient();
try
{
byte[] docAsBytes;
using (var ms = new MemoryStream())
{
file.CopyTo(ms);
docAsBytes = ms.ToArray();
}
PdfReader pdfReader = new PdfReader(docAsBytes);
MemoryStream m = new MemoryStream();
PdfStamper outStamper = new PdfStamper(pdfReader,m);
string formName = outStamper.AcroFields.GetField("FormSeqNo");
string endpointUrl = string.Format(
"{0}{1}/_api/web/GetFolderByServerRelativeUrl('{2}')/Files/Add(url='{3}', overwrite=true)",
this.apiService.AppSettings.SharePointSettings.SPSiteURL,
this.apiService.AppSettings.SharePointSettings.SmartFormsRelativeSiteURL,
this.apiService.AppSettings.SharePointSettings.SubmittedPDFsLibrary,
$"{formName}.pdf");
ByteArrayContent imageBytes = new ByteArrayContent(docAsBytes);
var result = await client.PostAsync(endpointUrl, imageBytes);
return Ok();
}
catch (Exception ex)
{
return StatusCode(StatusCodes.Status500InternalServerError, $"Error in method {ex.Message}");
}
}
Here is the answer that works for me. The .NET API method has to properly receive PDF based requests and write the responses back with the DFD type, NOT return it
[HttpPost]
[Route("SubmitForm")]
public async Task SubmitForm()
{
var file = Request.Body;
HttpClient client = GetBinaryRequestClient();
try
{
byte[] docAsBytes;
using (var ms = new MemoryStream())
{
file.CopyTo(ms);
docAsBytes = ms.ToArray();
}
PdfReader pdfReader = new PdfReader(docAsBytes);
MemoryStream m = new MemoryStream();
PdfStamper outStamper = new PdfStamper(pdfReader,m);
string formName = outStamper.AcroFields.GetField("FormSeqNo");
string endpointUrl = string.Format(
"{0}{1}/_api/web/GetFolderByServerRelativeUrl('{2}')/Files/Add(url='{3}', overwrite=true)",
this.apiService.AppSettings.SharePointSettings.SPSiteURL,
this.apiService.AppSettings.SharePointSettings.SmartFormsRelativeSiteURL,
this.apiService.AppSettings.SharePointSettings.SubmittedPDFsLibrary,
$"{formName}.pdf");
ByteArrayContent imageBytes = new ByteArrayContent(docAsBytes);
var result = await client.PostAsync(endpointUrl, imageBytes);
Response.Redirect(this.apiService.AppSettings.SharePointSettings.SPSiteURL);
//return Ok();
}
catch (Exception ex)
{
//return null;// StatusCode(StatusCodes.Status500InternalServerError, $"Error in method {ex.Message}");
await ReturnFDFResponse("Error Occured " + ex.Message);
}
}
private async Task ReturnFDFResponse(string status)
{
string fdfmessage = "%FDF-1.2" + "\n" + "1 0 obj <<" + "\n" + "/FDF <<" +
"\n" + "/Status (" + status + "!)" + "\n" + ">>" + "\n" +
">>" + "\n" + "endobj" + "\n" + "trailer" + "\n" + "<</Root 1 0 R>>" +
"\n" + "%%EOF";
HttpResponseMessage fdfresult = new HttpResponseMessage(HttpStatusCode.OK);
MemoryStream stream = new MemoryStream(Encoding.UTF8.GetBytes(fdfmessage));
stream.Position = 0;
fdfresult.Content = new StreamContent(stream);
fdfresult.Content.Headers.ContentType = new MediaTypeHeaderValue("application/vnd.fdf");
Response.ContentType = "application/vnd.fdf";
await Response.Body.WriteAsync(stream.ToArray());
}
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;
}
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!
I've spent hours working many found examples without success for what is super simple to do in a web forms application. That is, upload one or more files and store them in sql server.
In web forms (vb.net) I can do this:
Dim fs As Stream = fileUpload1.PostedFile.InputStream
Dim br As New BinaryReader(fs)
Dim bytes As Byte() = br.ReadBytes(fs.Length)
'insert the file into database
Dim strQuery As String = "INSERT INTO files ([name], [type], [file]) VALUES (#Name, #ContentType, #Data)"
Dim cmd As New SqlCommand(strQuery)
cmd.Parameters.Add("#Name", SqlDbType.VarChar).Value = filename
cmd.Parameters.Add("#ContentType", SqlDbType.VarChar).Value() = contenttype
cmd.Parameters.Add("#Data", SqlDbType.Binary).Value = bytes
Then do the database execute statements......done!
Now C# Web-Api:
The seemingly good example I have now that saves uploads to the filesystem via Web-Api is:
public Task<IEnumerable<FileDesc>> Old()
{
string folderName = "uploads";
string PATH = HttpContext.Current.Server.MapPath("~/" + folderName);
string rootUrl = Request.RequestUri.AbsoluteUri.Replace(Request.RequestUri.AbsolutePath, String.Empty);
if (Request.Content.IsMimeMultipartContent())
{
var streamProvider = new MultipartFormDataStreamProvider(PATH);
var task = Request.Content.ReadAsMultipartAsync(streamProvider).ContinueWith<IEnumerable<FileDesc>>(t =>
{
if (t.IsFaulted || t.IsCanceled)
{
throw new HttpResponseException(HttpStatusCode.InternalServerError);
}
var fileInfo = streamProvider.FileData.Select(i =>
{
var info = new FileInfo(i.LocalFileName);
return new FileDesc(info.Name, rootUrl + "/" + folderName + "/" + info.Name, info.Length / 1024);
});
return fileInfo;
});
return task;
}
else
{
throw new HttpResponseException(Request.CreateResponse(HttpStatusCode.NotAcceptable, "This request is not properly formatted"));
}
}
I cannot seem to figure out how to get each multipart file content stream so that I can send to the database. I've seen posts talking about MultipartMemoryStreamProvider and MultipartStreamProvider but I haven't figured out how to use them. I'm clearly over my head as a C# and Web-Api newbie.
Can anyone direct me on how to get the file contents into a stream I can get the bytes to send to the db?
Here's my solution when I encountered this issue:
Client:
public async Task UploadImage(byte[] image, string url)
{
Stream stream = new System.IO.MemoryStream(image);
HttpStreamContent streamContent = new HttpStreamContent(stream.AsInputStream());
Uri resourceAddress = null;
Uri.TryCreate(url.Trim(), UriKind.Absolute, out resourceAddress);
Windows.Web.Http.HttpRequestMessage request = new Windows.Web.Http.HttpRequestMessage(Windows.Web.Http.HttpMethod.Post, resourceAddress);
request.Content = streamContent;
var httpClient = new Windows.Web.Http.HttpClient();
var cts = new CancellationTokenSource();
Windows.Web.Http.HttpResponseMessage response = await httpClient.SendRequestAsync(request).AsTask(cts.Token);
}
Controller:
public async Task<HttpResponseMessage> Post()
{
Stream requestStream = await this.Request.Content.ReadAsStreamAsync();
byte[] byteArray = null;
using (MemoryStream ms = new MemoryStream())
{
await requestStream.CopyToAsync(ms);
byteArray = ms.ToArray();
}
.
.
.
return Request.CreateResponse(HttpStatusCode.OK);
}