ASP .Net MVC: getting 352 error on uploading video to Facebook using Facebook SDK version 6.8 - asp.net

I am getting the following error when trying to upload video to Facebook from my web application:
"(OAuthException - #352) (#352) Sorry, the video file you selected is in a format that we don't support"
public void uploadVideoToFaceBook(string accessToken, string videoURL, string videoTitle)
{
byte[] stream = DownloadVideoAsByte(videoURL);
var mediaObject = new FacebookMediaObject
{
FileName = videoTitle,
ContentType = "video/mp4"
};
mediaObject.SetValue(stream);
try
{
var fb = new FacebookClient(accessToken);
dynamic result = fb.Post("me/videos",
new
{
message = "my first photo upload using Facebook SDK for .NET",
file = mediaObject
});
var videoId = (string)result["vid"];
}
catch (FacebookApiException ex)
{
throw;
}
}
Note: DownloadVideoAsByte() returns byte[] from azure blob. following is the code:
public byte[] DownloadVideoAsByte(string videoUrl)
{
HttpWebRequest httpRequest = (HttpWebRequest)WebRequest.Create(videoUrl);
httpRequest.Credentials = CredentialCache.DefaultCredentials;
HttpWebResponse httpResponse = (HttpWebResponse)httpRequest.GetResponse();
System.IO.Stream dataStream = httpResponse.GetResponseStream();
System.IO.StreamReader streamReader = new System.IO.StreamReader(dataStream);
String data = streamReader.ReadToEnd();
byte[] buffer = new byte[data.Length];
for (int i = 0; i < data.Length; i++)
buffer[i] = (byte)data[i];
dataStream.Close();
streamReader.Close();
return buffer;
}
Any help in this regard shall be appreciated.

Related

how to call google acknowledge api from wcf service?

i need to add a call to google acknowledge endpoint into existing dotnet web service app.
this is the refence page https://developers.google.com/android-publisher/api-ref/rest/v3/purchases.products/acknowledge
i never worked on this app before, and i can not ask who developed it, He went away.
in the web.config are stored PlayStore ClientId and ClientSecret.
this is existing and working call to check a subscription:
internal PlayStoreSubscriptionPurchaseStatus verifySubscription(string packageName, string subscriptionId, string token, ref long timeMills)
{
Stopwatch watcher = new Stopwatch();
string accessToken = this.generateNewAccessToken(ref timeMills);
string verifySubscriptionAddress = _playStoreApisAddress + packageName + "/purchases/subscriptions/" + subscriptionId + "/tokens/" + token + "?access_token=" + accessToken;
PlayStoreSubscriptionPurchaseStatus playStoreResponse = null;
try
{
HttpWebRequest verifyRequest = WebRequest.Create(verifySubscriptionAddress) as HttpWebRequest;
verifyRequest.Method = "GET";
verifyRequest.ContentType = "application/json; charset=utf-8";
verifyRequest.Accept = "application/json; charset=utf-8";
watcher.Start();
using (HttpWebResponse verifyResponse = verifyRequest.GetResponse() as HttpWebResponse)
{
watcher.Stop();
Stream responseStream = verifyResponse.GetResponseStream();
StreamReader streamReader = new StreamReader(responseStream);
string responseAsString = streamReader.ReadToEnd();
JavaScriptSerializer jss = new JavaScriptSerializer();
if (verifyResponse.StatusCode == HttpStatusCode.OK)
playStoreResponse = jss.Deserialize<PlayStoreSubscriptionPurchaseStatus>(responseAsString);
else
{
playStoreResponse = new PlayStoreSubscriptionPurchaseStatus() { Success = false, ErrorMessage = responseAsString };
}
}
}
catch (WebException webEx)
{
using (StreamReader streamReader = new StreamReader(webEx.Response.GetResponseStream()))
{
string webExResponse = streamReader.ReadToEnd();
throw new Exception("Errore nella verifica subscription google play.\nErrore restituito dalle api google play:\n" + webExResponse);
}
}
finally
{
if (watcher.IsRunning)
watcher.Stop();
timeMills += watcher.ElapsedMilliseconds;
}
return playStoreResponse;
}
this code generates access_token:
private string generateNewAccessToken(ref long timeMills)
{
Stopwatch watcher = new Stopwatch();
string newAccessToken = string.Empty;
string postDta = string.Format("grant_type={0}&client_id={1}&client_secret={2}&refresh_token={3}",
"refresh_token", Uri.EscapeDataString(_clientId), Uri.EscapeDataString(_clientSecret), Uri.EscapeDataString(_refreshToken));
try
{
HttpWebRequest refreshAccessTokenRequest = WebRequest.Create(_refreshTokenAddress) as HttpWebRequest;
refreshAccessTokenRequest.Method = "POST";
refreshAccessTokenRequest.ContentType = "application/x-www-form-urlencoded";
//refreshAccessTokenRequest.ContentLength = new UTF8Encoding().GetBytes(postDta).Length;
refreshAccessTokenRequest.Accept = "application/json; charset=utf-8";
Stream refreshTokenRequestStream = refreshAccessTokenRequest.GetRequestStream();
StreamWriter streamWriter = new StreamWriter(refreshTokenRequestStream);
streamWriter.Write(postDta);
streamWriter.Close();
watcher.Start();
using (HttpWebResponse refreshAccessTokenResponse = refreshAccessTokenRequest.GetResponse() as HttpWebResponse)
{
watcher.Stop();
Stream responseStream = refreshAccessTokenResponse.GetResponseStream();
StreamReader streamReader = new StreamReader(responseStream);
string responseAsString = streamReader.ReadToEnd();
JavaScriptSerializer jss = new JavaScriptSerializer();
RenewAccessTokenResponse renewAccessTokenResponse = jss.Deserialize<RenewAccessTokenResponse>(responseAsString);
newAccessToken = renewAccessTokenResponse.access_token;
}
}
catch (WebException webEx)
{
using (StreamReader streamReader = new StreamReader(webEx.Response.GetResponseStream()))
{
string webExResponse = streamReader.ReadToEnd();
throw new Exception(webExResponse);
}
}
finally
{
if (watcher.IsRunning)
watcher.Stop();
timeMills += watcher.ElapsedMilliseconds;
}
return newAccessToken;
}
what i want to know is if i can, using only httpwebrequest, make a call to acknlowelage api,
access token generate from generateNewAccessToken is good for this api?
if yes where do i have to store it? acknlowelage is POST while all existing calls in the project are GET. do i have store the access code in body or into some header?
there is somewhere a working sample?
thanks.

files not uploading to FTP Server [duplicate]

I try upload a file to an FTP-server with C#. The file is uploaded but with zero bytes.
private void button2_Click(object sender, EventArgs e)
{
var dirPath = #"C:/Documents and Settings/sander.GD/Bureaublad/test/";
ftp ftpClient = new ftp("ftp://example.com/", "username", "password");
string[] files = Directory.GetFiles(dirPath,"*.*");
var uploadPath = "/httpdocs/album";
foreach (string file in files)
{
ftpClient.createDirectory("/test");
ftpClient.upload(uploadPath + "/" + Path.GetFileName(file), file);
}
if (string.IsNullOrEmpty(txtnaam.Text))
{
MessageBox.Show("Gelieve uw naam in te geven !");
}
}
The existing answers are valid, but why re-invent the wheel and bother with lower level WebRequest types while WebClient already implements FTP uploading neatly:
using (var client = new WebClient())
{
client.Credentials = new NetworkCredential(ftpUsername, ftpPassword);
client.UploadFile("ftp://host/path.zip", WebRequestMethods.Ftp.UploadFile, localFile);
}
Easiest way
The most trivial way to upload a file to an FTP server using .NET framework is using WebClient.UploadFile method:
WebClient client = new WebClient();
client.Credentials = new NetworkCredential("username", "password");
var url = "ftp://ftp.example.com/remote/path/file.zip";
client.UploadFile(url, #"C:\local\path\file.zip");
Advanced options
If you need a greater control, that WebClient does not offer (like TLS/SSL encryption, ascii/text transfer mode, active mode, transfer resuming, progress monitoring, etc), use FtpWebRequest. Easy way is to just copy a FileStream to an FTP stream using Stream.CopyTo:
var url = "ftp://ftp.example.com/remote/path/file.zip";
FtpWebRequest request = (FtpWebRequest)WebRequest.Create(url);
request.Credentials = new NetworkCredential("username", "password");
request.Method = WebRequestMethods.Ftp.UploadFile;
using (Stream fileStream = File.OpenRead(#"C:\local\path\file.zip"))
using (Stream ftpStream = request.GetRequestStream())
{
fileStream.CopyTo(ftpStream);
}
Progress monitoring
If you need to monitor an upload progress, you have to copy the contents by chunks yourself:
var url = "ftp://ftp.example.com/remote/path/file.zip";
FtpWebRequest request = (FtpWebRequest)WebRequest.Create(url);
request.Credentials = new NetworkCredential("username", "password");
request.Method = WebRequestMethods.Ftp.UploadFile;
using (Stream fileStream = File.OpenRead(#"C:\local\path\file.zip"))
using (Stream ftpStream = request.GetRequestStream())
{
byte[] buffer = new byte[10240];
int read;
while ((read = fileStream.Read(buffer, 0, buffer.Length)) > 0)
{
ftpStream.Write(buffer, 0, read);
Console.WriteLine("Uploaded {0} bytes", fileStream.Position);
}
}
For GUI progress (WinForms ProgressBar), see C# example at:
How can we show progress bar for upload with FtpWebRequest
Uploading folder
If you want to upload all files from a folder, see
Upload directory of files to FTP server using WebClient.
For a recursive upload, see
Recursive upload to FTP server in C#
.NET 5 Guide
async Task<FtpStatusCode> FtpFileUploadAsync(string ftpUrl, string userName, string password, string filePath)
{
FtpWebRequest request = (FtpWebRequest)WebRequest.Create(ftpUrl);
request.Method = WebRequestMethods.Ftp.UploadFile;
request.Credentials = new NetworkCredential(userName, password);
using (FileStream fileStream = new FileStream(filePath, FileMode.Open, FileAccess.Read))
using (Stream requestStream = request.GetRequestStream())
{
await fileStream.CopyToAsync(requestStream);
}
using (FtpWebResponse response = (FtpWebResponse)await request.GetResponseAsync())
{
return response.StatusCode;
}
}
.NET Framework
public void UploadFtpFile(string folderName, string fileName)
{
FtpWebRequest request;
string folderName;
string fileName;
string absoluteFileName = Path.GetFileName(fileName);
request = WebRequest.Create(new Uri(string.Format(#"ftp://{0}/{1}/{2}", "127.0.0.1", folderName, absoluteFileName))) as FtpWebRequest;
request.Method = WebRequestMethods.Ftp.UploadFile;
request.UseBinary = 1;
request.UsePassive = 1;
request.KeepAlive = 1;
request.Credentials = new NetworkCredential(user, pass);
request.ConnectionGroupName = "group";
using (FileStream fs = File.OpenRead(fileName))
{
byte[] buffer = new byte[fs.Length];
fs.Read(buffer, 0, buffer.Length);
fs.Close();
Stream requestStream = request.GetRequestStream();
requestStream.Write(buffer, 0, buffer.Length);
requestStream.Flush();
requestStream.Close();
}
}
How to use
UploadFtpFile("testFolder", "E:\\filesToUpload\\test.img");
use this in your foreach
and you only need to create folder one time
to create a folder
request = WebRequest.Create(new Uri(string.Format(#"ftp://{0}/{1}/", "127.0.0.1", "testFolder"))) as FtpWebRequest;
request.Method = WebRequestMethods.Ftp.MakeDirectory;
FtpWebResponse ftpResponse = (FtpWebResponse)request.GetResponse();
The following works for me:
public virtual void Send(string fileName, byte[] file)
{
ByteArrayToFile(fileName, file);
var request = (FtpWebRequest) WebRequest.Create(new Uri(ServerUrl + fileName));
request.Method = WebRequestMethods.Ftp.UploadFile;
request.UsePassive = false;
request.Credentials = new NetworkCredential(UserName, Password);
request.ContentLength = file.Length;
var requestStream = request.GetRequestStream();
requestStream.Write(file, 0, file.Length);
requestStream.Close();
var response = (FtpWebResponse) request.GetResponse();
if (response != null)
response.Close();
}
You can't read send the file parameter in your code as it is only the filename.
Use the following:
byte[] bytes = File.ReadAllBytes(dir + file);
To get the file so you can pass it to the Send method.
public static void UploadFileToFtp(string url, string filePath, string username, string password)
{
var fileName = Path.GetFileName(filePath);
var request = (FtpWebRequest)WebRequest.Create(url + fileName);
request.Method = WebRequestMethods.Ftp.UploadFile;
request.Credentials = new NetworkCredential(username, password);
request.UsePassive = true;
request.UseBinary = true;
request.KeepAlive = false;
using (var fileStream = File.OpenRead(filePath))
{
using (var requestStream = request.GetRequestStream())
{
fileStream.CopyTo(requestStream);
requestStream.Close();
}
}
var response = (FtpWebResponse)request.GetResponse();
Console.WriteLine("Upload done: {0}", response.StatusDescription);
response.Close();
}
In the first example must change those to:
requestStream.Flush();
requestStream.Close();
First flush and after that close.
This works for me,this method will SFTP a file to a location within your network.
It uses SSH.NET.2013.4.7 library.One can just download it for free.
//Secure FTP
public void SecureFTPUploadFile(string destinationHost,int port,string username,string password,string source,string destination)
{
ConnectionInfo ConnNfo = new ConnectionInfo(destinationHost, port, username, new PasswordAuthenticationMethod(username, password));
var temp = destination.Split('/');
string destinationFileName = temp[temp.Count() - 1];
string parentDirectory = destination.Remove(destination.Length - (destinationFileName.Length + 1), destinationFileName.Length + 1);
using (var sshclient = new SshClient(ConnNfo))
{
sshclient.Connect();
using (var cmd = sshclient.CreateCommand("mkdir -p " + parentDirectory + " && chmod +rw " + parentDirectory))
{
cmd.Execute();
}
sshclient.Disconnect();
}
using (var sftp = new SftpClient(ConnNfo))
{
sftp.Connect();
sftp.ChangeDirectory(parentDirectory);
using (var uplfileStream = System.IO.File.OpenRead(source))
{
sftp.UploadFile(uplfileStream, destinationFileName, true);
}
sftp.Disconnect();
}
}
publish date: 06/26/2018
https://learn.microsoft.com/en-us/dotnet/framework/network-programming/how-to-upload-files-with-ftp
using System;
using System.IO;
using System.Net;
using System.Text;
namespace Examples.System.Net
{
public class WebRequestGetExample
{
public static void Main ()
{
// Get the object used to communicate with the server.
FtpWebRequest request =
(FtpWebRequest)WebRequest.Create("ftp://www.contoso.com/test.htm");
request.Method = WebRequestMethods.Ftp.UploadFile;
// This example assumes the FTP site uses anonymous logon.
request.Credentials = new NetworkCredential("anonymous",
"janeDoe#contoso.com");
// Copy the contents of the file to the request stream.
byte[] fileContents;
using (StreamReader sourceStream = new StreamReader("testfile.txt"))
{
fileContents = Encoding.UTF8.GetBytes(sourceStream.ReadToEnd());
}
request.ContentLength = fileContents.Length;
using (Stream requestStream = request.GetRequestStream())
{
requestStream.Write(fileContents, 0, fileContents.Length);
}
using (FtpWebResponse response = (FtpWebResponse)request.GetResponse())
{
Console.WriteLine($"Upload File Complete, status
{response.StatusDescription}");
}
}
}
}
Best way I've found is FluentFtp
You can find the repo here:
https://github.com/robinrodricks/FluentFTP
and the quickstart example here:
https://github.com/robinrodricks/FluentFTP/wiki/Quick-Start-Example.
And actually the WebRequest class recommended by a few people here, is not recommended by Microsoft anymore, check out this page:
https://learn.microsoft.com/en-us/dotnet/api/system.net.webrequest?view=net-5.0
// create an FTP client and specify the host, username and password
// (delete the credentials to use the "anonymous" account)
FtpClient client = new FtpClient("123.123.123.123", "david", "pass123");
// connect to the server and automatically detect working FTP settings
client.AutoConnect();
// upload a file and retry 3 times before giving up
client.RetryAttempts = 3;
client.UploadFile(#"C:\MyVideo.mp4", "/htdocs/big.txt",
FtpRemoteExists.Overwrite, false, FtpVerify.Retry);
// disconnect! good bye!
client.Disconnect();
I have observed that -
FtpwebRequest is missing.
As the target is FTP, so the NetworkCredential required.
I have prepared a method that works like this, you can replace the value of the variable ftpurl with the parameter TargetDestinationPath. I had tested this method on winforms application :
private void UploadProfileImage(string TargetFileName, string TargetDestinationPath, string FiletoUpload)
{
//Get the Image Destination path
string imageName = TargetFileName; //you can comment this
string imgPath = TargetDestinationPath;
string ftpurl = "ftp://downloads.abc.com/downloads.abc.com/MobileApps/SystemImages/ProfileImages/" + imgPath;
string ftpusername = krayknot_DAL.clsGlobal.FTPUsername;
string ftppassword = krayknot_DAL.clsGlobal.FTPPassword;
string fileurl = FiletoUpload;
FtpWebRequest ftpClient = (FtpWebRequest)FtpWebRequest.Create(ftpurl);
ftpClient.Credentials = new System.Net.NetworkCredential(ftpusername, ftppassword);
ftpClient.Method = System.Net.WebRequestMethods.Ftp.UploadFile;
ftpClient.UseBinary = true;
ftpClient.KeepAlive = true;
System.IO.FileInfo fi = new System.IO.FileInfo(fileurl);
ftpClient.ContentLength = fi.Length;
byte[] buffer = new byte[4097];
int bytes = 0;
int total_bytes = (int)fi.Length;
System.IO.FileStream fs = fi.OpenRead();
System.IO.Stream rs = ftpClient.GetRequestStream();
while (total_bytes > 0)
{
bytes = fs.Read(buffer, 0, buffer.Length);
rs.Write(buffer, 0, bytes);
total_bytes = total_bytes - bytes;
}
//fs.Flush();
fs.Close();
rs.Close();
FtpWebResponse uploadResponse = (FtpWebResponse)ftpClient.GetResponse();
string value = uploadResponse.StatusDescription;
uploadResponse.Close();
}
Let me know in case of any issue, or here is one more link that can help you:
https://msdn.microsoft.com/en-us/library/ms229715(v=vs.110).aspx

Problems with downloading pdf file from web api service

I'm trying to set up a web api service that searches for a .pdf file in a directory and returns the file if it's found.
The controller
public class ProductsController : ApiController
{
[HttpPost]
public HttpResponseMessage Post([FromBody]string certificateId)
{
string fileName = certificateId + ".pdf";
var path = #"C:\Certificates\20487A" + fileName;
//check the directory for pdf matching the certid
if (File.Exists(path))
{
//if there is a match then return the file
HttpResponseMessage result = new HttpResponseMessage(HttpStatusCode.OK);
var stream = new FileStream(path, FileMode.Open);
stream.Position = 0;
result.Content = new StreamContent(stream);
result.Content.Headers.ContentDisposition = new System.Net.Http.Headers.ContentDispositionHeaderValue("attachment") { FileName = fileName };
result.Content.Headers.ContentType = new System.Net.Http.Headers.MediaTypeHeaderValue("application/pdf");
result.Content.Headers.ContentDisposition.FileName = fileName;
return result;
}
else
{
HttpResponseMessage result = new HttpResponseMessage(HttpStatusCode.Gone);
return result;
}
}
}
I'm calling the service with the following code
private void GetCertQueryResponse(string url, string serial)
{
string encodedParameters = "certificateId=" + serial.Replace(" ", "");
HttpWebRequest httpRequest = (HttpWebRequest)WebRequest.Create(url);
httpRequest.Method = "POST";
httpRequest.ContentType = "application/x-www-form-urlencoded";
httpRequest.AllowAutoRedirect = false;
byte[] bytedata = Encoding.UTF8.GetBytes(encodedParameters);
httpRequest.ContentLength = bytedata.Length;
Stream requestStream = httpRequest.GetRequestStream();
requestStream.Write(bytedata, 0, bytedata.Length);
requestStream.Close();
HttpWebResponse response = (HttpWebResponse)httpRequest.GetResponse();
if (response.StatusCode == HttpStatusCode.OK)
{
byte[] bytes = null;
using (Stream stream = response.GetResponseStream())
using (MemoryStream ms = new MemoryStream())
{
int count = 0;
do
{
byte[] buf = new byte[1024];
count = stream.Read(buf, 0, 1024);
ms.Write(buf, 0, count);
} while (stream.CanRead && count > 0);
ms.Position = 0;
bytes = ms.ToArray();
}
var filename = serial + ".pdf";
Response.ContentType = "application/pdf";
Response.Headers.Add("Content-Disposition", "attachment; filename=\"" + filename + "\"");
Response.BinaryWrite(bytes);
}
}
This appears to be working in the sense that the download file dialogue is shown with the correct file name and size etc, but the download takes only a couple of seconds (when the file sizes are >30mb) and the files are corrupt when I try to open them.
Any ideas what I'm doing wrong?
Your code looks similar to what Ive used in the past, but below is what I typically use:
Response.AddHeader("content-length", myfile.Length.ToString())
Response.AddHeader("content-disposition", "inline; filename=MyFilename")
Response.AddHeader("Expires", "0")
Response.AddHeader("Pragma", "Cache")
Response.AddHeader("Cache-Control", "private")
Response.ContentType = "application/pdf"
Response.BinaryWrite(finalForm)
I post this for 2 reasons. One, add the content-length header, you may have to indicate how large the file is so the application waits for the whole response.
If that doesn't fix it. Set a breakpoint, does the byte array content the appropriate length (aka, 30 million bytes for a 30 MB file)? Have you used fiddler to see how much content is coming back over the HTTP call?

Google Drive api uploads file name as "Untitled"

I can upload file to google drive from my website, but my problem is it will show the file as Untitled after uploading.
How can I add or post title to the uploading file.
Thanks,
My Code:
public string UploadFile(string accessToken, byte[] file_data, string mime_type)
{
try
{
string result = "";
byte[] buffer = file_data;
HttpWebRequest request = (HttpWebRequest)WebRequest.Create("https://www.googleapis.com/upload/drive/v2/files?uploadType=media");
request.Method = "POST";
request.ContentType = mime_type;
request.ContentLength = buffer.Length;
request.Headers.Add(HttpRequestHeader.Authorization, "Bearer " + accessToken);
var stream = request.GetRequestStream();
stream.Write(file_data, 0, file_data.Length);
stream.Close();
HttpWebResponse webResponse = (HttpWebResponse)request.GetResponse();//Get error here
if(webResponse.StatusCode == HttpStatusCode.OK)
{
Stream responseStream = webResponse.GetResponseStream();
StreamReader responseStreamReader = new StreamReader(responseStream);
result = responseStreamReader.ReadToEnd();//parse token from result
var jLinq = JObject.Parse(result);
JObject jObject = JObject.Parse(jLinq.ToString());
webResponse.Close();
return jObject["alternateLink"].ToString();
}
return string.Empty;
}
catch
{
return string.Empty;
}
}
I used RestSharp for uploading a file to google drive.
public static void UploadFile(string accessToken, string parentId)
{
var client = new RestClient { BaseUrl = new Uri("https://www.googleapis.com/") };
var request = new RestRequest(string.Format("/upload/drive/v2/files?uploadType=multipart&access_token={0}", accessToken), Method.POST);
var bytes = File.ReadAllBytes(#"D:\mypdf.pdf");
var content = new { title = "mypdf.pdf", description = "mypdf.pdf", parents = new[] { new { id = parentId } }, mimeType = "application/pdf" };
var data = JsonConvert.SerializeObject(content);
request.AddFile("content", Encoding.UTF8.GetBytes(data), "content", "application/json; charset=utf-8");
request.AddFile("mypdf.pdf", bytes, "mypdf.pdf", "application/pdf");
var response = client.Execute(request);
if (response.StatusCode != HttpStatusCode.OK) throw new Exception("Unable to upload file to google drive");
}
Doing it with out using the google.apis dlls isnt that easy. You need to send the meta data before you send the rest of the file. For that you need to use uploadType=multipart
https://developers.google.com/drive/manage-uploads#multipart
This should get you started sorry its a wall of code. I havent had time to create a tutorial for this yet.
FileInfo info = new FileInfo(pFilename);
//Createing the MetaData to send
List<string> _postData = new List<string>();
_postData.Add("{");
_postData.Add("\"title\": \"" + info.Name + "\",");
_postData.Add("\"description\": \"Uploaded with SendToGoogleDrive\",");
_postData.Add("\"parents\": [{\"id\":\"" + pFolder + "\"}],");
_postData.Add("\"mimeType\": \"" + GetMimeType(pFilename).ToString() + "\"");
_postData.Add("}");
string postData = string.Join(" ", _postData.ToArray());
byte[] MetaDataByteArray = Encoding.UTF8.GetBytes(postData);
// creating the Data For the file
byte[] FileByteArray = System.IO.File.ReadAllBytes(pFilename);
string boundry = "foo_bar_baz";
string url = "https://www.googleapis.com/upload/drive/v2/files?uploadType=multipart" + "&access_token=" + myAutentication.accessToken;
WebRequest request = WebRequest.Create(url);
request.Method = "POST";
request.ContentType = "multipart/related; boundary=\"" + boundry + "\"";
// Wrighting Meta Data
string headerJson = string.Format("--{0}\r\nContent-Type: {1}\r\n\r\n",
boundry,
"application/json; charset=UTF-8");
string headerFile = string.Format("\r\n--{0}\r\nContent-Type: {1}\r\n\r\n",
boundry,
GetMimeType(pFilename).ToString());
string footer = "\r\n--" + boundry + "--\r\n";
int headerLenght = headerJson.Length + headerFile.Length + footer.Length;
request.ContentLength = MetaDataByteArray.Length + FileByteArray.Length + headerLenght;
Stream dataStream = request.GetRequestStream();
dataStream.Write(Encoding.UTF8.GetBytes(headerJson), 0, Encoding.UTF8.GetByteCount(headerJson)); // write the MetaData ContentType
dataStream.Write(MetaDataByteArray, 0, MetaDataByteArray.Length); // write the MetaData
dataStream.Write(Encoding.UTF8.GetBytes(headerFile), 0, Encoding.UTF8.GetByteCount(headerFile)); // write the File ContentType
dataStream.Write(FileByteArray, 0, FileByteArray.Length); // write the file
// Add the end of the request. Start with a newline
dataStream.Write(Encoding.UTF8.GetBytes(footer), 0, Encoding.UTF8.GetByteCount(footer));
dataStream.Close();
try
{
WebResponse response = request.GetResponse();
// Get the stream containing content returned by the server.
dataStream = response.GetResponseStream();
// Open the stream using a StreamReader for easy access.
StreamReader reader = new StreamReader(dataStream);
// Read the content.
string responseFromServer = reader.ReadToEnd();
// Display the content.
//Console.WriteLine(responseFromServer);
// Clean up the streams.
reader.Close();
dataStream.Close();
response.Close();
}
catch (Exception ex)
{
return "Exception uploading file: uploading file." + ex.Message;
}
If you need any explinations beyond the comments let me know. I strugled to get this working for a month. Its almost as bad as resumable upload.
I was searching for the solution of the given problem and previously I was putting uploadType=resumable that causes the given issue and when I used uploadType=multipart problem is resolved...

ASP .Net Web API downloading images as binary

I want to try to use Web API make a rest call but I want the response to be the actual binary image stored in a database, not a JSON base64 encoded string. Anyone got some pointers on this?
Update-
This is what I ended up implementing:
HttpResponseMessage result = new HttpResponseMessage(HttpStatusCode.OK);
result.Content = new StreamContent(new MemoryStream(profile.Avatar));
result.Content.Headers.ContentType = new MediaTypeHeaderValue("application/octet-stream");
result.Content.Headers.ContentDisposition = new ContentDispositionHeaderValue("attachment");
result.Content.Headers.ContentDisposition.FileName = "avatar.png";
return result;
You can set the response content to a StreamContent object:
var fileStream = new FileStream(path, FileMode.Open);
var resp = new HttpResponseMessage()
{
Content = new StreamContent(fileStream)
};
// Find the MIME type
string mimeType = _extensions[Path.GetExtension(path)];
resp.Content.Headers.ContentType = new MediaTypeHeaderValue(mimeType);
While this has been marked as answered, it wasn't quite what I wanted, so I kept looking. Now that I've figured it out, here's what I've got:
public FileContentResult GetFile(string id)
{
byte[] fileContents;
using (MemoryStream memoryStream = new MemoryStream())
{
using (Bitmap image = new Bitmap(WebRequest.Create(myURL).GetResponse().GetResponseStream()))
image.Save(memoryStream, ImageFormat.Jpeg);
fileContents = memoryStream.ToArray();
}
return new FileContentResult(fileContents, "image/jpg");
}
Granted, that's for getting an image through a URL. If you just want to grab an image off the file server, I'd imagine you replace this line:
using (Bitmap image = new Bitmap(WebRequest.Create(myURL).GetResponse().GetResponseStream()))
With this:
using (Bitmap image = new Bitmap(myFilePath))
EDIT: Never mind, this is for regular MVC. for Web API, I have this:
public HttpResponseMessage Get(string id)
{
string fileName = string.Format("{0}.jpg", id);
if (!FileProvider.Exists(fileName))
throw new HttpResponseException(HttpStatusCode.NotFound);
FileStream fileStream = FileProvider.Open(fileName);
HttpResponseMessage response = new HttpResponseMessage { Content = new StreamContent(fileStream) };
response.Content.Headers.ContentType = new MediaTypeHeaderValue("image/jpg");
response.Content.Headers.ContentLength = FileProvider.GetLength(fileName);
return response;
}
Which is quite similar to what OP has.
I did this exact thing. Here is my code:
if (!String.IsNullOrWhiteSpace(imageName))
{
var savedFileName = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, Path.Combine(uploadPath, imageName));
var image = System.Drawing.Image.FromFile(savedFileName);
if (ImageFormat.Jpeg.Equals(image.RawFormat))
{
// JPEG
using(var memoryStream = new MemoryStream())
{
image.Save(memoryStream, ImageFormat.Jpeg);
var result = new HttpResponseMessage(HttpStatusCode.OK)
{
Content = new ByteArrayContent(memoryStream.ToArray())
};
result.Content.Headers.ContentType = new MediaTypeHeaderValue("image/jpeg");
result.Content.Headers.ContentLength = memoryStream.Length;
return result;
}
}
else if (ImageFormat.Png.Equals(image.RawFormat))
{
// PNG
using (var memoryStream = new MemoryStream())
{
image.Save(memoryStream, ImageFormat.Png);
var result = new HttpResponseMessage(HttpStatusCode.OK)
{
Content = new ByteArrayContent(memoryStream.ToArray())
};
result.Content.Headers.ContentType = new MediaTypeHeaderValue("image/png");
result.Content.Headers.ContentLength = memoryStream.Length;
return result;
}
}
else if (ImageFormat.Gif.Equals(image.RawFormat))
{
// GIF
using (var memoryStream = new MemoryStream())
{
image.Save(memoryStream, ImageFormat.Gif);
var result = new HttpResponseMessage(HttpStatusCode.OK)
{
Content = new ByteArrayContent(memoryStream.ToArray())
};
result.Content.Headers.ContentType = new MediaTypeHeaderValue("image/gif");
result.Content.Headers.ContentLength = memoryStream.Length;
return result;
}
}
}
And then on the client:
var client = new HttpClient();
var imageName = product.ImageUrl.Replace("~/Uploads/", "");
var path = Path.Combine(AppDomain.CurrentDomain.BaseDirectory,
Properties.Settings.Default.DeviceMediaPath + "\\" + imageName);
var response =
client.GetAsync(apiUrl + "/Image?apiLoginId=" + apiLoginId + "&authorizationToken=" + authToken +
"&imageName=" + product.ImageUrl.Replace("~/Uploads/","")).Result;
if (response.IsSuccessStatusCode)
{
var data = response.Content.ReadAsByteArrayAsync().Result;
using (var ms = new MemoryStream(data))
{
using (var fs = File.Create(path))
{
ms.CopyTo(fs);
}
}
result = true;
}
else
{
result = false;
break;
}
This task is much easily achieved without using WebAPI. I would implement a custom HTTP handler for a unique extension, and return the binary response there. The plus is that you can also modify the HTTP Response headers and content type, so you have absolute control over what is returned.
You can devise a URL pattern (defining how you know what image to return based on its URL), and keep those URLs in your API resources. Once the URL is returned in the API response, it can be directly requested by the browser, and will reach your HTTP handler, returning the correct image.
Images are static content and have their own role in HTTP and HTML - no need to mix them with the JSON that is used when working with an API.

Resources