// constructors public GridFSForwardOnlyDownloadStream( GridFSBucket <TFileId> bucket, IReadBinding binding, GridFSFileInfo <TFileId> fileInfo, bool checkMD5) : base(bucket, binding, fileInfo) { _checkMD5 = checkMD5; if (_checkMD5) { _md5 = IncrementalMD5.Create(); } _lastChunkNumber = (int)((fileInfo.Length - 1) / fileInfo.ChunkSizeBytes); _lastChunkSize = (int)(fileInfo.Length % fileInfo.ChunkSizeBytes); if (_lastChunkSize == 0) { _lastChunkSize = fileInfo.ChunkSizeBytes; } var idSerializer = bucket.Options.SerializerRegistry.GetSerializer <TFileId>(); var idSerializationInfo = new BsonSerializationInfo("_id", idSerializer, typeof(TFileId)); _idAsBsonValue = idSerializationInfo.SerializeValue(fileInfo.Id); }
// constructors public GridFSForwardOnlyUploadStream( GridFSBucket <TFileId> bucket, IWriteBinding binding, TFileId id, string filename, BsonDocument metadata, IEnumerable <string> aliases, string contentType, int chunkSizeBytes, int batchSize) { _bucket = bucket; _binding = binding; _id = id; _filename = filename; _metadata = metadata; // can be null _aliases = aliases == null ? null : aliases.ToList(); // can be null _contentType = contentType; // can be null _chunkSizeBytes = chunkSizeBytes; _batchSize = batchSize; _batch = new List <byte[]>(); _md5 = IncrementalMD5.Create(); var idSerializer = bucket.Options.SerializerRegistry.GetSerializer <TFileId>(); var idSerializationInfo = new BsonSerializationInfo("_id", idSerializer, typeof(TFileId)); _idAsBsonValue = idSerializationInfo.SerializeValue(id); }
/// <summary> /// Downloads a GridFS file. /// </summary> /// <param name="stream">The destination stream.</param> /// <param name="fileInfo">The GridFS file.</param> public void Download(Stream stream, MongoGridFSFileInfo fileInfo) { using (_server.RequestStart(_settings.ReadPreference)) { var connectionId = _server.RequestConnectionId; if (_settings.VerifyMD5 && fileInfo.MD5 == null) { throw new MongoGridFSException(connectionId, "VerifyMD5 is true and file being downloaded has no MD5 hash."); } var database = GetDatabase(); var chunksCollection = GetChunksCollection(database); string md5Client = null; using (var md5Algorithm = _settings.VerifyMD5 ? IncrementalMD5.Create() : null) { var numberOfChunks = (fileInfo.Length + fileInfo.ChunkSize - 1) / fileInfo.ChunkSize; for (var n = 0L; n < numberOfChunks; n++) { var query = Query.And(Query.EQ("files_id", fileInfo.Id), Query.EQ("n", n)); var chunk = chunksCollection.FindOne(query); if (chunk == null) { string errorMessage = string.Format("Chunk {0} missing for GridFS file '{1}'.", n, fileInfo.Name); throw new MongoGridFSException(connectionId, errorMessage); } var data = chunk["data"].AsBsonBinaryData; if (data.Bytes.Length != fileInfo.ChunkSize) { // the last chunk only has as many bytes as needed to complete the file if (n < numberOfChunks - 1 || data.Bytes.Length != fileInfo.Length % fileInfo.ChunkSize) { string errorMessage = string.Format("Chunk {0} for GridFS file '{1}' is the wrong size.", n, fileInfo.Name); throw new MongoGridFSException(connectionId, errorMessage); } } stream.Write(data.Bytes, 0, data.Bytes.Length); if (_settings.VerifyMD5) { md5Algorithm.AppendData(data.Bytes, 0, data.Bytes.Length); } } if (_settings.VerifyMD5) { md5Client = BsonUtils.ToHexString(md5Algorithm.GetHashAndReset()); } } if (_settings.VerifyMD5 && !md5Client.Equals(fileInfo.MD5, StringComparison.OrdinalIgnoreCase)) { throw new MongoGridFSException(connectionId, "Download client and server MD5 hashes are not equal."); } } }
/// <summary> /// Uploads a GridFS file. /// </summary> /// <param name="stream">The source stream.</param> /// <param name="remoteFileName">The remote file name.</param> /// <param name="createOptions">The create options.</param> /// <returns>The file info of the new GridFS file.</returns> public MongoGridFSFileInfo Upload( Stream stream, string remoteFileName, MongoGridFSCreateOptions createOptions) { if (_settings.ReadPreference != ReadPreference.Primary) { var gridFS = WithReadPreferencePrimary(); return(gridFS.Upload(stream, remoteFileName, createOptions)); } using (_server.RequestStart(ReadPreference.Primary)) { var connectionId = _server.RequestConnectionId; EnsureIndexes(); var database = GetDatabase(ReadPreference.Primary); var chunksCollection = GetChunksCollection(database); var filesCollection = GetFilesCollection(database); var files_id = createOptions.Id ?? ObjectId.GenerateNewId(); var chunkSize = (createOptions.ChunkSize == 0) ? _settings.ChunkSize : createOptions.ChunkSize; var buffer = new byte[chunkSize]; var length = 0L; string md5Client = null; using (var md5Algorithm = _settings.VerifyMD5 ? IncrementalMD5.Create() : null) { for (var n = 0L; true; n++) { // might have to call Stream.Read several times to get a whole chunk var bytesNeeded = chunkSize; var bytesRead = 0; while (bytesNeeded > 0) { var partialRead = stream.Read(buffer, bytesRead, bytesNeeded); if (partialRead == 0) { break; // EOF may or may not have a partial chunk } bytesNeeded -= partialRead; bytesRead += partialRead; } if (bytesRead == 0) { break; // EOF no partial chunk } length += bytesRead; byte[] data = buffer; if (bytesRead < chunkSize) { data = new byte[bytesRead]; Buffer.BlockCopy(buffer, 0, data, 0, bytesRead); } var chunk = new BsonDocument { { "_id", ObjectId.GenerateNewId() }, { "files_id", files_id }, { "n", n < int.MaxValue ? (BsonValue)(BsonInt32)(int)n : (BsonInt64)n }, { "data", new BsonBinaryData(data) } }; chunksCollection.Insert(chunk, _settings.WriteConcern); if (_settings.VerifyMD5) { md5Algorithm.AppendData(data, 0, data.Length); } if (bytesRead < chunkSize) { break; // EOF after partial chunk } } if (_settings.VerifyMD5) { md5Client = BsonUtils.ToHexString(md5Algorithm.GetHashAndReset()); } } string md5Server = null; if (_settings.UpdateMD5 || _settings.VerifyMD5) { var md5Command = new CommandDocument { { "filemd5", files_id }, { "root", _settings.Root } }; var md5Result = database.RunCommand(md5Command); md5Server = md5Result.Response["md5"].AsString; } if (_settings.VerifyMD5 && !md5Client.Equals(md5Server, StringComparison.OrdinalIgnoreCase)) { throw new MongoGridFSException(connectionId, "Upload client and server MD5 hashes are not equal."); } var uploadDate = (createOptions.UploadDate == DateTime.MinValue) ? DateTime.UtcNow : createOptions.UploadDate; var aliases = (createOptions.Aliases != null) ? new BsonArray(createOptions.Aliases) : null; BsonDocument fileInfo = new BsonDocument { { "_id", files_id }, { "filename", remoteFileName, !string.IsNullOrEmpty(remoteFileName) }, // optional { "length", length }, { "chunkSize", chunkSize }, { "uploadDate", uploadDate }, { "md5", (md5Server == null) ? (BsonValue)BsonNull.Value : new BsonString(md5Server) }, { "contentType", createOptions.ContentType, !string.IsNullOrEmpty(createOptions.ContentType) }, // optional { "aliases", aliases, aliases != null }, // optional { "metadata", createOptions.Metadata, createOptions.Metadata != null } // optional }; filesCollection.Insert(fileInfo, _settings.WriteConcern); return(FindOneById(files_id)); } }