Я попытался создать API для загрузки и получения изображений с помощью NestJS. Изображения должны храниться на S3.
Что у меня сейчас есть:
Контроллер
@Post()
@UseInterceptors(FileFieldsInterceptor([
{name: 'photos', maxCount: 10},
]))
async uploadPhoto(@UploadedFiles() files): Promise<void> {
await this.s3Service.savePhotos(files.photos)
}
@Get('/:id')
@Header('content-type', 'image/jpeg')
async getPhoto(@Param() params,
@Res() res) {
const photoId = PhotoId.of(params.id)
const photoObject = await this.s3Service.getPhoto(photoId)
res.send(photoObject)
}
S3Service
async savePhotos(photos: FileUploadEntity[]): Promise<any> {
return Promise.all(photos.map(photo => {
const filePath = `${moment().format('YYYYMMDD-hhmmss')}${Math.floor(Math.random() * (1000))}.jpg`
const params = {
Body: photo.buffer,
Bucket: Constants.BUCKET_NAME,
Key: filePath,
}
return new Promise((resolve) => {
this.client.putObject(params, (err: any, data: any) => {
if (err) {
logger.error(`Photo upload failed [err=${err}]`)
ExceptionHelper.throw(ErrorCodes.SERVER_ERROR_UNCAUGHT_EXCEPTION)
}
logger.info(`Photo upload succeeded [filePath=${filePath}]`)
return resolve()
})
})
}))
}
async getPhoto(photoId: PhotoId): Promise<AWS.S3.Body> {
const object: S3.GetObjectOutput = await this.getObject(S3FileKey.of(`${Constants.S3_PHOTO_PATH}/${photoId.value}`))
.catch(() => ExceptionHelper.throw(ErrorCodes.RESOURCE_NOT_FOUND_PHOTO)) as S3.GetObjectOutput
logger.info(JSON.stringify(object.Body))
return object.Body
}
async getObject(s3FilePath: S3FileKey): Promise<S3.GetObjectOutput> {
logger.info(`Retrieving object from S3 s3FilePath=${s3FilePath.value}]`)
return this.client.getObject({
Bucket: Constants.BUCKET_NAME,
Key: s3FilePath.value
}).promise()
.catch(err => {
logger.error(`Could not retrieve object from S3 [err=${err}]`)
ExceptionHelper.throw(ErrorCodes.SERVER_ERROR_UNCAUGHT_EXCEPTION)
}) as S3.GetObjectOutput
}
Фотообъект фактически попадает в S3, но когда я его загружаю, я не могу его открыть. То же самое для GET => не может быть отображено.
Какую общую ошибку (-ы) я делаю здесь?
Не уверен, какие значения вы возвращаете своему потребителю и какие значения они используют, чтобы снова получить изображение; Не могли бы вы опубликовать, как выглядит фактический ответ, каков запрос и проверьте, совпадают ли полное доменное имя и путь? Похоже, вы тоже забыли про ACL, т.е. ресурсы, которые вы загружаете таким образом, по умолчанию не
public-read
.Кстати, вы можете использовать
aws SDK
там:спасибо за Ваш ответ. Мои проблемы связаны с тем, что я не включил поддержку двоичного кода для своего шлюза API. Загрузки теперь работают и правильно сохраняются в s3. ПОЛУЧИТЬ все еще не работает — person tpschmidt; 04.10.2019
не требуется
Я хочу получить файлы только с помощью лямбда-функции — person tpschmidt; 09.10.2019
Для тех, у кого такие же проблемы, я наконец понял это:
Я включил двоичную поддержку на API Gateway (
<your-gateway>
Settings
->Binary Media Types
->*/*
), а затем вернул все ответы из лямбда-кодировки base64. API Gateway выполнит декодирование автоматически перед возвратом ответа клиенту. С помощью serverless express вы можете легко включить автоматическое кодирование base64 при создании сервера:Теперь в контроллере вы можете просто вернуть тело ответа S3:
Надеюсь, это кому-то поможет!