diff --git a/internal/r2/r2.go b/internal/r2/r2.go index 0437864..cd2ffa9 100644 --- a/internal/r2/r2.go +++ b/internal/r2/r2.go @@ -1,6 +1,7 @@ package r2 import ( + "bytes" "context" "fmt" "io" @@ -48,11 +49,19 @@ func (c *Client) Upload(ctx context.Context, key, contentType string, size int64 } func (c *Client) uploadSimple(ctx context.Context, key, contentType string, body io.Reader) error { - _, err := c.s3.PutObject(ctx, &s3.PutObjectInput{ - Bucket: &c.bucket, - Key: &key, - Body: body, - ContentType: &contentType, + // R2 requires Content-Length; buffer the body so we can set it. + // Only used for files < 100MB, so memory usage is bounded. + data, err := io.ReadAll(body) + if err != nil { + return fmt.Errorf("read body: %w", err) + } + size := int64(len(data)) + _, err = c.s3.PutObject(ctx, &s3.PutObjectInput{ + Bucket: &c.bucket, + Key: &key, + Body: bytes.NewReader(data), + ContentType: &contentType, + ContentLength: &size, }) return err } @@ -78,12 +87,16 @@ func (c *Client) uploadMultipart(ctx context.Context, key, contentType string, b break } + partData := make([]byte, n) + copy(partData, buf[:n]) + partLen := int64(n) upload, err := c.s3.UploadPart(ctx, &s3.UploadPartInput{ - Bucket: &c.bucket, - Key: &key, - UploadId: uploadID, - PartNumber: &partNum, - Body: io.NopCloser(io.LimitReader(bytesReader(buf[:n]), int64(n))), + Bucket: &c.bucket, + Key: &key, + UploadId: uploadID, + PartNumber: &partNum, + Body: bytes.NewReader(partData), + ContentLength: &partLen, }) if err != nil { c.s3.AbortMultipartUpload(ctx, &s3.AbortMultipartUploadInput{ @@ -147,24 +160,3 @@ func (c *Client) Delete(ctx context.Context, key string) error { return err } -// bytesReader wraps a byte slice as an io.Reader. -type bytesReaderImpl struct { - data []byte - pos int -} - -func bytesReader(b []byte) io.Reader { - // Make a copy so the buffer can be reused - cp := make([]byte, len(b)) - copy(cp, b) - return &bytesReaderImpl{data: cp} -} - -func (r *bytesReaderImpl) Read(p []byte) (int, error) { - if r.pos >= len(r.data) { - return 0, io.EOF - } - n := copy(p, r.data[r.pos:]) - r.pos += n - return n, nil -} diff --git a/web/index.html b/web/index.html index 70fdb0a..589c544 100644 --- a/web/index.html +++ b/web/index.html @@ -28,7 +28,7 @@
/f/ - +