여러 파일을 드래그 앤 드롭하면 Uppy 업로더가 에러 발생

안녕하세요,
마지막 업데이트 이후(관리형 환경에서 사용 중) 업로드 기능이 깨진 것 같습니다. 특별한 작업을 하고 있지는 않습니다.

우리는 단순히 테마 컴포넌트 내에서 새로운 api.addComposerUploadHandler()를 등록할 뿐입니다.
이전에는 여러 파일을 컴포저에 드래그해도 잘 작동했습니다. 그런데 이제 콘솔에 Uppy와 관련된 것으로 보이는 오류가 발생합니다(우리는 Uppy를 원하지 않습니다).

우리의 코드는 정말 간단하지만, 여전히 Uppy가 간섭을 하는 것 같습니다.

// Register custom upload handler for videos.
	api.addComposerUploadHandler(["mp4", "mov", "mkv", "avi", "m4v"], (file, editor) => {
		console.log("Handling upload for", file.name);
	})

3개 파일(mkv, mov, mkv)을 컴포저에 드롭하면 “your file is larger than 4 MB”(파일 크기가 4MB를 초과합니다)라는 오류 메시지가 표시됩니다. 우리는 모든 파일을 Gdrive에 업로드하기 때문에 이 제한을 우회하고 싶었습니다.

Chrome 콘솔에는 다음과 같은 오류가 발생합니다:

크기가 50MB인 단일 파일을 드롭하면 “file too large error”(파일이 너무 큼 오류)가 발생하지 않고, 예상대로 파일이 정상적으로 처리됩니다. 따라서 이 오류는 여러 파일 중 하나가 4MB 파일 제한(이 제한이 어디에서 설정되는지 확실하지 않습니다)을 초과할 때 발생하는 것으로 보입니다.

도움 주시면 감사하겠습니다. 이는 Discourse 자체의 마지막 업데이트와 관련이 있는 것 같습니다.

@martin

안녕하세요 @Sören_Geier. 최근 이 영역에서 몇 가지 변경 사항이 있었지만, 저는 기존 컴포저의 업로드 핸들러와 동일한 동작을 유지하려고 노력했습니다. 사용 사례를 좀 더 명확히 파악하고 싶습니다. 제가 파악한 바로는, uppy가 아닌 버전의 컴포저도 api.addComposerUploadHandler를 통해 업로드할 때 한 번에 하나의 파일만 처리합니다:

https://github.com/discourse/discourse/blob/main/app/assets/javascripts/discourse/app/mixins/composer-upload.js#L215-L222

따라서 여러 파일을 드롭하면 일반적인 플로우가 실행되며, 이 토픽의 OP(원글)에서 언급된 경우처럼 일반적인 업로드 플로우의 파일 크기 제한에 부딪히는 것으로 보입니다.

한 번에 여러 파일을 드래그 앤 드롭했을 때 과거에는 어떤 일이 발생했거나, 어떤 동작을 기대하고 계신가요? 공개적으로 공유하기 꺼리신다면 Meta에서 개인 메시지로 보내주시면 Meta에서 개인 메시지로 보내주시면 도움이 될 것입니다. 그리고 저희가 호스팅을 제공하고 있는지 확인차 질문드립니다.

2개의 좋아요

@martin 님, 빠른 답변 감사합니다.

네, 저희는 Discourse를 호스팅하고 있습니다. 보통 파일을 컴포저에 드래그 앤 드롭하면 "Processing "과 같은 텍스트가 컴포저에 삽입됩니다. 또한 API.addComposerUploadHandler(["mp4", "mov", "mkv", "avi", "m4v"])를 사용하는 경우, 이는 Discourse가 파일을 커스텀 핸들러로 전달하기 전에 수행하는 동작입니다. 그러나 어느 시점부터 이 플레이스홀더 텍스트 삽입이 작동하지 않게 되었는데, 제 핸들러에 아래 코드를 직접 삽입했을 때부터였습니다:

composerController.model.appEvents.trigger("composer:insert-block", `[Processing: ${file.name}...]()`);

그다음으로 문제가 된 것은, 갑자기 “theme authorized extensions” 설정에서 해당 비디오 확장자가 사라지면서 제 핸들러가 실행되지 않게 된 것이었습니다. 다시 설정에 추가해야만 정상적으로 작동하기 시작했습니다.

이후에 앞서 설명드린 “다중 파일 드롭” 문제를 발견했습니다.

저희는 2개 이상의 파일을 드롭했을 때 에러 메시지가 뜨지 않도록 작동하도록 설정한 적이 있습니다. 이는 Discourse의 모든 검증 로직을 우회했기 때문에 올바른 방식이라고 느껴졌습니다.

관련 코드 스니펫은 다음과 같습니다:

여기서는 단순히 Discourse가 드롭된 파일들을 하나씩 전달해주기를 기대합니다.

// Register custom upload handler for videos.
	api.addComposerUploadHandler(["mp4", "mov", "mkv", "avi", "m4v"], (file, editor) => {
		console.log("Handling upload for", file.name);
		sendToGDrive(file, api);
	})

Discourse가 파일을 개별적으로 전달해주었기 때문에, 중간 매개 함수를 만들어 배열을 채우고 타임아웃이 지난 후 실제 업로더 함수를 실행하도록 했습니다. 즉, Discourse에서 전달받은 파일을 제 배열에 수집하는 방식입니다.

// Collect all dropped files in sequence - as reported by Discourse handler.
function sendToGDrive(file, api) {
	clearTimeout(uploaderStartTimeout);
	filesHolder.push(file)
	const composerController = api.container.lookup("controller:composer");
	composerController.model.appEvents.trigger("composer:insert-block", `[Processing: ${file.name}...]()`);

	uploaderStartTimeout = setTimeout(function () {
		initFileSend(api);
	}, 300);
}

그 다음 각 파일을 개별적으로 Gdrive로 업로드합니다.

// Handle every file individually.
async function initFileSend(api) {
	for (const file of filesHolder) {
		const content = await sendFileToGdrive(file, api, uploadFolderId);
	}
}

관찰된 문제점:

  • “다중 파일” 드롭 시에는 파일 크기 검증이 이루어지지만, 단일 파일 드롭 시에는 그렇지 않습니다
1개의 좋아요

이렇게 자세한 보고서와 관련 코드를 공유해 주셔서 감사합니다. 저는 이미 업로드 핸들러에 대해 비슷한 방향으로 생각하고 있었습니다. 각 파일이 해당 핸들러와 일치하도록 하고, 여기서 하신 것처럼 일종의 큐나 풀에 넣은 다음 한꺼번에 업로드하거나 다른 UI로 전달하는 방식이었죠. 왜냐하면 1개씩만 처리하는 제한이 다소 이상하게 느껴졌기 때문입니다. 다만, 말씀하시는 내용을 들어 보니 이전 컴포저 업로드 핸들러에서 1개씩 처리하는 제한이 어떻게 작동했는지를 제가 오해했을 수도 있겠다는 생각이 듭니다.

제가 할 일은 로컬 테스트를 통해, 테마 컴포넌트에서 제공해 주신 함수의 단순화된 버전을 사용하여 업로드 핸들러가 여러 파일을 어떻게 처리했는지 확인하는 것입니다. 그리고 나서 새 방식과 구 방식 간의 동등성을 달성해 보려고 합니다. 어차피 1개씩만 허용하는 것보다 훨씬 더 유연할 테니까요.

이를 수정하는 데 시간이 좀 걸릴 수 있지만, 오늘 중에 작업하겠습니다.

2개의 좋아요

간단한 업데이트를 공유하고자 합니다. pre-uppy composer 업로드 핸들러의 경우, 코드에서는 파일이 하나만 업로드되는지 확인하지만, 이는 정확하지 않습니다. jQuery file uploader는 이 코드 경로에서 한 번에 하나의 파일만 전송하기 때문입니다. 여러 파일을 한꺼번에 드롭하더라도 마찬가지입니다. 이는 uppy와 대조적입니다. uppy는 추가된 파일을 그룹 단위로 처리합니다. 이 "한 번에 하나의 파일"이라는 가정은 우리가 만든 api.addComposerUploadHandler를 사용하는 다른 두 플러그인에서도 적용되고 있어, 이는 일반적인 문제로 보입니다.

앞서 말씀드린 대로, 최선의 방법은 이 핸들러가 여러 파일을 처리할 수 있도록 하고, 플러그인/테마 개발자에게 합리적인 방식으로 배치(batch)하여 다른 곳으로 전송할 수 있도록 하는 것이라고 생각합니다. 최소한 uppy 업로드 핸들러에서 한 번에 하나의 파일만 전송될 수 있다는 가정을 수정할 수 있습니다. 업데이트가 있을 때 다시 이곳에 게시하겠습니다.

2개의 좋아요

주말 전에 마지막으로 업데이트를 남깁니다. 다음 주 초에 병합될 예정인 수정 사항이 있는데, 이를 통해 uppy 이전의 “구식” 방식을 uppy 내부에서 다시 사용할 수 있게 됩니다. 따라서 이 수정 사항이 적용된 후 여러분의 구현도 다시 올바르게 작동하게 될 것입니다:

하지만 저는 이후에 addComposerUploadHandler가 핸들러 콜백으로 여러 파일을 배열 형태로 전달하도록 변경하는 후속 PR도 추가할 예정입니다. 이를 통해 여러 파일이 들어오는 경우를 처리하기 위해 큐와 setTimeout 콜백을 설정할 필요가 사라집니다. 저는 이것이 어쨌든 더 올바른 방식이며, API 전체적으로도 개선된다고 생각합니다.

따라서 여러분의 핸들러는 다음과 같은 형태로 바뀌게 됩니다:

// Register custom upload handler for videos.
api.addComposerUploadHandler(
  ["mp4", "mov", "mkv", "avi", "m4v"],
  (files, editor) => {
    console.log("Handling upload for", files.map((file) => file.name).join(", "));
    sendToGDrive(files, api);
  }
);
2개의 좋아요

훌륭습니다. 이렇게 빨리 확인해 주셔서 감사합니다!
정말 잘 쉬시기 바랍니다 :blush:

2개의 좋아요

@Sören_Geier 방금 업로드 핸들러에 여러 파일을 한 번에 전송하도록 uppy를 변경하는 DEV: Send multiple files in batches to composer upload handlers when using uppy - Pull Request #15124%EB%A5%BC - discourse/discourse - GitHub 병합했습니다. 이제 이 변경 사항을 처리하도록 테마 컴포넌트를 업데이트해야 합니다 :slight_smile:

3개의 좋아요

정말 좋습니다. 아직 배포되지 않았죠?

표준 호스팅을 사용 중이신가요? 그렇다면 이제 배포가 완료되었을 것입니다 :slight_smile:

3개의 좋아요

오케이, 업로드를 하려던 사람들이 문제가 생겼다는 불만이 들어왔어요.
직접 확인해보니, 파일 객체를 그대로 전달해서 GDRIVE로 파일을 보내는 데도 초기에 문제가 있었더라고요. 알고 보니 파일 객체가 바이너리 파일을 uppy로 감싸서 표현한 형태였는데, 모양은 이랬어요.

실제 네이티브 파일 객체에 접근하려면 files[0].data를 사용해야 했어요. (혹시 깨지는 변경 사항일까요?)

그 변경 사항 이전에는 핸들러가 네이티브 파일 객체를 그대로 전달하고 있었거든요. 이 변경 사항으로 인해 다른 사용자들도 기능이 깨지는 문제를 겪을 수 있을지 저는 잘 모르겠어요.

이제 모든 것이 정상적으로 작동합니다. 빠른 대응과 지원에 정말 감사드립니다!

3개의 좋아요

아, 맞아요. 방금 리팩토링을 할 때 어떻게 그걸 놓쳤는지 모르겠네요. :sweat: 오늘 오전 중에 수정해서 올릴게요. 오래 걸리지 않을 겁니다.

수정: 수정 사항이 반영되었습니다. 몇 시간 내에 표준 호스팅 환경에 배포될 예정입니다.

3개의 좋아요

좋아요, 코드도 수정했습니다. 이제 이 주제를 닫아도 될 것 같습니다. @martin, 정말 큰 도움 주셔서 감사합니다.

1개의 좋아요

문제없어! 내가 만든 난리니까 내가 치우는 게 당연하지 :sweat_smile:

1개의 좋아요