2011-02-14 69 views
60

Estoy desarrollando una aplicación web con mongodb como mi back-end. Me gustaría que los usuarios suban imágenes a sus perfiles como una foto de perfil enlazado. Estoy usando una página aspx con MVC2 y he leído que la biblioteca GridFs se usa para almacenar grandes tipos de archivos como binarios. He buscado pistas en todas partes sobre cómo se hace esto, pero mongodb no tiene ninguna documentación para C# api o GridFs C#. Estoy desconcertado y confundido, realmente podría usar otro conjunto de cerebros.MongoDB GridFs con C#, ¿cómo almacenar archivos como imágenes?

¿Alguien sabe cómo implementar un controlador de carga de archivos que almacena una imagen cargada por un usuario en una colección de mongodb? ¡Un millón de gracias!

He intentado variaciones de esto en vano.

Database db = mongo.getDB("Blog"); 
GridFile file = new GridFile(db); 
file.Create("image.jpg"); 

var images = db.GetCollection("images"); 
images.Insert(file.ToDocument()); 
+0

https: // stackoverflow.com/questions/45535296/how-to-create-a-cdn-server-in-dotnet-core-using-mongodb-gridfs-and-angularjs?noredirect=1#comment78034138_45535296 –

Respuesta

84

Siguiendo el ejemplo muestran cómo guardar archivos y leído desde GridFS (usando piloto oficial mongodb):

var server = MongoServer.Create("mongodb://localhost:27020"); 
var database = server.GetDatabase("tesdb"); 

var fileName = "D:\\Untitled.png"; 
var newFileName = "D:\\new_Untitled.png"; 
using (var fs = new FileStream(fileName, FileMode.Open)) 
{ 
    var gridFsInfo = database.GridFS.Upload(fs, fileName); 
    var fileId = gridFsInfo.Id; 

    ObjectId oid= new ObjectId(fileId); 
    var file = database.GridFS.FindOne(Query.EQ("_id", oid)); 

    using (var stream = file.OpenRead()) 
    { 
     var bytes = new byte[stream.Length]; 
     stream.Read(bytes, 0, (int)stream.Length); 
     using(var newFs = new FileStream(newFileName, FileMode.Create)) 
     { 
     newFs.Write(bytes, 0, bytes.Length); 
     } 
    } 
} 

Resultados:

del archivo:

File im mongodb

Trozos colección:

Chunks collection

Esperanza esta ayuda.

+1

Andrew, ¿Qué utilizas para ver? ¿el resultado? ¿De qué programa son las capturas de pantalla? Parece un administrador lite sql mucho. – Goff

+8

@Goff: es mongovue -> http://www.mongovue.com/. –

+0

Andrew, una pregunta, ya que MongoDb divide archivos grandes en trozos más pequeños para su almacenamiento, ¿puede usarse para almacenamiento parcial y reanudarlos más tarde? Digamos que alguien está escribiendo una aplicación de escritorio en la nube de respaldo en MongoDB, donde los archivos se respaldan automáticamente. Ahora supongamos que se está copiando un archivo PDF, cuando el 70% del archivo ha completado la copia de seguridad (estoy hablando en el lenguaje de la copia de archivos en el SO, digamos cuando copiamos un archivo de una unidad a otra en Windows, el '60 % done 'tipo de mensaje), el usuario se desconecta. Cuando se vuelve a conectar, ¿se puede usar la información del 70% para reanudar la copia de seguridad desde donde se quedó? – SexyBeast

17

Este ejemplo le permitirá atar un documento a un objeto

using System; 
using System.Collections.Generic; 
using System.Linq; 
using System.Text; 
using MongoDB.Driver; 
using MongoDB.Driver.Linq; 
using MongoDB.Bson; 
using MongoDB.Driver.Builders; 
using MongoDB.Driver.GridFS; 
using System.IO; 

namespace ConsoleApplication1 
{ 
class Program 
{ 
    static void Main(string[] args) 
    { 
     MongoServer ms = MongoServer.Create(); 
     string _dbName = "docs"; 

     MongoDatabase md = ms.GetDatabase(_dbName); 
     if (!md.CollectionExists(_dbName)) 
     { 
      md.CreateCollection(_dbName); 
     } 

     MongoCollection<Doc> _documents = md.GetCollection<Doc>(_dbName); 
     _documents.RemoveAll(); 
     //add file to GridFS 

     MongoGridFS gfs = new MongoGridFS(md); 
     MongoGridFSFileInfo gfsi = gfs.Upload(@"c:\mongodb.rtf"); 
     _documents.Insert(new Doc() 
     { 
      DocId = gfsi.Id.AsObjectId, 
      DocName = @"c:\foo.rtf" 
     } 
     ); 

     foreach (Doc item in _documents.FindAll()) 
     { 
      ObjectId _documentid = new ObjectId(item.DocId.ToString()); 
      MongoGridFSFileInfo _fileInfo = md.GridFS.FindOne(Query.EQ("_id", _documentid)); 
      gfs.Download(item.DocName, _fileInfo); 
      Console.WriteLine("Downloaded {0}", item.DocName); 
      Console.WriteLine("DocName {0} dowloaded", item.DocName); 
     } 

     Console.ReadKey(); 
    } 
} 

class Doc 
{ 
    public ObjectId Id { get; set; } 
    public string DocName { get; set; } 
    public ObjectId DocId { get; set; } 
} 
14

Las respuestas anteriores son pronto a ser obsoletos ahora que el 2,1-RC 0 conductor ha sido puesto en libertad.

La manera de trabajar con archivos en MongoDB v2.1 con GridFS ahora se puede hacer de esta manera:

using MongoDB.Bson; 
using MongoDB.Driver; 
using MongoDB.Driver.GridFS; 
using System.IO; 
using System.Threading.Tasks; 

namespace MongoGridFSTest 
{ 
    class Program 
    { 
     static void Main(string[] args) 
     { 
      var client = new MongoClient("mongodb://localhost"); 
      var database = client.GetDatabase("TestDB"); 
      var fs = new GridFSBucket(database); 

      var id = UploadFile(fs); 

      DownloadFile(fs, id); 
     } 

     private static ObjectId UploadFile(GridFSBucket fs) 
     { 
      using (var s = File.OpenRead(@"c:\temp\test.txt")) 
      { 
       var t = Task.Run<ObjectId>(() => { return 
        fs.UploadFromStreamAsync("test.txt", s); 
       }); 

       return t.Result; 
      } 
     } 

     private static void DownloadFile(GridFSBucket fs, ObjectId id) 
     { 
      //This works 
      var t = fs.DownloadAsBytesByNameAsync("test.txt"); 
      Task.WaitAll(t); 
      var bytes = t.Result; 


      //This blows chunks (I think it's a driver bug, I'm using 2.1 RC-0) 
      var x = fs.DownloadAsBytesAsync(id); 
      Task.WaitAll(x); 
     } 
    } 
} 

Esto está tomado de un diff en las pruebas del controlador C# here

+0

No probé el código. ¿Funciona? Dijiste que explotó pedazos –

+0

Buena pregunta. Para aclarar, la primera llamada, DownloadAsBytesByNameAsync, funciona bien. La segunda llamada falla. Pero hubo una edición sugerida que mostró que para que DownloadAsBytesAsync funcione, el argumento Nitlable CancellationToken debe ser incluido y no nulo. – Josh

+0

Thx para la respuesta. ¿Hay métodos sincrónicos para descargar archivos? –

Cuestiones relacionadas