valence desire 2 learn profile image upload - image

I'm trying to upload an image to my profile using the api but I'm getting a Unknown: NOT_FOUND 404 error. the call I am using is /d2l/api/lp/1.0/profile/myProfile/image, I am passing the content type, length and filename (profileImage). I'm passing the image as a dataStream. I've reduced the size of the image as well. Any ideas?
also here is part of my CallAction code orginally gotten from the Getting Started example
public void CallAction(ID2LUserContext userContext, int retryAttempts, string url, byte[] data, string method = "")
{
Uri uri = userContext.CreateAuthenticatedUri(url, method);
HttpWebRequest request = (HttpWebRequest)WebRequest.Create(uri);
request.AllowAutoRedirect = false;
request.Method = method;
if (method.Equals("PUT") || method.Equals("POST"))
{
request.ContentType = "image/jpeg";
//request.Headers.Add("Content-Disposition", "form-data; name=\"profileImage\"; filename=\"profileImage.jpg\"");
request.Headers.Add("Accept-Encoding", "gzip, deflate, compress");
//request.Headers.Add("X-Upload-Content-Type", "image/jpg");
//request.Headers.Add("X-Upload-Content-Length", data.Length.ToString());
//request.Headers.Add("X-Upload-File-Name", "profileImage");
request.ContentLength = data.Length;
Stream dataStream = request.GetRequestStream();
dataStream.Write(data, 0, data.Length);
dataStream.Flush();
dataStream.Close();
}
}
Also when I run a get to retrieve my photo it also returns a 404 error.

We have tested this call against our test instances here, and it does work. Here's what the HTTP packet headers look like for a valid test call (from a call formed with the python requests module):
{ 'User-Agent': 'python-requests/1.2.3 CPython/3.3.2 Darwin/12.4.0',
'Accept': '*/*',
'Content-Type': 'multipart/form-data; boundary=716acd781e224902854e6845bc62f653',
'Content-Length': '117886',
'Accept-Encoding': 'gzip, deflate, compress' }
to this URL:
https://somelms.edu/d2l/api/lp/1.0/profile/myProfile/image?
x_a={appId}
&x_c=Lz3PDTaUgG46cMF3CajAsiiGzz0C6u5QTLieAmbONZ0
&x_b={userId}
&x_d=7sSqbce1_ictuNAs80n01h0jSI0YxxKbPM01W7f49a0
&x_t={timestamp}
with a body that looks like this (note the part headers in this body, that characterize the content of the single part in the body that contains the image data):
--716acd781e224902854e6845bc62f653
Content-Disposition: form-data; name="profileImage"; filename="profileImage-student.png"
Content-Type: image/png
{image bytes here}
--716acd781e224902854e6845bc62f653--

This code should fix your problem:
public static void UploadFilesToRemoteUrl(byte[] profileImage, ID2LUserContext userContext, string accion)
{
//Reference:
//action = "/d2l/api/lp/1.3/profile/" + profileIdentifier + "/image";
//profileImage = the profileImage of user read from disk:
/*
FileStream fileStream = new FileStream(pictureLocalPath, FileMode.Open, FileAccess.Read);
Byte[] img = new Byte[fileStream.Length];
fileStream.Read(img, 0, Convert.ToInt32(img.Length));
fileStream.Close();
*/
var uri = userContext.CreateAuthenticatedUri(accion, "POST");
string boundary = "bde472ff1f1a46539e54e655857c27c1";
HttpWebRequest request = (HttpWebRequest)WebRequest.Create(uri);
request.ContentType = "multipart/form-data; boundary=" +
boundary;
request.Headers.Add("Accept-Encoding", "gzip, deflate, compress");
request.Method = "POST";
request.KeepAlive = true;
request.Proxy.Credentials = new NetworkCredential(Constantes.UsuarioProxy, Constantes.PasswordProxy, Constantes.DominioProxy);
Stream memStream = new System.IO.MemoryStream();
byte[] boundarybytes = System.Text.Encoding.ASCII.GetBytes("\r\n--" +
boundary + "\r\n");
string formdataTemplate = "\r\n--" + boundary +
"\r\nContent-Disposition: form-data; name=\"profileImage\"; filename=\"profileImage.jpg\"\r\nContent-Type: image/jpeg;\r\n\r\n";
byte[] formitembytes = System.Text.Encoding.UTF8.GetBytes(formdataTemplate);
memStream.Write(formitembytes, 0, formitembytes.Length);
//escribo el array de byte de la imagen
memStream.Write(profileImage, 0, profileImage.Length);
byte[] boundaryClose = System.Text.Encoding.ASCII.GetBytes("\r\n--" + boundary + "--");
memStream.Write(boundaryClose, 0, boundarybytes.Length);
StreamReader readerReq = new StreamReader(memStream);
string stringReq = readerReq.ReadToEnd();
request.ContentLength = memStream.Length;
Stream requestStream = request.GetRequestStream();
memStream.Position = 0;
byte[] tempBuffer = new byte[memStream.Length];
memStream.Read(tempBuffer, 0, tempBuffer.Length);
memStream.Close();
requestStream.Write(tempBuffer, 0, tempBuffer.Length);
requestStream.Close();
HttpWebResponse response = (HttpWebResponse)request.GetResponse();
if (response.StatusCode == HttpStatusCode.OK)
{
StreamReader reader = new StreamReader(response.GetResponseStream(), Encoding.UTF8);
string responseValence = reader.ReadToEnd();
response.Close();
}
}

Related

ASP MVC - Upload Rar Files with FTP

I have this code to upload a rar file to server and this works. But when i download the file from server, contents of file are spoiled. Please tell me how can I fix that. Thanks.
public ActionResult UpFile(HttpPostedFileBase upFile)
{
string fileName = System.IO.Path.GetFileName(upFile.FileName);
FtpWebRequest request = (FtpWebRequest)WebRequest.Create("ftp://myhostaddress.com/" + fileName);
request.Method = WebRequestMethods.Ftp.UploadFile;
request.Credentials = new NetworkCredential("myUserName", "MyPassword");
StreamReader streamReader = new StreamReader(upFile.InputStream);
byte[] fileContents = Encoding.Default.GetBytes(streamReader.ReadToEnd());
streamReader.Close();
request.ContentLength = fileContents.Length;
Stream requestStream = request.GetRequestStream();
requestStream.Write(fileContents, 0, fileContents.Length);
requestStream.Close();
FtpWebResponse response = (FtpWebResponse)request.GetResponse();
return RedirectToAction("/");
}
This code is working for me, try it:
var request = (FtpWebRequest)WebRequest.Create(ftp + fileName);
request.Method = WebRequestMethods.Ftp.UploadFile;
request.Credentials = new NetworkCredential(user, pass);
using (var input = File.OpenRead(filePth))
{
using (var output = request.GetRequestStream())
{
input.CopyTo(output);
}
}
var response = (FtpWebResponse)request.GetResponse();
response.Close();

valence desire 2 learn profile image upload error 404

I'm trying to upload an image profile using the api but I'm getting a Unknown: NOT_FOUND 404 error. the call I am using is POST /d2l/api/lp/1.3/profile/(profileId)/image, I am passing the content type, length and filename (profileImage). I'm passing the image as a dataStream. I've reduced the size of the image as well. Any ideas?
public static void UploadFilesToRemoteUrl(string file, string logpath, NameValueCollection nvc, ID2LUserContext userContext, string accion)
{
var uri = userContext.CreateAuthenticatedUri(accion, "POST");
string boundary = "bde472ff1f1a46539e54e655857c27c1";
HttpWebRequest request = (HttpWebRequest)WebRequest.Create(uri);
request.ContentType = "multipart/form-data; boundary=" +
boundary;
request.Headers.Add("Accept-Encoding", "gzip, deflate, compress");
request.Method = "POST";
request.KeepAlive = true;
request.Proxy.Credentials = new NetworkCredential(Constantes.UsuarioProxy, Constantes.PasswordProxy, Constantes.DominioProxy);
Stream memStream = new System.IO.MemoryStream();
byte[] boundarybytes = System.Text.Encoding.ASCII.GetBytes("\r\n--" +
boundary + "\r\n");
string formdataTemplate = "\r\n--" + boundary +
"\r\nContent-Disposition: form-data; name=\"profileImage\"; filename=\"profileImage.png\" \r\nContent-Type: image/png\r\n";
byte[] formitembytes = System.Text.Encoding.UTF8.GetBytes(formdataTemplate);
memStream.Write(formitembytes, 0, formitembytes.Length);
// Read image File *************************************************************
FileStream fileStream = new FileStream(file, FileMode.Open,FileAccess.Read);
byte[] buffer = new byte[1024];
int bytesRead = 0;
while ((bytesRead = fileStream.Read(buffer, 0, buffer.Length)) != 0)
{
memStream.Write(buffer, 0, bytesRead);
}
fileStream.Close();
//*****************************************************************************
//*********** End Read image file *********************************************
memStream.Write(boundarybytes, 0, boundarybytes.Length);
request.ContentLength = memStream.Length;
Stream requestStream = request.GetRequestStream();
memStream.Position = 0;
byte[] tempBuffer = new byte[memStream.Length];
memStream.Read(tempBuffer, 0, tempBuffer.Length);
memStream.Close();
requestStream.Write(tempBuffer, 0, tempBuffer.Length);
requestStream.Close();
HttpWebResponse response = (HttpWebResponse)request.GetResponse();
StreamReader reader = new StreamReader(response.GetResponseStream(), Encoding.UTF8);
string responseValence = reader.ReadToEnd();
}
It seems most likely that the 404 is coming either from
The API route you're providing (and the back-end service cannot match your API route to a handler method): this could be because of an incorrect profileId value, or a mis-typed route, or an incorrect API version number in the route, and so forth.
That for some reason the back-end service is accepting your profile image data but then unable to assign it to the user's profile.
Here's a capture of some request/response details of what an uploaded profile image packet looks like. When uploading a profile image to "my profile", I use an HTTP header that gets built from these values:
{'Content-Length': '75143',
'User-Agent': 'python-requests/2.2.1 CPython/3.3.3 Darwin/12.5.0',
'Content-Type': 'multipart/form-data; boundary=bde472ff1f1a46539e54e655857c27c1',
'Accept': '*/*',
'Accept-Encoding': 'gzip, deflate, compress'}
Note that this is a multipart/form-data content body, with a boundary marker around a single body part. The body content for the request looks like this:
--bde472ff1f1a46539e54e655857c27c1
Content-Disposition: form-data; name="profileImage"; filename="profile_img-225x225.png"
[actual PNG bytes here]
--bde472ff1f1a46539e54e655857c27c1--
The name property in the Content-Disposition header must be profileImage, and the filename property should be named after the local filename you're using to provide the content (so, as far as the back-end service is concerned, it's value is not particularly relevant).
Finally, there are particular role permissions at play that permit a user to edit someone else's profile image, so you should ensure that your calling user context for the API call has permission to edit someone else's image.
Fixed. This code works correctly:
public static void UploadFilesToRemoteUrl(byte[] profileImage, ID2LUserContext userContext, string accion)
{
//Reference:
//action = "/d2l/api/lp/1.3/profile/" + profileIdentifier + "/image";
//profileImage = the profileImage of user read from disk:
/*
FileStream fileStream = new FileStream(pictureLocalPath, FileMode.Open, FileAccess.Read);
Byte[] img = new Byte[fileStream.Length];
fileStream.Read(img, 0, Convert.ToInt32(img.Length));
fileStream.Close();
*/
var uri = userContext.CreateAuthenticatedUri(accion, "POST");
string boundary = "bde472ff1f1a46539e54e655857c27c1";
HttpWebRequest request = (HttpWebRequest)WebRequest.Create(uri);
request.ContentType = "multipart/form-data; boundary=" +
boundary;
request.Headers.Add("Accept-Encoding", "gzip, deflate, compress");
request.Method = "POST";
request.KeepAlive = true;
request.Proxy.Credentials = new NetworkCredential(Constantes.UsuarioProxy, Constantes.PasswordProxy, Constantes.DominioProxy);
Stream memStream = new System.IO.MemoryStream();
byte[] boundarybytes = System.Text.Encoding.ASCII.GetBytes("\r\n--" +
boundary + "\r\n");
string formdataTemplate = "\r\n--" + boundary +
"\r\nContent-Disposition: form-data; name=\"profileImage\"; filename=\"profileImage.jpg\"\r\nContent-Type: image/jpeg;\r\n\r\n";
byte[] formitembytes = System.Text.Encoding.UTF8.GetBytes(formdataTemplate);
memStream.Write(formitembytes, 0, formitembytes.Length);
//escribo el array de byte de la imagen
memStream.Write(profileImage, 0, profileImage.Length);
byte[] boundaryClose = System.Text.Encoding.ASCII.GetBytes("\r\n--" + boundary + "--");
memStream.Write(boundaryClose, 0, boundarybytes.Length);
StreamReader readerReq = new StreamReader(memStream);
string stringReq = readerReq.ReadToEnd();
request.ContentLength = memStream.Length;
Stream requestStream = request.GetRequestStream();
memStream.Position = 0;
byte[] tempBuffer = new byte[memStream.Length];
memStream.Read(tempBuffer, 0, tempBuffer.Length);
memStream.Close();
requestStream.Write(tempBuffer, 0, tempBuffer.Length);
requestStream.Close();
HttpWebResponse response = (HttpWebResponse)request.GetResponse();
if (response.StatusCode == HttpStatusCode.OK)
{
StreamReader reader = new StreamReader(response.GetResponseStream(), Encoding.UTF8);
string responseValence = reader.ReadToEnd();
response.Close();
}
}

Getting Error 400 while Exchanging Code for Access Token in Google oAuth C#

WebRequest request = WebRequest.Create("https://accounts.google.com/o/oauth2/token");
request.Method = "POST";
string postData = "code=" + code + "&client_id=" + _clientId + "&client_secret=" + _clientSecret + "&redirect_uri=" + _callback_url + "&grant_type=authorization_code";
byte[] byteArray = Encoding.UTF8.GetBytes(postData);
request.ContentType = "application/x-www-form-urlencoded";
request.ContentLength = byteArray.Length;
Stream dataStream = request.GetRequestStream();
dataStream.Write(byteArray, 0, byteArray.Length);
dataStream.Close();
WebResponse response = request.GetResponse();
I have placed a google sign in button in HTML page, on its callback got auth code to call ajax web servcice containing above code. But I am getting Error 400 on GetResponse(), I don't know why. Can any body please help me?
I have found following link workable in my case:
Code on page Page load :
protected void Page_Load(object sender, EventArgs e)
{
if (Request["code"] != null)
{
vCode = Request["code"].ToString();
getRefreshToken();
}
else
{
Response.Redirect(vAuthURL + "?scope=" + vScope + "&state=%2Fprofile&client_id=" + vClientId + "&redirect_uri=" + vRedURL + "&response_type=code&access_type=offline&approval_prompt=force", false);
}
}
Following function is being called in page load when code is available:
private void getRefreshToken()
{
string vClientId = "974762xxxxxx-xxxxxxxxx.apps.googleusercontent.com";
string vSecCode = "xxxxxxxxxxxxxxx";
string vScope = "https%3A%2F%2Fwww.googleapis.com%2Fauth%2Fuserinfo.email+https%3A%2F%2Fwww.googleapis.com%2Fauth%2Fuserinfo.profile+https%3A%2F%2Fwww.googleapis.com%2Fauth%2Fplus.login";
string vRedURL = "http://localhost:50488/wwwroot/member/social/googlesignin.aspx";
string vAuthURL = "https://accounts.google.com/o/oauth2/auth";
StringBuilder authLink = new StringBuilder();
HttpWebRequest webRequest = (HttpWebRequest)WebRequest.Create("https://accounts.google.com/o/oauth2/token");
webRequest.ContentType = "application/x-www-form-urlencoded";
webRequest.Method = "POST";
authLink.AppendFormat("code={0}", vCode);
authLink.AppendFormat("&client_id={0}", vClientId);
authLink.AppendFormat("&client_secret={0}", vSecCode);
authLink.AppendFormat("&redirect_uri={0}", vRedURL);
authLink.Append("&grant_type=authorization_code");
UTF8Encoding utfenc = new UTF8Encoding();
byte[] bytes = utfenc.GetBytes(authLink.ToString());
Stream os = null;
webRequest.ContentLength = bytes.Length; // Count bytes to send
os = webRequest.GetRequestStream();
os.Write(bytes, 0, bytes.Length); // Send it
HttpWebResponse webResponse = (HttpWebResponse)webRequest.GetResponse();
if (webResponse == null) { Response.Write("null"); }
StreamReader sr = new StreamReader(webResponse.GetResponseStream());
string jsonStr = sr.ReadToEnd().Trim();
}
Probably the important thing was to get code with server side code instead of mixing the client code and server side access_token getting script. Hope this works for you too.

Not able to construct httpmessage for push notification in windows phone 7

I am trying to construct the httpmessage for sending push notification(toast type), but it doesn't recognize methods in the below code. I have this code in Class Library.
Add method in sendNotificationRequest.Headers.Add("X-NotificationClass", "2");
Content Length in sendNotificationRequest.ContentLength = notificationMessage.Length;
GetRequestStream in Stream requestStream = sendNotificationRequest.GetRequestStream()
GetResponse in HttpWebResponse response = (HttpWebResponse)sendNotificationRequest.GetResponse();
HttpWebRequest sendNotificationRequest = (HttpWebRequest)WebRequest.Create(channel.ChannelUri.ToString());
sendNotificationRequest.Method = "POST";
//Indicate that you'll send toast notifications!
sendNotificationRequest.ContentType = "text/xml";
sendNotificationRequest.Headers = new WebHeaderCollection();
sendNotificationRequest.Headers.Add("X-NotificationClass", "2");
if (string.IsNullOrEmpty(txtMessage.Text)) return;
//Create xml envelope
string data = "X-WindowsPhone-Target: toast\r\n\r\n" +
"<?xml version='1.0' encoding='utf-8'?>" +
"<wp:Notification xmlns:wp='WPNotification'>" +
"<wp:Toast>" +
"<wp:Text1>{0}</wp:Text1>" +
"</wp:Toast>" +
"</wp:Notification>";
//Wrap custom data into envelope
string message = string.Format(data, txtMessage.Text);
byte[] notificationMessage = Encoding.Default.GetBytes(message);
// Set Content Length
sendNotificationRequest.ContentLength = notificationMessage.Length;
//Push data to stream
using (Stream requestStream = sendNotificationRequest.GetRequestStream())
{
requestStream.Write(notificationMessage, 0, notificationMessage.Length);
}
//Get reponse for message sending
HttpWebResponse response = (HttpWebResponse)sendNotificationRequest.GetResponse();
string notificationStatus = response.Headers["X-NotificationStatus"];
string notificationChannelStatus = response.Headers["X-SubscriptionStatus"];
string deviceConnectionStatus = response.Headers["X-DeviceConnectionStatus"];
Got it worked after moving the code to WCF project.

How to issue PUT HttpWebRequest

I'm trying to integrate with an API that requires a PUT to update data:
Here's an example from them using curl:
curl --request PUT \
--user-agent "Your Client Name/1.0" \
--header "Content-Type: application/xml" \
--data-binary '<order><status_id>10</status_id></order>' \
https://www.example.com/api/v2/orders/101
However, I'd need to use JSON (they support that as well) using .NET MVC 3. Any idea on how I can do that?
I use the code below for GET successfully:
Order obj = Call<Order>(url, "GET");
private T Call<T>(string url, string methodType) where T : class {
T result;
HttpWebRequest request = WebRequest.Create(url) as HttpWebRequest;
request.Method = methodType;
request.Accept = "application/json";
request.ContentType = "application/json";
using (HttpWebResponse response = request.GetResponse() as HttpWebResponse)
using (StreamReader reader = new StreamReader(response.GetResponseStream())) {
JavaScriptSerializer jsSerializer = new JavaScriptSerializer();
string jsonData = reader.ReadToEnd();
result = (T)jsSerializer.Deserialize<T>(jsonData);
}
return result;
}
However, can I issue a PUT using a similar method?
Order obj = Call<Order>(url, "PUT");
If so, where do I put the data that's required in "data-binary"?
Well, here's a possible point of origin - untested; written straight into the browser; not production code; assumes that the PUT call both sends and receives the same object type (which is probably not the case)...
The main addition is that you need to supply the request's ContentLength, and you need to write the serialized JSON object to the request stream, which you'll get by calling HttpWebRequest::GetRequestStream(). It's the same approach as when POSTing.
private T Call<T>(string url, string methodType, T data) where T: class
{
T result;
HttpWebRequest request = WebRequest.Create(url) as HttpWebRequest;
request.Method = methodType;
request.ContentType = "application/json";
request.Accept = "application/json";
if (methodType == "PUT" || methodType == "POST")
{
JavaScriptSerializer jsSerializer = new JavaScriptSerializer();
string jsonData = jsSerializer.Serialize(data);
byte[] arrData = Encoding.UTF8.GetBytes(jsonData);
request.ContentLength = arrData.Length;
using (Stream dataStream = request.GetRequestStream())
{
dataStream.Write(arrData, 0, arrData.Length);
}
}
// Note: You may not need to parse any response content,
// or it may be a different class
using (HttpWebResponse response = request.GetResponse() as HttpWebResponse)
{
using (StreamReader reader
= new StreamReader(response.GetResponseStream()))
{
JavaScriptSerializer jsSerializer = new JavaScriptSerializer();
string jsonData = reader.ReadToEnd();
result = (T)jsSerializer.Deserialize<T>(jsonData);
}
}
return result;
}

Resources