@@ -40,6 +40,7 @@ var ( | |||
DisabledRepoUnits []string | |||
DefaultRepoUnits []string | |||
PrefixArchiveFiles bool | |||
RepoMaxSize int64 | |||
// Repository editor settings | |||
Editor struct { | |||
@@ -54,6 +55,7 @@ var ( | |||
AllowedTypes []string `delim:"|"` | |||
FileMaxSize int64 | |||
MaxFiles int | |||
TotalMaxSize int64 | |||
} `ini:"-"` | |||
// Repository local settings | |||
@@ -104,6 +106,7 @@ var ( | |||
DisabledRepoUnits: []string{}, | |||
DefaultRepoUnits: []string{}, | |||
PrefixArchiveFiles: true, | |||
RepoMaxSize: 1024, | |||
// Repository editor settings | |||
Editor: struct { | |||
@@ -121,12 +124,14 @@ var ( | |||
AllowedTypes []string `delim:"|"` | |||
FileMaxSize int64 | |||
MaxFiles int | |||
TotalMaxSize int64 | |||
}{ | |||
Enabled: true, | |||
TempPath: "data/tmp/uploads", | |||
AllowedTypes: []string{}, | |||
FileMaxSize: 3, | |||
MaxFiles: 5, | |||
FileMaxSize: 30, | |||
MaxFiles: 10, | |||
TotalMaxSize: 1024, | |||
}, | |||
// Repository local settings | |||
@@ -1256,6 +1256,10 @@ editor.cannot_commit_to_protected_branch = Cannot commit to protected branch '%s | |||
editor.no_commit_to_branch = Unable to commit directly to branch because: | |||
editor.user_no_push_to_branch = User cannot push to branch | |||
editor.require_signed_commit = Branch requires a signed commit | |||
editor.repo_too_large = Repository can not exceed %d MB | |||
editor.repo_file_invalid = Upload files are invalid | |||
editor.upload_file_too_much = Can not upload more than %d files at a time | |||
commits.desc = Browse source code change history. | |||
commits.commits = Commits | |||
@@ -2863,6 +2867,8 @@ uploading = Uploading | |||
upload_complete = Uploading complete | |||
failed = Upload Failed | |||
enable_minio_support = Enable minio support to use the dataset service | |||
max_file_tooltips= Upload a maximum of ? files at a time, each file does not exceed ? MB. | |||
max_size_tooltips= You can only upload a maximum of ? files at a time. The upload limit has been reached, please do not add more files. | |||
[notification] | |||
notifications = Notifications | |||
@@ -1263,6 +1263,9 @@ editor.cannot_commit_to_protected_branch=不可以提交到受保护的分支 '% | |||
editor.no_commit_to_branch=无法直接提交分支,因为: | |||
editor.user_no_push_to_branch=用户不能推送到分支 | |||
editor.require_signed_commit=分支需要签名提交 | |||
editor.repo_too_large = 代码仓总大小不能超过%dMB | |||
editor.repo_file_invalid = 提交的文件非法 | |||
editor.upload_file_too_much = 不能同时提交超过%d个文件 | |||
commits.desc=浏览代码修改历史 | |||
commits.commits=次代码提交 | |||
@@ -2869,6 +2872,8 @@ uploading=正在上传 | |||
upload_complete=上传完成 | |||
failed=上传失败 | |||
enable_minio_support=启用minio支持以使用数据集服务 | |||
max_file_tooltips=单次最多上传?个文件,每个文件不超过? MB。 | |||
max_size_tooltips=一次最多只能上传?个文件, 上传已达到上限,请勿再添加文件。 | |||
[notification] | |||
notifications=通知 | |||
@@ -5,6 +5,7 @@ | |||
package repo | |||
import ( | |||
repo_service "code.gitea.io/gitea/services/repository" | |||
"encoding/json" | |||
"fmt" | |||
"io/ioutil" | |||
@@ -614,6 +615,19 @@ func UploadFilePost(ctx *context.Context, form auth.UploadRepoFileForm) { | |||
message += "\n\n" + form.CommitMessage | |||
} | |||
if err := repo_service.CheckPushSizeLimit4Web(ctx.Repo.Repository, form.Files); err != nil { | |||
if repo_service.IsRepoTooLargeErr(err) { | |||
ctx.RenderWithErr(ctx.Tr("repo.editor.repo_too_large", setting.Repository.RepoMaxSize), tplUploadFile, &form) | |||
} else if repo_service.IsUploadFileInvalidErr(err) { | |||
ctx.RenderWithErr(ctx.Tr("repo.editor.repo_file_invalid"), tplUploadFile, &form) | |||
} else if repo_service.IsUploadFileTooMuchErr(err) { | |||
ctx.RenderWithErr(ctx.Tr("repo.editor.upload_file_too_much", setting.Repository.Upload.MaxFiles), tplUploadFile, &form) | |||
} else { | |||
ctx.RenderWithErr(err.Error(), tplUploadFile, &form) | |||
} | |||
return | |||
} | |||
if err := repofiles.UploadRepoFiles(ctx.Repo.Repository, ctx.User, &repofiles.UploadRepoFileOptions{ | |||
LastCommitID: ctx.Repo.CommitID, | |||
OldBranch: oldBranchName, | |||
@@ -8,6 +8,7 @@ import ( | |||
"fmt" | |||
"io/ioutil" | |||
"net/http" | |||
"os" | |||
"strings" | |||
"code.gitea.io/gitea/models" | |||
@@ -172,3 +173,137 @@ func RecommendFromPromote(url string) ([]string, error) { | |||
} | |||
return result, nil | |||
} | |||
func CheckPushSizeLimit4Web(repo *models.Repository, fileIds []string) error { | |||
if err := CheckRepoNumOnceLimit(len(fileIds)); err != nil { | |||
return err | |||
} | |||
totalSize, err := CountUploadFileSizeByIds(fileIds) | |||
if err != nil { | |||
return UploadFileInvalidErr{} | |||
} | |||
if err := CheckRepoTotalSizeLimit(repo, totalSize); err != nil { | |||
return err | |||
} | |||
return nil | |||
} | |||
func CheckPushSizeLimit4Http(repo *models.Repository, uploadFileSize int64) error { | |||
if err := CheckRepoOnceTotalSizeLimit(uploadFileSize); err != nil { | |||
return err | |||
} | |||
if err := CheckRepoTotalSizeLimit(repo, uploadFileSize); err != nil { | |||
return err | |||
} | |||
return nil | |||
} | |||
func CheckRepoTotalSizeLimit(repo *models.Repository, uploadFileSize int64) error { | |||
if repo.Size+uploadFileSize > setting.Repository.RepoMaxSize*1024*1024 { | |||
return RepoTooLargeErr{} | |||
} | |||
return nil | |||
} | |||
func CheckRepoOnceTotalSizeLimit(uploadFileSize int64) error { | |||
if uploadFileSize > setting.Repository.Upload.TotalMaxSize*1024*1024 { | |||
return UploadFileTooLargeErr{} | |||
} | |||
return nil | |||
} | |||
func CheckRepoNumOnceLimit(uploadFileNum int) error { | |||
if uploadFileNum > setting.Repository.Upload.MaxFiles { | |||
return UploadFileTooMuchErr{} | |||
} | |||
return nil | |||
} | |||
func CountUploadFileSizeByIds(fileIds []string) (int64, error) { | |||
if len(fileIds) == 0 { | |||
return 0, nil | |||
} | |||
uploads, err := models.GetUploadsByUUIDs(fileIds) | |||
if err != nil { | |||
return 0, fmt.Errorf("CountUploadFileSizeByIds error [uuids: %v]: %v", fileIds, err) | |||
} | |||
var totalSize int64 | |||
for _, upload := range uploads { | |||
size, err := GetUploadFileSize(upload) | |||
if err != nil { | |||
return 0, err | |||
} | |||
totalSize += size | |||
} | |||
return totalSize, nil | |||
} | |||
func GetUploadFileSize(upload *models.Upload) (int64, error) { | |||
info, err := os.Lstat(upload.LocalPath()) | |||
if err != nil { | |||
return 0, err | |||
} | |||
return info.Size(), nil | |||
} | |||
type RepoTooLargeErr struct { | |||
} | |||
func (RepoTooLargeErr) Error() string { | |||
return fmt.Sprintf("Repository can not exceed %d MB. Please remove some unnecessary files and try again", setting.Repository.RepoMaxSize) | |||
} | |||
func IsRepoTooLargeErr(err error) bool { | |||
_, ok := err.(RepoTooLargeErr) | |||
return ok | |||
} | |||
type UploadFileTooLargeErr struct { | |||
} | |||
func (UploadFileTooLargeErr) Error() string { | |||
return fmt.Sprintf("Upload files can not exceed %d MB at a time", setting.Repository.Upload.TotalMaxSize) | |||
} | |||
func IsUploadFileTooLargeErr(err error) bool { | |||
_, ok := err.(UploadFileTooLargeErr) | |||
return ok | |||
} | |||
type RepoFileTooLargeErr struct { | |||
} | |||
func (RepoFileTooLargeErr) Error() string { | |||
return "repository file is too large" | |||
} | |||
func IsRepoFileTooLargeErr(err error) bool { | |||
_, ok := err.(RepoFileTooLargeErr) | |||
return ok | |||
} | |||
type UploadFileTooMuchErr struct { | |||
} | |||
func (UploadFileTooMuchErr) Error() string { | |||
return "upload files are too lmuch" | |||
} | |||
func IsUploadFileTooMuchErr(err error) bool { | |||
_, ok := err.(UploadFileTooMuchErr) | |||
return ok | |||
} | |||
type UploadFileInvalidErr struct { | |||
} | |||
func (UploadFileInvalidErr) Error() string { | |||
return "upload files are invalid" | |||
} | |||
func IsUploadFileInvalidErr(err error) bool { | |||
_, ok := err.(UploadFileInvalidErr) | |||
return ok | |||
} |
@@ -27,7 +27,7 @@ | |||
</div> | |||
<div class="field"> | |||
<div class="files"></div> | |||
<div class="ui dropzone" id="dropzone" data-upload-url="{{.RepoLink}}/upload-file" data-remove-url="{{.RepoLink}}/upload-remove" data-csrf="{{.CsrfToken}}" data-accepts="{{.UploadAllowedTypes}}" data-max-file="{{.UploadMaxFiles}}" data-max-size="{{.UploadMaxSize}}" data-default-message="{{.i18n.Tr "dropzone.default_message"}}" data-invalid-input-type="{{.i18n.Tr "dropzone.invalid_input_type"}}" data-file-too-big="{{.i18n.Tr "dropzone.file_too_big"}}" data-remove-file="{{.i18n.Tr "dropzone.remove_file"}}"></div> | |||
<div class="ui dropzone" id="dropzone" data-upload-url="{{.RepoLink}}/upload-file" data-remove-url="{{.RepoLink}}/upload-remove" data-csrf="{{.CsrfToken}}" data-accepts="{{.UploadAllowedTypes}}" data-max-file="{{.UploadMaxFiles}}" data-max-size="{{.UploadMaxSize}}" data-default-message="{{.i18n.Tr "dropzone.default_message"}}" data-invalid-input-type="{{.i18n.Tr "dropzone.invalid_input_type"}}" data-file-too-big="{{.i18n.Tr "dropzone.file_too_big"}}" data-remove-file="{{.i18n.Tr "dropzone.remove_file"}}" data-max-file-tooltips="{{.i18n.Tr "dropzone.max_file_tooltips"}}" data-max-size-tooltips="{{.i18n.Tr "dropzone.max_size_tooltips"}}"><div class="maxfilesize ui red message" style="display: none;margin: 2.5rem;"></div></div> | |||
</div> | |||
{{template "repo/editor/commit_form" .}} | |||
</form> | |||
@@ -2751,9 +2751,23 @@ $(document).ready(async () => { | |||
$('td[data-href]').click(function () { | |||
window.location = $(this).data('href'); | |||
}); | |||
// 在String原型对象上添加format方法 | |||
String.prototype.format = function(){ | |||
let str = this; | |||
if(arguments.length == 0){ | |||
return str; | |||
}else{ | |||
Object.keys(arguments).forEach((item,index)=>{ | |||
str = str.replace(/\?/,arguments[item]) | |||
}) | |||
return str | |||
} | |||
} | |||
// Dropzone | |||
const $dropzone = $('#dropzone'); | |||
let maxFileTooltips=$dropzone.data('max-file-tooltips').format($dropzone.data('max-file'),$dropzone.data('max-size')) | |||
let maxSizeTooltips=$dropzone.data('max-size-tooltips').format($dropzone.data('max-file')) | |||
if ($dropzone.length > 0) { | |||
const filenameDict = {}; | |||
@@ -2788,6 +2802,22 @@ $(document).ready(async () => { | |||
}); | |||
} | |||
}); | |||
this.on('addedfile',(file)=>{ | |||
if(file.size/(1000*1000)>$dropzone.data('max-size')){ | |||
this.removeFile(file) | |||
$('.maxfilesize.ui.red.message').text(maxFileTooltips) | |||
$('.maxfilesize.ui.red.message').css('display','block') | |||
}else{ | |||
$('.maxfilesize.ui.red.message').css('display','none') | |||
} | |||
}); | |||
this.on('maxfilesexceeded',(file)=>{ | |||
this.removeFile(file) | |||
$('.maxfilesize.ui.red.message').text(maxSizeTooltips) | |||
$('.maxfilesize.ui.red.message').css('display','block') | |||
}) | |||
} | |||
}); | |||
} | |||
Dear OpenI User
Thank you for your continuous support to the Openl Qizhi Community AI Collaboration Platform. In order to protect your usage rights and ensure network security, we updated the Openl Qizhi Community AI Collaboration Platform Usage Agreement in January 2024. The updated agreement specifies that users are prohibited from using intranet penetration tools. After you click "Agree and continue", you can continue to use our services. Thank you for your cooperation and understanding.
For more agreement content, please refer to the《Openl Qizhi Community AI Collaboration Platform Usage Agreement》