FIX: catch all server-side error when uploading a file
UX: always show a message to the user whenever an error happens on the server when uploading a file
This commit is contained in:
parent
805d1c25d3
commit
f5e170c6b5
|
@ -493,7 +493,7 @@ export default Ember.Component.extend({
|
||||||
this._xhr = null;
|
this._xhr = null;
|
||||||
|
|
||||||
if (!userCancelled) {
|
if (!userCancelled) {
|
||||||
displayErrorForUpload(data.jqXHR.responseJSON);
|
displayErrorForUpload(data);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
|
@ -334,27 +334,27 @@ export function getUploadMarkdown(upload) {
|
||||||
}
|
}
|
||||||
|
|
||||||
export function displayErrorForUpload(data) {
|
export function displayErrorForUpload(data) {
|
||||||
// deal with meaningful errors first
|
|
||||||
if (data.jqXHR) {
|
if (data.jqXHR) {
|
||||||
switch (data.jqXHR.status) {
|
switch (data.jqXHR.status) {
|
||||||
// cancelled by the user
|
// cancelled by the user
|
||||||
case 0: return;
|
case 0:
|
||||||
|
return;
|
||||||
|
|
||||||
// entity too large, usually returned from the web server
|
// entity too large, usually returned from the web server
|
||||||
case 413:
|
case 413:
|
||||||
var type = uploadTypeFromFileName(data.files[0].name);
|
const type = uploadTypeFromFileName(data.files[0].name);
|
||||||
var maxSizeKB = Discourse.SiteSettings['max_' + type + '_size_kb'];
|
const max_size_kb = Discourse.SiteSettings[`max_${type}_size_kb`];
|
||||||
bootbox.alert(I18n.t('post.errors.file_too_large', { max_size_kb: maxSizeKB }));
|
bootbox.alert(I18n.t('post.errors.file_too_large', { max_size_kb }));
|
||||||
return;
|
return;
|
||||||
|
|
||||||
// the error message is provided by the server
|
// the error message is provided by the server
|
||||||
case 422:
|
case 422:
|
||||||
if (data.jqXHR.responseJSON.message) {
|
if (data.jqXHR.responseJSON.message) {
|
||||||
bootbox.alert(data.jqXHR.responseJSON.message);
|
bootbox.alert(data.jqXHR.responseJSON.message);
|
||||||
} else {
|
} else {
|
||||||
bootbox.alert(data.jqXHR.responseJSON.join("\n"));
|
bootbox.alert(data.jqXHR.responseJSON.join("\n"));
|
||||||
}
|
}
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
} else if (data.errors && data.errors.length > 0) {
|
} else if (data.errors && data.errors.length > 0) {
|
||||||
bootbox.alert(data.errors.join("\n"));
|
bootbox.alert(data.errors.join("\n"));
|
||||||
|
|
|
@ -56,7 +56,7 @@ export default Em.Mixin.create({
|
||||||
});
|
});
|
||||||
|
|
||||||
$upload.on("fileuploadfail", (e, data) => {
|
$upload.on("fileuploadfail", (e, data) => {
|
||||||
displayErrorForUpload(data.jqXHR.responseJSON);
|
displayErrorForUpload(data);
|
||||||
reset();
|
reset();
|
||||||
});
|
});
|
||||||
}.on("didInsertElement"),
|
}.on("didInsertElement"),
|
||||||
|
|
|
@ -26,17 +26,22 @@ class UploadsController < ApplicationController
|
||||||
# note, atm hijack is processed in its own context and has not access to controller
|
# note, atm hijack is processed in its own context and has not access to controller
|
||||||
# longer term we may change this
|
# longer term we may change this
|
||||||
hijack do
|
hijack do
|
||||||
info = UploadsController.create_upload(
|
begin
|
||||||
current_user: me,
|
info = UploadsController.create_upload(
|
||||||
file: file,
|
current_user: me,
|
||||||
url: url,
|
file: file,
|
||||||
type: type,
|
url: url,
|
||||||
for_private_message: for_private_message,
|
type: type,
|
||||||
pasted: pasted,
|
for_private_message: for_private_message,
|
||||||
is_api: is_api,
|
pasted: pasted,
|
||||||
retain_hours: retain_hours
|
is_api: is_api,
|
||||||
)
|
retain_hours: retain_hours
|
||||||
render json: UploadsController.serialize_upload(info), status: Upload === info ? 200 : 422
|
)
|
||||||
|
rescue => e
|
||||||
|
render json: failed_json.merge(message: e.message&.split("\n")&.first), status: 422
|
||||||
|
else
|
||||||
|
render json: UploadsController.serialize_upload(info), status: Upload === info ? 200 : 422
|
||||||
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
|
@ -2873,6 +2873,7 @@ en:
|
||||||
store_failure: "Failed to store upload #%{upload_id} for user #%{user_id}."
|
store_failure: "Failed to store upload #%{upload_id} for user #%{user_id}."
|
||||||
file_missing: "Sorry, you must provide a file to upload."
|
file_missing: "Sorry, you must provide a file to upload."
|
||||||
empty: "Sorry, but the file you provided is empty."
|
empty: "Sorry, but the file you provided is empty."
|
||||||
|
png_to_jpg_conversion_failure_message: "An error happened when converting from PNG to JPG."
|
||||||
attachments:
|
attachments:
|
||||||
too_large: "Sorry, the file you are trying to upload is too big (maximum size is %{max_size_kb}KB)."
|
too_large: "Sorry, the file you are trying to upload is too big (maximum size is %{max_size_kb}KB)."
|
||||||
images:
|
images:
|
||||||
|
|
|
@ -163,7 +163,7 @@ class UploadCreator
|
||||||
command << '-debug' << 'all' if debug
|
command << '-debug' << 'all' if debug
|
||||||
command << output_file.path
|
command << output_file.path
|
||||||
|
|
||||||
Discourse::Utils.execute_command(*command, failure_message: "failed to convert png to jpg")
|
Discourse::Utils.execute_command(*command, failure_message: I18n.t("upload.png_to_jpg_conversion_failure_message"))
|
||||||
end
|
end
|
||||||
|
|
||||||
def should_downsize?
|
def should_downsize?
|
||||||
|
|
Loading…
Reference in New Issue