public static LegacyAttachmentDetails GenerateLegacyAttachmentDetails( DocumentsOperationContext context, Stream decodedStream, string key, BlittableJsonReaderObject metadata, ref DocumentItem.AttachmentStream attachment) { var stream = attachment.Stream; var hash = AsyncHelpers.RunSync(() => AttachmentsStorageHelper.CopyStreamToFileAndCalculateHash(context, decodedStream, stream, CancellationToken.None)); attachment.Stream.Flush(); var lazyHash = context.GetLazyString(hash); attachment.Base64HashDispose = Slice.External(context.Allocator, lazyHash, out attachment.Base64Hash); var tag = $"{DummyDocumentPrefix}{key}{RecordSeparator}d{RecordSeparator}{key}{RecordSeparator}{hash}{RecordSeparator}"; var lazyTag = context.GetLazyString(tag); attachment.TagDispose = Slice.External(context.Allocator, lazyTag, out attachment.Tag); var id = GetLegacyAttachmentId(key); var lazyId = context.GetLazyString(id); attachment.Data = context.ReadObject(metadata, id); return(new LegacyAttachmentDetails { Id = lazyId, Hash = hash, Key = key, Size = attachment.Stream.Length, Tag = tag, Metadata = attachment.Data }); }
private async Task <BatchHandler.MergedBatchCommand.AttachmentStream> WriteAttachment(long size, Stream stream) { var attachmentStream = new BatchHandler.MergedBatchCommand.AttachmentStream(); if (size <= 32 * 1024) { attachmentStream.Stream = new MemoryStream(); } else { StreamsTempFile attachmentStreamsTempFile = Database.DocumentsStorage.AttachmentsStorage.GetTempFile("bulk"); attachmentStream.Stream = attachmentStreamsTempFile.StartNewStream(); if (_streamsTempFiles == null) { _streamsTempFiles = new List <StreamsTempFile>(); } _streamsTempFiles.Add(attachmentStreamsTempFile); } using (Database.DocumentsStorage.ContextPool.AllocateOperationContext(out DocumentsOperationContext ctx)) using (ctx.OpenWriteTransaction()) { attachmentStream.Hash = await AttachmentsStorageHelper.CopyStreamToFileAndCalculateHash(ctx, stream, attachmentStream.Stream, Database.DatabaseShutdown); await attachmentStream.Stream.FlushAsync(); } return(attachmentStream); }
public async Task InsertDocument(BlittableJsonReaderObject document, string id, Dictionary <string, byte[]> attachments) { _commands.Add(new BatchRequestParser.CommandData { Type = CommandType.PUT, Document = document, Id = id }); foreach (var attachment in attachments) { var memoryStream = new MemoryStream(attachment.Value); var stream = _command.AttachmentStreamsTempFile.StartNewStream(); _toDispose.Add(memoryStream); _toDispose.Add(stream); var attachmentStream = new BatchHandler.MergedBatchCommand.AttachmentStream { Stream = stream, Hash = await AttachmentsStorageHelper.CopyStreamToFileAndCalculateHash(_context, memoryStream, stream, _context.DocumentDatabase.DatabaseShutdown) //TODO: do we need it? }; await stream.FlushAsync(); _attachmentStreams.Add(attachmentStream); _commands.Add(new BatchRequestParser.CommandData { Type = CommandType.AttachmentPUT, Id = id, ContentType = "", Name = attachment.Key }); } if (_commands.Count >= _batchSize) { await FlushCommands(); } }
private async Task ParseMultipart(DocumentsOperationContext context, MergedBatchCommand command) { var boundary = MultipartRequestHelper.GetBoundary( MediaTypeHeaderValue.Parse(HttpContext.Request.ContentType), MultipartRequestHelper.MultipartBoundaryLengthLimit); var reader = new MultipartReader(boundary, RequestBodyStream()); for (var i = 0; i < int.MaxValue; i++) { var section = await reader.ReadNextSectionAsync().ConfigureAwait(false); if (section == null) { break; } var bodyStream = GetBodyStream(section); if (i == 0) { command.ParsedCommands = await BatchRequestParser.BuildCommandsAsync(context, bodyStream, Database, ServerStore); continue; } if (command.AttachmentStreams == null) { command.AttachmentStreams = new Queue <MergedBatchCommand.AttachmentStream>(); command.AttachmentStreamsTempFile = Database.DocumentsStorage.AttachmentsStorage.GetTempFile("batch"); } var attachmentStream = new MergedBatchCommand.AttachmentStream { Stream = command.AttachmentStreamsTempFile.StartNewStream() }; attachmentStream.Hash = await AttachmentsStorageHelper.CopyStreamToFileAndCalculateHash(context, bodyStream, attachmentStream.Stream, Database.DatabaseShutdown); attachmentStream.Stream.Flush(); command.AttachmentStreams.Enqueue(attachmentStream); } }
public async Task Put() { using (ContextPool.AllocateOperationContext(out DocumentsOperationContext context)) { var id = GetQueryStringValueAndAssertIfSingleAndNotEmpty("id"); var name = GetQueryStringValueAndAssertIfSingleAndNotEmpty("name"); var contentType = GetStringQueryString("contentType", false) ?? ""; AttachmentDetails result; using (var streamsTempFile = Database.DocumentsStorage.AttachmentsStorage.GetTempFile("put")) using (var stream = streamsTempFile.StartNewStream()) { Stream requestBodyStream = RequestBodyStream(); string hash; try { hash = await AttachmentsStorageHelper.CopyStreamToFileAndCalculateHash(context, requestBodyStream, stream, Database.DatabaseShutdown); } catch (Exception) { try { // if we failed to read the entire request body stream, we might leave // data in the pipe still, this will cause us to read and discard the // rest of the attachment stream and return the actual error to the caller requestBodyStream.CopyTo(Stream.Null); } catch (Exception) { // we tried, but we can't clean the request, so let's just kill // the connection HttpContext.Abort(); } throw; } var changeVector = context.GetLazyString(GetStringFromHeaders("If-Match")); var cmd = new MergedPutAttachmentCommand { Database = Database, ExpectedChangeVector = changeVector, DocumentId = id, Name = name, Stream = stream, Hash = hash, ContentType = contentType }; stream.Flush(); await Database.TxMerger.Enqueue(cmd); cmd.ExceptionDispatchInfo?.Throw(); result = cmd.Result; } HttpContext.Response.StatusCode = (int)HttpStatusCode.Created; using (var writer = new BlittableJsonTextWriter(context, ResponseBodyStream())) { writer.WriteStartObject(); writer.WritePropertyName(nameof(AttachmentDetails.ChangeVector)); writer.WriteString(result.ChangeVector); writer.WriteComma(); writer.WritePropertyName(nameof(AttachmentDetails.Name)); writer.WriteString(result.Name); writer.WriteComma(); writer.WritePropertyName(nameof(AttachmentDetails.DocumentId)); writer.WriteString(result.DocumentId); writer.WriteComma(); writer.WritePropertyName(nameof(AttachmentDetails.ContentType)); writer.WriteString(result.ContentType); writer.WriteComma(); writer.WritePropertyName(nameof(AttachmentDetails.Hash)); writer.WriteString(result.Hash); writer.WriteComma(); writer.WritePropertyName(nameof(AttachmentDetails.Size)); writer.WriteInteger(result.Size); writer.WriteEndObject(); } } }
public async Task Put() { using (ContextPool.AllocateOperationContext(out DocumentsOperationContext context)) { var id = GetQueryStringValueAndAssertIfSingleAndNotEmpty("id"); var name = GetQueryStringValueAndAssertIfSingleAndNotEmpty("name"); var contentType = GetStringQueryString("contentType", false) ?? ""; AttachmentDetails result; using (var streamsTempFile = Database.DocumentsStorage.AttachmentsStorage.GetTempFile("put")) using (var stream = streamsTempFile.StartNewStream()) { var hash = await AttachmentsStorageHelper.CopyStreamToFileAndCalculateHash(context, RequestBodyStream(), stream, Database.DatabaseShutdown); var changeVector = context.GetLazyString(GetStringQueryString("If-Match", false)); var cmd = new MergedPutAttachmentCommand { Database = Database, ExpectedChangeVector = changeVector, DocumentId = id, Name = name, Stream = stream, Hash = hash, ContentType = contentType }; await Database.TxMerger.Enqueue(cmd); cmd.ExceptionDispatchInfo?.Throw(); result = cmd.Result; } HttpContext.Response.StatusCode = (int)HttpStatusCode.Created; using (var writer = new BlittableJsonTextWriter(context, ResponseBodyStream())) { writer.WriteStartObject(); writer.WritePropertyName(nameof(AttachmentDetails.ChangeVector)); writer.WriteString(result.ChangeVector); writer.WriteComma(); writer.WritePropertyName(nameof(AttachmentDetails.Name)); writer.WriteString(result.Name); writer.WriteComma(); writer.WritePropertyName(nameof(AttachmentDetails.DocumentId)); writer.WriteString(result.DocumentId); writer.WriteComma(); writer.WritePropertyName(nameof(AttachmentDetails.ContentType)); writer.WriteString(result.ContentType); writer.WriteComma(); writer.WritePropertyName(nameof(AttachmentDetails.Hash)); writer.WriteString(result.Hash); writer.WriteComma(); writer.WritePropertyName(nameof(AttachmentDetails.Size)); writer.WriteInteger(result.Size); writer.WriteEndObject(); } } }