feat(upload): integrate upload service for chat image validation and S3 uploads
- Added UploadService to handle image uploads and validation for chat messages. - Updated ChatService and MessageService to utilize UploadService for validating image segments in messages. - Enhanced wire generation to inject UploadService into relevant services. - Introduced UploadImageBytes method in UploadService for uploading images directly from memory. - Added TrustedPublicURLPrefix method in S3 Client for generating public URLs for uploaded images.
This commit is contained in:
@@ -75,6 +75,41 @@ func (s *UploadService) UploadImage(ctx context.Context, file *multipart.FileHea
|
||||
return url, previewURL, previewURLLarge, nil
|
||||
}
|
||||
|
||||
const maxUploadImageBytesFromBuffer = 15 << 20 // 与聊天内联解码上限一致,略大于 upload.max_file_size 时可接受
|
||||
|
||||
// UploadImageBytes 从内存字节上传图片(与 multipart 上传走同一套压缩与存储逻辑)。
|
||||
func (s *UploadService) UploadImageBytes(ctx context.Context, raw []byte, filename string) (url, previewURL, previewURLLarge string, err error) {
|
||||
if len(raw) == 0 {
|
||||
return "", "", "", fmt.Errorf("empty image data")
|
||||
}
|
||||
if len(raw) > maxUploadImageBytesFromBuffer {
|
||||
return "", "", "", fmt.Errorf("image data too large")
|
||||
}
|
||||
|
||||
detectedType := normalizeImageContentType(http.DetectContentType(raw))
|
||||
compressedData, compressedType, cerr := compressImageData(raw, detectedType)
|
||||
if cerr != nil {
|
||||
compressedData = raw
|
||||
compressedType = detectedType
|
||||
}
|
||||
compressedType = cmp.Or(compressedType, http.DetectContentType(compressedData))
|
||||
ext := cmp.Or(getExtFromContentType(compressedType), strings.ToLower(filepath.Ext(filename)), ".jpg")
|
||||
|
||||
hash := sha256.Sum256(compressedData)
|
||||
hashStr := fmt.Sprintf("%x", hash)
|
||||
objectName := fmt.Sprintf("images/%s%s", hashStr, ext)
|
||||
url, err = s.s3Client.UploadData(ctx, objectName, compressedData, compressedType)
|
||||
if err != nil {
|
||||
return "", "", "", fmt.Errorf("failed to upload to S3: %w", err)
|
||||
}
|
||||
|
||||
previewURL, previewURLLarge, prevErr := s.GeneratePreviewImages(ctx, compressedData, hashStr)
|
||||
if prevErr != nil {
|
||||
zap.L().Warn("UploadImageBytes: preview generation failed", zap.Error(prevErr))
|
||||
}
|
||||
return url, previewURL, previewURLLarge, nil
|
||||
}
|
||||
|
||||
// getExtFromContentType 根据Content-Type获取文件扩展名
|
||||
func getExtFromContentType(contentType string) string {
|
||||
baseType, _, err := mime.ParseMediaType(contentType)
|
||||
|
||||
Reference in New Issue
Block a user