Why does sending files from GridFS via MVC4 take so much time? - mongodb

I want to send images stored in MongoDB using GridFS via a MVC4 Web app to the browser via my LAN environment, but it take ~500ms until the image is sent to the browser.
Google Chrome network inspector says most of the time is spent during "Waiting" while the actual "Receiving" takes ~1ms.
The MongoDB server is in the local network, so what can take so long to send an 10kb image? I use Windows 8 with Visual Studio 2012 and the official mongo-csharp-driver via NuGet.
Here is my code of my "Files" controller which takes an object id and sends the data for this id:
public FileContentResult Files(string id)
{
var database = new MongoClient(MyConnection).GetServer().GetDatabase("MyDB");
var gridFs = new MongoGridFS(database);
var bsonId = new BsonObjectId(id);
var gridInfo = gridFs.FindOneById(bsonId);
var bytes = GridInfoToArray(gridInfo);
return new FileContentResult(bytes, "image/jpeg") { FileDownloadName = gridInfo.Name };
}
private byte[] GridInfoToArray(MongoGridFSFileInfo file)
{
using (var stream = file.OpenRead())
{
var bytes = new byte[stream.Length];
stream.Read(bytes, 0, (int)stream.Length);
return bytes;
}
}
Code to display the image in a View:
<img src="#Url.Action("Files", new { id = objectIdOfMyImage) })"/>

How different are the results if you cache your Database and MongoGridFS instances?
// create static fields for _database & _gridFs
var database = _database ??
(_database = new MongoClient(MyConnection).GetServer().GetDatabase("MyDB"));
var gridFs = _gridFs ??
(_gridFs = new MongoGridFS(database));
I'm not sure how much overhead it incurs when you instantiate these, but it wouldn't hurt to move it outside of the method you're trying to optimize.

Related

How to upload image file in Xamarin forms using rest api . Have issues with large images

I tried and I face a problem when uploading images greater than 570 kb. This issue is in Xamarin Forms for android and PHP rest api. I tested the rest api separately and I have no issues there uploading 2mb files using postman.
Tried various ways also by giving some delay. I am capturing image using cross.media plugin. Then navigating to another page to upload. I wait for sometime and then click the button to upload. I am not able ascertain where the issue is.
System.IO.Stream fileStream = System.IO.File.Open(file, FileMode.Open);
byte[] data = ReadFully(fileStream);
fileStream.Close();
MultipartFormDataContent multi = new MultipartFormDataContent();
ByteArrayContent imageStream = new ByteArrayContent(data);
StringContent SequenceID = new StringContent(osequence);
imageStream.Headers.ContentType = new MediaTypeHeaderValue("image/jpg");
imageStream.Headers.ContentDisposition = new ContentDispositionHeaderValue("attachment")
{
FileName = osequence, // "screenshot.jpg", // generate this and send
Name = "avatar",
};
multi.Add(imageStream);
alertLabel.Text = "Uploading Now";
var response = await App.client.PostAsync(url, multi);
string responsestr = response.Content.ReadAsStringAsync().Result;
var retresponse = new retResponse();
bool uploadSuccess = false;
I have made the rest api to send response on error and showing the same in an alert box as below
if (responsestr != "") alertLabel.Text = responsestr.ToString();
else alertLabel.Text = alertLabel.Text + " After Upload Command ";
}
catch (Exception e)
{
}
} // private void upload(MediaFile mediaFile)
The error I get is no file sent
Please ignore the above question. The problem was solved by changing the PHP.ini max upload file size. The file size in the device was around 500 - 700 KB . don't know how it comes to 1.99 and 2 mb when uploaded. Increasing max file size solved it.

How to connect sqlite db to unity

I have a preloaded db file, which is present in c drive in my system. If I connect that db file to unity project and try to get data from tables it didn't get any data and I am not getting any exceptions also. If I open this db file (which is present in c drive) with sqlite admin software it shows data in tables. Please suggest any idea, what I am missing. Here is the code I am using for connecting database to my unity project.
Public void OpenDatabase()
{
var dbfileName = "Testuser.db"
var _filePath = File.GetFullPath(dbfileName);
var _connectionString = "URI=file:" + _filePath;
dbcon = new SqliteConnection(_connectionString);
dbcon.Open();
}
When I am trying to create and read db file in the following manner working well.
Working code :
Public void OpenDatabase()
{
var _filePath = Application.PersistanceDataPath + "/" + "owndbfile.db";
if (!File.Exists(_filePath))
{
WWW loadDB = new WWW("jar:file://" + Application.PersistanceDataPath + "!/assets/" + "owndbfile.db");
while (!loadDB.isDone) { }
// then save to Application.persistentDataPath
File.WriteAllBytes(_filePath, loadDB.bytes);
}
var _connectionString = "URI=file:" + _filePath;
dbcon = new SqliteConnection(_connectionString);
dbcon.Open();
}
Please suggest any idea for reading data from tables, if db file is present in one of the drive in a system instead of a present in "application persistance" path.

It can RecorderJs processing a record of a file without emit any sound in speakers meanwhile?

While reading some about RecorderJs I ask myself if is possible record a sound without emit any sound in the speakers, all in a background, somebody knows if that is possible? because I don't see something similar in the Recorderjs Repository.
If you really want to use recorder.js, I guess there is a way to feed it directly with a MediaStream, that you'll get from the streamNode.stream.
Reading quickly the source code of this lib, it seems it only accepts AudioContext Source Nodes, not directly streams, and anyway, you just have to comment the line 38 of recorder.js file.
this.node.connect(this.context.destination); //this should not be necessary
comment from the author
And indeed it is.
Otherwise, you can also achieve it vanilla style (except that it will save as ogg instead of wav), by using the official MediaRecorder API, available in latests browsers.
The main key is the MediaStreamDestination which doesn't need to be connected to the AudioContext's destination.
var audio = new Audio();
audio.crossOrigin = 'anonymous';
audio.src = 'https://dl.dropboxusercontent.com/s/agepbh2agnduknz/camera.mp3';
audio.onloadedmetadata = startRecording;
var aCtx = new AudioContext();
var sourceNode = aCtx.createMediaElementSource(audio);
var streamNode = aCtx.createMediaStreamDestination();
sourceNode.connect(streamNode);
function startRecording() {
var recorder = new MediaRecorder(streamNode.stream),
chunks = [];
recorder.ondataavailable = function(e) {
chunks.push(e.data);
}
recorder.onstop = function() {
var blob = new Blob(chunks);
var url = URL.createObjectURL(blob);
var a = new Audio(url);
a.controls = true;
document.body.appendChild(a);
}
audio.onended = function() {
recorder.stop();
};
audio.play();
recorder.start();
}

How to upload an image from a tablet running Windows 8.1 metro application?

I need to upload an image to a server, less then 20 lines of code please. and no questions about services. My boss expects it to work like ftp of old days...
I don't think there is a 20 lines solution to your problem.
But check this link out :
http://code.msdn.microsoft.com/Windows-8-SocketsFtp-4fc23b33#content
It contains a full Ftp client that works on Windows 8.1 metro application.
You could use this project as a library in your own project.
If you especially need to upload file, I think you need to use the UploadFileAsync function in FtpClient class
public async Task UploadFileAsync(StorageFile file, string destination)
{
using (var stream = await OpenWriteAsync(destination))
{
//
// A more efficient way, maybe a DataReader can be used here
using (var readStream = await file.OpenReadAsync())
{
var buffer = new byte[512].AsBuffer();
var resultingBuffer = new byte[0];
while (true)
{
IBuffer readBuffer = await readStream.ReadAsync(buffer, 512, InputStreamOptions.Partial);
if (readBuffer.Length == 0) break;
resultingBuffer = resultingBuffer.Concat(readBuffer.ToArray()).ToArray();
}
await stream.WriteAsync(resultingBuffer.AsBuffer());
await stream.FlushAsync();
}
}
}

ADO.NET Data Services - Uploading files

I am trying to write REST web service through which our clients can upload a file on our file server. IS there an example or any useful links which I can refer for any guidance?
I haven't seen many examples of POST operation using ADO.NET data services available.
I've uploaded a file to ADO.NET dataservices using POST although I'm not sure whether it's the recommended approach. The way I went about it is:
On the dataservice I've implemented a service operation called UploadFile (using the WebInvoke attribute so that it caters for POST calls):
[WebInvoke]
public void UploadFile()
{
var request = HttpContext.Current.Request;
for (int i = 0; i < request.Files.Count; i++)
{
var file = request.Files[i];
var inputValues = new byte[file.ContentLength];
using (var requestStream = file.InputStream)
{
requestStream.Read(inputValues, 0, file.ContentLength);
}
File.WriteAllBytes(#"c:\temp\" + file.FileName, inputValues);
}
}
Then on the client side I call the data service using:
var urlString = "http://localhost/TestDataServicePost/CustomDataService.svc/UploadFile";
var webClient = new WebClient();
webClient.UploadFile(urlString, "POST", #"C:\temp\test.txt");
This uses a WebClient to upload the file which places the file data in the HttpRequest.Files collection and sets the content type. If you would prefer to send the contents of the file yourself (eg from an Asp FileUpload control) rather than the webClient reading a file using a path to the file, you can use a WebRequest similar to the way that it's done in this post. Although instead of using
FileStream fileStream = new FileStream(uploadfile,
FileMode.Open, FileAccess.Read);
you could use a byte array that you pass in.
I hope this helps.
I'm not 100% sure how to do this directly to a file server per se, but ADO.Net Data Services definitely support something similar to a database. The code below is how a similar goal of putting a file into a database has been accomplished. Not sure how much that will help, but
var myDocumentRepositoryUri = new Uri("uri here");
var dataContext = new FileRepositoryEntities(myDocumentRepositoryUri);
var myFile = new FileItem();
myfile.Filename = "upload.dat";
myFile.Data = new byte[1000]; // or put whatever file data you want to here
dataContext.AddToFileItem(myFile);
dataContext.SaveChanges();
Note: this code is also using Entity Framework to create a FileItem (representation of a database table as an object) and to save that data.