|
| 1 | +using System.Net.Http; |
| 2 | +using System.Net.Http.Headers; |
| 3 | + |
| 4 | +namespace Replicate; |
| 5 | + |
| 6 | +public partial class ReplicateApi |
| 7 | +{ |
| 8 | +#pragma warning disable CA1822 // Partial methods cannot be static |
| 9 | +#pragma warning disable CA2000 // Content parts are owned by MultipartFormDataContent |
| 10 | + partial void PrepareFilesCreateRequest( |
| 11 | + HttpClient httpClient, |
| 12 | + HttpRequestMessage httpRequestMessage, |
| 13 | + FilesCreateRequest request) |
| 14 | + { |
| 15 | + // Rebuild the multipart content to work around .NET 6+ Content-Disposition |
| 16 | + // formatting changes. Modern .NET no longer quotes name/filename values |
| 17 | + // (e.g. name=content instead of name="content"), but Replicate's API |
| 18 | + // requires quoted values and returns HTTP 500 without them. |
| 19 | + // Also removes the filename* (RFC 5987) extended parameter which |
| 20 | + // Replicate does not support. |
| 21 | + |
| 22 | + var fileName = request.Contentname ?? request.Filename ?? "upload"; |
| 23 | + var contentType = request.Type ?? "application/octet-stream"; |
| 24 | + |
| 25 | + var boundary = Guid.NewGuid().ToString("N"); |
| 26 | + var multipart = new MultipartFormDataContent(boundary); |
| 27 | + |
| 28 | + // Ensure boundary is not quoted in the Content-Type header |
| 29 | + multipart.Headers.Remove("Content-Type"); |
| 30 | + multipart.Headers.TryAddWithoutValidation("Content-Type", |
| 31 | + $"multipart/form-data; boundary={boundary}"); |
| 32 | + |
| 33 | + var fileContent = new ByteArrayContent(request.Content ?? []); |
| 34 | + fileContent.Headers.ContentType = new MediaTypeHeaderValue(contentType); |
| 35 | + fileContent.Headers.ContentDisposition = new ContentDispositionHeaderValue("form-data") |
| 36 | + { |
| 37 | + Name = $"\"{EscapeQuotes("content")}\"", |
| 38 | + FileName = $"\"{EscapeQuotes(fileName)}\"", |
| 39 | + }; |
| 40 | + multipart.Add(fileContent); |
| 41 | + |
| 42 | + if (request.Metadata != null) |
| 43 | + { |
| 44 | + var metadataContent = new StringContent($"{request.Metadata}"); |
| 45 | + metadataContent.Headers.ContentDisposition = new ContentDispositionHeaderValue("form-data") |
| 46 | + { |
| 47 | + Name = "\"metadata\"", |
| 48 | + }; |
| 49 | + metadataContent.Headers.ContentType = new MediaTypeHeaderValue("application/json"); |
| 50 | + multipart.Add(metadataContent); |
| 51 | + } |
| 52 | + |
| 53 | + httpRequestMessage.Content = multipart; |
| 54 | + } |
| 55 | + |
| 56 | +#pragma warning disable CA1307 // Ordinal is implied for char/string Replace |
| 57 | + private static string EscapeQuotes(string value) => |
| 58 | + value.Replace("\\", "\\\\").Replace("\"", "\\\""); |
| 59 | +} |
0 commit comments