Getting file info from memory stream - c#

I am trying to make webapi which returns image
[HttpGet("[action]")]
public IActionResult GetCheckInPhoto(int checkInId, string dealerNr, int photoIndex, int photoType)
{
var stream = _checkinService.GetCheckInPhoto(checkInId, dealerNr, photoIndex, photoType);
return new MultipartResult(){
new MultipartContent()
{
ContentType = System.Net.Mime.MediaTypeNames.Image.Jpeg,
Name = "xxx",
FileName = "dsada",
Stream = stream
}
};
}
My method GetCheckInPhoto returns MemoryStream where is photo.
how to get FileInfo like Filename or FileType from MemoryStream?

Your "CheckinService" should return something like
public class MyFile
{
public string FileName { get; set; }
public string ContentType { get; set; }
public Stream ReadStream { get; set; }
}

Related

How to convert byte array to HttpPostedFileBase in C#?

I am using asp.net MVC web application. My requirement is to convert byte array to HttpPostedFileBase. I am creating byte array using filepath.
I have taken reference of this question
how to convert a byte[] to HttpPostedFileBase using c# (answer by https://stackoverflow.com/users/2678145/zerratar)
When I used that code I am getting exception while saving that converted file to server. Exception is method or operation is not implemented.
I thought I am getting error because, the content type and filename of converted file was returning null.
So I slightly changed the code like this.
public class HttpPostedFileForStl : HttpPostedFileBase
{
private readonly byte[] fileBytes;
public HttpPostedFileForStl(byte[] fileBytes, string fileName)
{
this.fileBytes = fileBytes;
this.InputStream = new MemoryStream(fileBytes);
this.FileName = fileName;
}
public override int ContentLength => fileBytes.Length;
public override string FileName { get; }
public override string ContentType { get; } = "application/octet-stream";
public override Stream InputStream { get; }
}
I am passing byte array and filename to this class.
Now I am getting appropriate filename and content type in converted file, but exception is still there. Can anyone help?
public class HttpPostedFileBaseCustom : HttpPostedFileBase
{
private byte[] _Bytes;
private String _ContentType;
private String _FileName;
private MemoryStream _Stream;
public override Int32 ContentLength { get { return this._Bytes.Length; } }
public override String ContentType { get { return this._ContentType; } }
public override String FileName { get { return this._FileName; } }
public override Stream InputStream
{
get
{
if(this._Stream == null)
{
this._Stream = new MemoryStream(this._Bytes);
}
return this._Stream;
}
}
public HttpPostedFileBaseCustom(byte[] contentData, String contentType, String fileName)
{
this._ContentType = contentType;
this._FileName = fileName;
this._Bytes = contentData ?? new byte[0];
}
public override void SaveAs(String filename)
{
System.IO.File.WriteAllBytes(filename, this._Bytes);
}
}

List assigned to Json deserialize is null

Since my last question was marked as duplicate and i didn't find an answer in recommended link i'm asking my question again.
I want to deserialize some JSON data and pass it to view in my ASP.NET MVC 5 app.
My model:
public class OrderModel
{
public string Seat { get; set; }
public string objectId { get; set; }
public DateTime? createdAt { get; set; }
}
I've read that to deserialize JSON data to list of object i have to make "root" class which is here:
public class OrderRootModel
{
public List<OrderModel> OrderList { get; set; }
}
Here is a method that gets JSON data in ApiModel class and assignsit to list. This method is probably a problem since it is returning null :
//ApiModel class
public OrderRootModel GetOrderData()
{
string url = "https://api.parse.com/1/classes/Orders";
OrderRootModel model = new OrderRootModel();
model = JsonConvert.DeserializeObject<OrderRootModel>(getParseIdData(url));
return model;
}
Here is a method that gets JSON string:
public string getParseIdData(string url)
{
HttpWebRequest request = (HttpWebRequest)WebRequest.Create(url);
request.Headers.Add("X-Parse-Application-Id", id);
request.Headers.Add("X-Parse-REST-API-KEY", key);
try
{
WebResponse response = request.GetResponse();
using (Stream responseStream = response.GetResponseStream())
{
StreamReader reader = new StreamReader(responseStream, Encoding.UTF8);
return reader.ReadToEnd();
}
}
catch (WebException ex)
{
WebResponse errorResponse = ex.Response;
using (Stream responseStream = errorResponse.GetResponseStream())
{
StreamReader reader = new StreamReader(responseStream, Encoding.GetEncoding("utf-8"));
String errorText = reader.ReadToEnd();
Console.WriteLine(errorText);
}
throw;
}
}
Here is getParseIdData() response:
{"results":[{"Seat":"5","createdAt":"2015-11-29T18:50:15.320Z","objectId":"BsDSolYPsT","updatedAt":"2015-11-29T19:40:55.020Z"},{"Seat":"6","createdAt":"2015-12-02T22:31:36.892Z","objectId":"kQJ0R5TUvw","updatedAt":"2015-12-02T22:31:36.892Z"},{"Seat":"7","createdAt":"2015-12-02T22:31:40.261Z","objectId":"sVtdj3aipb","updatedAt":"2015-12-02T22:31:40.261Z"},{"Seat":"8","createdAt":"2015-12-02T22:31:43.082Z","objectId":"7oH2ySrDFH","updatedAt":"2015-12-02T22:31:43.082Z"}]}
My controller:
public ActionResult Index()
{
ApiModel model = new ApiModel();
return View(model.GetOrderData()) ;
}
So probably i've made a mistake somewhere in GetOrderData() method since it returns null. Can you help me to solve this issue?
Based on your code this is what would the C# Class should look like when converting your JSON to a C# Class
{
"results":[
{"Seat":"5","createdAt":"2015-11-29T18:50:15.320Z","objectId":"BsDSolYPsT","updatedAt":"2015-11-29T19:40:55.020Z"},
{"Seat":"6","createdAt":"2015-12-02T22:31:36.892Z","objectId":"kQJ0R5TUvw","updatedAt":"2015-12-02T22:31:36.892Z"},
{"Seat":"7","createdAt":"2015-12-02T22:31:40.261Z","objectId":"sVtdj3aipb","updatedAt":"2015-12-02T22:31:40.261Z"},
{"Seat":"8","createdAt":"2015-12-02T22:31:43.082Z","objectId":"7oH2ySrDFH","updatedAt":"2015-12-02T22:31:43.082Z"}
]
}
public class Result
{
public string Seat { get; set; }
public string createdAt { get; set; }
public string objectId { get; set; }
public string updatedAt { get; set; }
}
public class RootObject
{
public List<Result> results { get; set; }
}

Deserialisation unable to list data

I am trying to create an application that can both serialise and deserialise data, i can serialise the information however when i try to read the information i am left with an empty list and i do not know why.
My Serialization class
[Serializable()]
public class FileSerilizeObject
{
public static string FileName { get; set; }
public static string Extension { get; set; }
public static string Base64 { get; set; }
public FileSerilizeObject(string filename, string extension, string base64vaulue)
{
FileName = filename;
Extension = extension;
Base64 = base64vaulue;
}
}
}
My serialization/deserialization methods
public void Serialize(List<FileSerilizeObject> List)
{
using (Stream stream = File.Open(savepath, FileMode.OpenOrCreate))
{
BinaryFormatter bin = new BinaryFormatter();
bin.Serialize(stream, List);
stream.Close();
}
}
public List<FileSerilizeObject> Deserialised(string OpenPath)
{
List<FileSerilizeObject> defo;
using(Stream stream = File.Open(OpenPath, FileMode.Open))
{
BinaryFormatter bin = new BinaryFormatter();
defo = (List<FileSerilizeObject>)bin.Deserialize(stream);
}
return defo;
}
I have checked to insure that the file paths are correct and that the file itself is not empty.Everything is fine however the "defo" list is always empty so i can only assume the issue is with the defo = (List<FileSerilizeObject>)bin.Deserialize(stream);Line however i do not know why.
You need to remove the static from your properties
[Serializable]
public class FileSerializeObject
{
public string FileName { get; set; }
public string Extension { get; set; }
public string Base64 { get; set; }
public FileSerializeObject(string filename, string extension, string base64vaulue)
{
FileName = filename;
Extension = extension;
Base64 = base64vaulue;
}
}
Try to set the [Serializable()] attribute for each property.
So it would look like this:
[Serializable()]
public class FileSerilizeObject
{
[Serializable()]
public string FileName { get; set; }
[Serializable()]
public string Extension { get; set; }
[Serializable()]
public string Base64 { get; set; }
public FileSerilizeObject(string filename, string extension, string base64vaulue)
{
FileName = filename;
Extension = extension;
Base64 = base64vaulue;
}
}
}
EDIT: Removed static keyword from properties.
I tested your code into a console application and it is working for me, I tested with VS 2013 but I used the same code that you wrote above.
Some details:
1. I removed the word static form the "FileSerilizeObject"
The class FileSerilizeObject
[Serializable()]
public class FileSerilizeObject
{
public string FileName { get; set; }
public string Extension { get; set; }
public string Base64 { get; set; }
public FileSerilizeObject(string filename, string extension, string base64vaulue)
{
FileName = filename;
Extension = extension;
Base64 = base64vaulue;
}
}
Functions
public static void Serialize(List<FileSerilizeObject> List)
{
using (Stream stream = File.Open(#"C:\Users\ttest\Desktop\folder1\data.bin", FileMode.OpenOrCreate))
{
BinaryFormatter bin = new BinaryFormatter();
bin.Serialize(stream, List);
stream.Close();
}
}
public static List<FileSerilizeObject> Deserialised(string OpenPath)
{
List<FileSerilizeObject> defo;
using (Stream stream = File.Open(OpenPath, FileMode.Open))
{
BinaryFormatter bin = new BinaryFormatter();
defo = (List<FileSerilizeObject>)bin.Deserialize(stream);
}
return defo;
}
Main
var bytes = Encoding.UTF8.GetBytes("dffesdbcdef==");
var base64 = Convert.ToBase64String(bytes);
FileSerilizeObject f1 = new FileSerilizeObject("test", "jpg", base64);
bytes = Encoding.UTF8.GetBytes("ggasddbcdef==");
base64 = Convert.ToBase64String(bytes);
FileSerilizeObject f2 = new FileSerilizeObject("test2", "png", base64);
bytes = Encoding.UTF8.GetBytes("asddffasdasdasdesdbcdef==");
base64 = Convert.ToBase64String(bytes);
FileSerilizeObject f3 = new FileSerilizeObject("test3", "doc", base64);
List<FileSerilizeObject> lFiles = new List<FileSerilizeObject>();
lFiles.Add(f1);
lFiles.Add(f2);
lFiles.Add(f3);
Serialize(lFiles);
Deserialised(#"C:\Users\rjimen4x\Desktop\tutoriales\data.bin");

How to Implement a Web API controller to accept chunked uploads using JQuery File Upload?

As the title states, I need some help implementing a Web API controller to accept chunked uploads using JQuery File Upload. Any help (including links to existing articles/tutorials) will be much appreciated.
First let start with the client side.
You must set the maxChunkSize option for chunked uploads. After that you need a unique identifier per file in order to identify each chunk on the server and append the corresponding chunk data to the correct file.
$('#fileupload')
.bind('fileuploadsubmit', function (e, data) {
data.headers = $.extend(data.headers,
{"X-File-Identifier": generateFileUniqueIdentifier(data)})
});
});
generateFileUniqueIdentifier = function(data){
var file=data.files[0],
var result = file.relativePath||file.webkitRelativePath||file.fileName||file.name;
return result.replace(/[^0-9a-zA-Z_-]/img,"") + "-" + i.size + "-" + $.now()
}
Now on the server side: ApiController
public class UploadController : ApiController
{
[HttpPost]
[Route("upload/{targetFolder:int}")]
[ValidateMimeMultipartContentFilter]
public async Task<IHttpActionResult> UploadDocument(int targetFolder)
{
var uploadFileService = new UploadFileService();
UploadProcessingResult uploadResult = await uploadFileService.HandleRequest(Request);
if (uploadResult.IsComplete)
{
// do other stuff here after file upload complete
return Ok();
}
return Ok(HttpStatusCode.Continue);
}
}
The service class which actually upload the file. This support chunks or a whole file.
public class UploadFileService
{
private readonly string _uploadPath;
private readonly MultipartFormDataStreamProvider _streamProvider;
public UploadFileService()
{
_uploadPath = UserLocalPath;
_streamProvider = new MultipartFormDataStreamProvider(_uploadPath);
}
#region Interface
public async Task<UploadProcessingResult> HandleRequest(HttpRequestMessage request)
{
await request.Content.ReadAsMultipartAsync(_streamProvider);
return await ProcessFile(request);
}
#endregion
#region Private implementation
private async Task<UploadProcessingResult> ProcessFile(HttpRequestMessage request)
{
if (request.IsChunkUpload())
{
return await ProcessChunk(request);
}
return new UploadProcessingResult()
{
IsComplete = true,
FileName = OriginalFileName,
LocalFilePath = LocalFileName,
FileMetadata = _streamProvider.FormData
};
}
private async Task<UploadProcessingResult> ProcessChunk(HttpRequestMessage request)
{
//use the unique identifier sent from client to identify the file
FileChunkMetaData chunkMetaData = request.GetChunkMetaData();
string filePath = Path.Combine(_uploadPath, string.Format("{0}.temp", chunkMetaData.ChunkIdentifier));
//append chunks to construct original file
using (FileStream fileStream = new FileStream(filePath, FileMode.OpenOrCreate | FileMode.Append))
{
var localFileInfo = new FileInfo(LocalFileName);
var localFileStream = localFileInfo.OpenRead();
await localFileStream.CopyToAsync(fileStream);
await fileStream.FlushAsync();
fileStream.Close();
localFileStream.Close();
//delete chunk
localFileInfo.Delete();
}
return new UploadProcessingResult()
{
IsComplete = chunkMetaData.IsLastChunk,
FileName = OriginalFileName,
LocalFilePath = chunkMetaData.IsLastChunk ? filePath : null,
FileMetadata = _streamProvider.FormData
};
}
#endregion
#region Properties
private string LocalFileName
{
get
{
MultipartFileData fileData = _streamProvider.FileData.FirstOrDefault();
return fileData.LocalFileName;
}
}
private string OriginalFileName
{
get
{
MultipartFileData fileData = _streamProvider.FileData.FirstOrDefault();
return fileData.Headers.ContentDisposition.FileName.Replace("\"", string.Empty);
}
}
private string UserLocalPath
{
get
{
//return the path where you want to upload the file
}
}
#endregion
}
The extensions over HttpRequestMessagge used to identify a chunk request
public static class HttpRequestMessageExtensions
{
public static bool IsChunkUpload(this HttpRequestMessage request)
{
return request.Content.Headers.ContentRange != null;
}
public static FileChunkMetaData GetChunkMetaData(this HttpRequestMessage request)
{
return new FileChunkMetaData()
{
ChunkIdentifier = request.Headers.Contains("X-DS-Identifier") ? request.Headers.GetValues("X-File-Identifier").FirstOrDefault() : null,
ChunkStart = request.Content.Headers.ContentRange.From,
ChunkEnd = request.Content.Headers.ContentRange.To,
TotalLength = request.Content.Headers.ContentRange.Length
};
}
}
And at the end the service response model and chunk metadata
public class FileChunkMetaData
{
public string ChunkIdentifier { get; set; }
public long? ChunkStart { get; set; }
public long? ChunkEnd { get; set; }
public long? TotalLength { get; set; }
public bool IsLastChunk
{
get { return ChunkEnd + 1 >= TotalLength; }
}
}
public class UploadProcessingResult
{
public bool IsComplete { get; set; }
public string FileName { get; set; }
public string LocalFilePath { get; set; }
public NameValueCollection FileMetadata { get; set; }
}
The MultiPartContentFilter is just an ActionFilter to validate the content (from damienbod)
public class ValidateMimeMultipartContentFilter : ActionFilterAttribute
{
public override void OnActionExecuting(HttpActionContext actionContext)
{
if (!actionContext.Request.Content.IsMimeMultipartContent())
{
throw new HttpResponseException(HttpStatusCode.UnsupportedMediaType);
}
}
public override void OnActionExecuted(HttpActionExecutedContext actionExecutedContext)
{
}
}
You can find inspiration here: ASP.NET Multiple File Upload With Drag & Drop and Progress Bar Using HTML5. An example of a chunked upload controller method starts in UploadFile. On the client, jquery file upload option maxChunkSize needs to be set according to https://github.com/blueimp/jQuery-File-Upload/wiki/Options .

JSON deserialization not working after changing response string

I want to deserialize following string:
YAHOO.Finance.SymbolSuggest.ssCallback({"ResultSet":{"Query":"google","Result":[{"symbol":"GOOG","name": "Google Inc.","exch": "NMS","type": "S","exchDisp":"NASDAQ","typeDisp":"Equity"},{"symbol":"GGQ1.DE","name": "GOOGLE-A","exch": "GER","type": "S","exchDisp":"XETRA","typeDisp":"Equity"}]}})
Which I download with a WebClient. But before I can deserialize, I need to remove "YAHOO.Finance.SymbolSuggest.ssCallback(" and the ")" at the end:
// get response
WebResponse response = request.EndGetResponse(result);
Stream stream = response.GetResponseStream();
// convert to string
StreamReader reader = new StreamReader(stream);
string output = reader.ReadToEnd();
// cut string
output = output.Substring(39, output.Length - 40);
// convert back to stream
MemoryStream ms = new MemoryStream(Encoding.UTF8.GetBytes(output));
So, the response I get is a stream. I convert that stream to a string, change the string and then convert the string back to a stream. Next, I try to deserialize:
// parse json
System.Runtime.Serialization.Json.DataContractJsonSerializer rootSer = new System.Runtime.Serialization.Json.DataContractJsonSerializer(typeof(RootObject));
// get root object
RootObject root = (RootObject)rootSer.ReadObject(ms);
// add to listbox
foreach (Result res in root.ResultSet.Result)
{
Dispatcher.BeginInvoke(() => ResultList.Add(res));
}
The problem is I get a nullpointexeption in the foreach...
My classes are like so:
public class Result
{
public string symbol { get; set; }
public string name { get; set; }
public string exch { get; set; }
public string type { get; set; }
public string exchDisp { get; set; }
public string typeDisp { get; set; }
}
public class ResultSet
{
public string Query { get; set; }
public List<Result> Result { get; set; }
}
public class RootObject
{
public ResultSet ResultSet { get; set; }
}
You can use Regex to extract the json from jsonp
output = Regex.Match(output, #".+?\((.+?)\)").Groups[1].Value

Categories

Resources