fix file uploading

This commit is contained in:
Hongbo Wu
2023-09-06 14:59:34 +08:00
parent e05d341952
commit 1bade22076
9 changed files with 68 additions and 74 deletions

View File

@ -80,12 +80,12 @@ import { isSiteBlockedForParse } from '../../utils/blocked'
import {
authorized,
cleanUrl,
errorHandler,
generateSlug,
isBase64Image,
isParsingTimeout,
libraryItemToArticle,
libraryItemToSearchItem,
pageError,
titleForFilePath,
userDataToUser,
} from '../../utils/helpers'
@ -153,7 +153,7 @@ export const createArticleResolver = authorized<
const userData = await userRepository.findById(uid)
if (!userData) {
return pageError(
return errorHandler(
{
errorCodes: [CreateArticleErrorCode.Unauthorized],
},
@ -166,7 +166,7 @@ export const createArticleResolver = authorized<
try {
if (isSiteBlockedForParse(url)) {
return pageError(
return errorHandler(
{
errorCodes: [CreateArticleErrorCode.NotAllowedToParse],
},
@ -190,7 +190,6 @@ export const createArticleResolver = authorized<
let title: string | undefined
let parsedContent: Readability.ParseResult | null = null
let canonicalUrl
let userArticleUrl: string | null = null
let uploadFileHash = null
let domContent = null
let itemType = LibraryItemType.Unknown
@ -226,7 +225,7 @@ export const createArticleResolver = authorized<
*/
const uploadFile = await findUploadFileById(uploadFileId)
if (!uploadFile) {
return pageError(
return errorHandler(
{ errorCodes: [CreateArticleErrorCode.UploadFileMissing] },
uid,
articleSavingRequestId,
@ -238,7 +237,6 @@ export const createArticleResolver = authorized<
uploadFile.fileName
)
uploadFileHash = uploadFileDetails.md5Hash
userArticleUrl = uploadFileDetails.fileUrl
canonicalUrl = uploadFile.url
itemType = itemTypeForContentType(uploadFile.contentType)
title = titleForFilePath(uploadFile.url)
@ -282,7 +280,6 @@ export const createArticleResolver = authorized<
title,
parsedContent,
userId: uid,
itemId: articleSavingRequestId,
slug,
croppedPathname,
originalHtml: domContent,
@ -295,21 +292,15 @@ export const createArticleResolver = authorized<
log.info('New article saving', {
parsedArticle: Object.assign({}, libraryItemToSave, {
content: undefined,
originalHtml: undefined,
readableContent: undefined,
originalContent: undefined,
}),
userArticleUrl,
labels: {
source: 'resolver',
resolver: 'createArticleResolver',
userId: uid,
},
})
if (uploadFileId) {
const uploadFileData = await setFileUploadComplete(uploadFileId)
if (!uploadFileData || !uploadFileData.id || !uploadFileData.fileName) {
return pageError(
return errorHandler(
{
errorCodes: [CreateArticleErrorCode.UploadFileMissing],
},
@ -344,7 +335,7 @@ export const createArticleResolver = authorized<
pubsub
)
} else {
// create new page in elastic
// create new page in database
libraryItemToReturn = await createLibraryItem(
libraryItemToSave,
uid,
@ -353,7 +344,7 @@ export const createArticleResolver = authorized<
}
log.info(
'page created in elastic',
'item created in database',
libraryItemToReturn.id,
libraryItemToReturn.originalUrl,
libraryItemToReturn.slug,
@ -367,7 +358,7 @@ export const createArticleResolver = authorized<
}
} catch (error) {
log.error('Error creating article', error)
return pageError(
return errorHandler(
{
errorCodes: [CreateArticleErrorCode.ElasticError],
},
@ -399,6 +390,7 @@ export const getArticleResolver = authorized<
user: true,
labels: true,
},
uploadFile: true,
},
})
)

View File

@ -383,7 +383,7 @@ export const functionResolvers = {
}
return article.url
},
async originalArticleUrl(article: { url: string }) {
originalArticleUrl(article: { url: string }) {
return article.url
},
hasContent(article: {
@ -464,6 +464,9 @@ export const functionResolvers = {
image(item: SearchItem) {
return item.image && createImageProxyUrl(item.image, 320, 320)
},
originalArticleUrl(item: { url: string }) {
return item.url
},
},
Subscription: {
newsletterEmail(subscription: Subscription) {

View File

@ -20,6 +20,7 @@ import {
import { analytics } from '../../utils/analytics'
import { authorized, generateSlug } from '../../utils/helpers'
import {
contentReaderForLibraryItem,
generateUploadFilePathName,
generateUploadSignedUrl,
getFilePublicUrl,
@ -127,25 +128,21 @@ export const uploadFileRequestResolver = authorized<
// If we have a file:// URL, don't try to match it
// and create a copy of the page, just create a
// new item.
const item = isFileUrl(input.url)
? await findLibraryItemByUrl(input.url, uid)
: undefined
const item = await findLibraryItemByUrl(input.url, uid)
if (item) {
if (
!(await updateLibraryItem(
item.id,
{
savedAt: new Date(),
archivedAt: null,
},
uid
))
) {
return { errorCodes: [UploadFileRequestErrorCode.FailedCreate] }
}
await updateLibraryItem(
item.id,
{
savedAt: new Date(),
archivedAt: null,
state: LibraryItemState.Processing,
},
uid
)
createdItemId = item.id
} else {
const itemType = itemTypeForContentType(input.contentType)
const uploadFileId = uploadFileData.id
const item = await createLibraryItem(
{
originalUrl: isFileUrl(input.url) ? publicUrl : input.url,
@ -153,9 +150,11 @@ export const uploadFileRequestResolver = authorized<
user: { id: uid },
title,
readableContent: '',
itemType: itemTypeForContentType(input.contentType),
itemType,
uploadFile: { id: uploadFileData.id },
slug: generateSlug(uploadFilePathName),
state: LibraryItemState.Processing,
contentReader: contentReaderForLibraryItem(itemType, uploadFileId),
},
uid
)

View File

@ -81,7 +81,7 @@ export const createPageSaveRequest = async ({
userId,
url,
pubsub = createPubSubClient(),
articleSavingRequestId = uuidv4(),
articleSavingRequestId,
state,
priority,
labels,
@ -149,7 +149,7 @@ export const createPageSaveRequest = async ({
await enqueueParseRequest({
url,
userId,
saveRequestId: articleSavingRequestId,
saveRequestId: libraryItem.id,
priority,
state,
labels,

View File

@ -1,3 +1,4 @@
import { LibraryItemState } from '../entity/library_item'
import { User } from '../entity/user'
import { homePageURL } from '../env'
import {
@ -6,7 +7,6 @@ import {
SaveFileInput,
SaveResult,
} from '../generated/graphql'
import { logger } from '../utils/logger'
import { getStorageFileDetails } from '../utils/uploads'
import { findOrCreateLabels } from './labels'
import { updateLibraryItem } from './library_item'
@ -16,8 +16,6 @@ export const saveFile = async (
input: SaveFileInput,
user: User
): Promise<SaveResult> => {
logger.info('saving file with input', input)
const pageId = input.clientRequestId
const uploadFile = await findUploadFileById(input.uploadFileId)
if (!uploadFile) {
return {
@ -35,28 +33,25 @@ export const saveFile = async (
}
}
// save state
const archivedAt =
input.state === ArticleSavingRequestStatus.Archived ? new Date() : null
// add labels to page
const labels = input.labels
? await findOrCreateLabels(input.labels, user.id)
: undefined
if (input.state || input.labels) {
const updated = await updateLibraryItem(
pageId,
// save state
const archivedAt =
input.state === ArticleSavingRequestStatus.Archived ? new Date() : null
// add labels to page
const labels = input.labels
? await findOrCreateLabels(input.labels, user.id)
: undefined
await updateLibraryItem(
input.clientRequestId,
{
archivedAt,
labels,
state: input.state
? (input.state as unknown as LibraryItemState)
: LibraryItemState.Succeeded,
},
user.id
)
if (!updated) {
logger.info('error updating page', pageId)
return {
errorCodes: [SaveErrorCode.Unknown],
}
}
}
return {

View File

@ -28,6 +28,7 @@ import {
} from '../utils/helpers'
import { logger } from '../utils/logger'
import { parsePreparedContent } from '../utils/parser'
import { contentReaderForLibraryItem } from '../utils/uploads'
import { createPageSaveRequest } from './create_page_save_request'
import { createHighlight } from './highlights'
import { findOrCreateLabels } from './labels'
@ -258,5 +259,6 @@ export const parsedContentToLibraryItem = ({
itemLanguage: parsedContent?.language,
siteIcon: parsedContent?.siteIcon,
wordCount: wordsCount(parsedContent?.textContent || ''),
contentReader: contentReaderForLibraryItem(itemType, uploadFileId),
}
}

View File

@ -7,8 +7,12 @@ export const findUploadFileById = async (id: string) => {
export const setFileUploadComplete = async (id: string, userId?: string) => {
return authTrx(
async (tx) =>
tx.getRepository(UploadFile).save({ id, status: 'COMPLETED' }),
async (tx) => {
const repo = tx.getRepository(UploadFile)
await repo.update(id, { status: 'COMPLETED' })
return repo.findOneByOrFail({ id })
},
undefined,
userId
)

View File

@ -178,7 +178,7 @@ export const generateSlug = (title: string): string => {
export const MAX_CONTENT_LENGTH = 5e7 //50MB
export const pageError = async (
export const errorHandler = async (
result: CreateArticleError,
userId: string,
pageId?: string | null,
@ -242,6 +242,8 @@ export const libraryItemToArticle = (item: LibraryItem): Article => ({
readingProgressAnchorIndex: item.readingProgressHighestReadAnchor,
readingProgressPercent: item.readingProgressTopPercent,
highlights: item.highlights?.map(highlightDataToHighlight) || [],
uploadFileId: item.uploadFile?.id,
pageType: item.itemType as unknown as PageType,
})
export const libraryItemToSearchItem = (item: LibraryItem): SearchItem => ({
@ -260,6 +262,7 @@ export const libraryItemToSearchItem = (item: LibraryItem): SearchItem => ({
),
image: item.thumbnail,
highlights: item.highlights?.map(highlightDataToHighlight),
uploadFileId: item.uploadFile?.id,
})
export const isParsingTimeout = (libraryItem: LibraryItem): boolean => {

View File

@ -1,24 +1,24 @@
/* eslint-disable @typescript-eslint/no-unsafe-member-access */
/* eslint-disable @typescript-eslint/no-unsafe-assignment */
import { File, GetSignedUrlConfig, Storage } from '@google-cloud/storage'
import { ContentReaderType, LibraryItemType } from '../entity/library_item'
import { env } from '../env'
import { ContentReader, PageType } from '../generated/graphql'
import { logger } from './logger'
export const contentReaderForPage = (
pageType: PageType,
export const contentReaderForLibraryItem = (
itemType: LibraryItemType,
uploadFileId: string | null | undefined
) => {
if (!uploadFileId) {
return ContentReader.Web
return ContentReaderType.WEB
}
switch (pageType) {
case PageType.Book:
return ContentReader.Epub
case PageType.File:
return ContentReader.Pdf
switch (itemType) {
case LibraryItemType.Book:
return ContentReaderType.EPUB
case LibraryItemType.File:
return ContentReaderType.PDF
default:
return ContentReader.Web
return ContentReaderType.WEB
}
}
@ -47,10 +47,6 @@ export const generateUploadSignedUrl = async (
contentType: string,
selectedBucket?: string
): Promise<string> => {
// if (env.dev.isLocal) {
// return 'http://localhost:3000/uploads/' + filePathName
// }
// These options will allow temporary uploading of file with requested content type
const options: GetSignedUrlConfig = {
version: 'v4',