diff --git a/backend/app/http/admin/uploads.go b/backend/app/http/admin/uploads.go
index 09a1858..6e65cee 100644
--- a/backend/app/http/admin/uploads.go
+++ b/backend/app/http/admin/uploads.go
@@ -35,7 +35,7 @@ type PreCheckResp struct {
func (up *uploads) PreUploadCheck(ctx fiber.Ctx, md5, ext string) (*PreCheckResp, error) {
_, err := models.Medias.GetByHash(ctx.Context(), md5)
if err != nil && errors.Is(err, qrm.ErrNoRows) {
- preSign, err := up.oss.PreSignUpload(ctx.Context(), fmt.Sprintf("%s%s", md5, ext))
+ preSign, err := up.oss.PreSignUpload(ctx.Context(), fmt.Sprintf("%s.%s", md5, ext))
if err != nil {
return nil, err
}
diff --git a/backend/providers/ali/oss_client.go b/backend/providers/ali/oss_client.go
index d537e48..2fc0776 100644
--- a/backend/providers/ali/oss_client.go
+++ b/backend/providers/ali/oss_client.go
@@ -19,8 +19,9 @@ func (c *OSSClient) GetClient() *oss.Client {
func (c *OSSClient) PreSignUpload(ctx context.Context, path string) (*oss.PresignResult, error) {
request := &oss.PutObjectRequest{
- Bucket: oss.Ptr(c.config.Bucket),
- Key: oss.Ptr("quyun/" + strings.Trim(path, "/")),
+ Bucket: oss.Ptr(c.config.Bucket),
+ Key: oss.Ptr("quyun/" + strings.Trim(path, "/")),
+ ContentType: oss.Ptr("multipart/form-data"),
}
log.Printf("%+v", request)
return c.client.Presign(ctx, request)
diff --git a/frontend/admin/src/api/mediaService.js b/frontend/admin/src/api/mediaService.js
index 551a1b9..0625f38 100644
--- a/frontend/admin/src/api/mediaService.js
+++ b/frontend/admin/src/api/mediaService.js
@@ -11,11 +11,8 @@ export const mediaService = {
return httpClient.post('/admin/medias', mediaInfo);
},
- getUploadToken() {
- return httpClient.get('/admin/uploads/token');
- },
- preUploadedCheck(md5) {
- return httpClient.get(`/admin/uploads/pre-uploaded-check/${md5}`);
+ preUploadedCheck(md5, ext) {
+ return httpClient.get(`/admin/uploads/pre-uploaded-check/${md5}.${ext}`);
},
uploadedSuccess(data) {
diff --git a/frontend/admin/src/pages/MediaUploadPage.vue b/frontend/admin/src/pages/MediaUploadPage.vue
index fa3b04d..79ef0ea 100644
--- a/frontend/admin/src/pages/MediaUploadPage.vue
+++ b/frontend/admin/src/pages/MediaUploadPage.vue
@@ -15,7 +15,6 @@ const dropZone = ref(null);
const uploadProgress = ref(0);
const isUploading = ref(false);
const currentFile = ref(null);
-const ossConfig = ref(null);
const uploadHistory = ref([]);
const STORAGE_KEY = 'media_upload_history';
@@ -56,19 +55,10 @@ const addToHistory = (file, status = 'uploading') => {
// Clear completed uploads
const clearCompleted = () => {
- uploadHistory.value = uploadHistory.value.filter(item => item.status !== 'completed');
+ uploadHistory.value = [];
saveUploadHistory();
};
-const getOssToken = async () => {
- try {
- const response = await mediaService.getUploadToken();
- ossConfig.value = response.data;
- } catch (error) {
- toast.add({ severity: 'error', summary: '错误', detail: '获取上传凭证失败', life: 3000 });
- }
-};
-
// Add pending uploads state
const uploadQueue = ref([]);
const currentUploadIndex = ref(-1);
@@ -107,10 +97,12 @@ const processNextUpload = async () => {
try {
const md5Hash = await calculateMD5(nextFile.file);
+ // get file ext
+ const fileExt = nextFile.file.name.split('.').pop();
// Check if file exists before upload
- const checkResult = await mediaService.preUploadedCheck(md5Hash);
- console.log(checkResult)
- if (checkResult.data === 'exists') {
+ const checkResult = await mediaService.preUploadedCheck(md5Hash, fileExt);
+
+ if (checkResult.data.exists) {
// Skip upload and mark as completed
uploadQueue.value.shift();
addToHistory(nextFile.file, 'completed');
@@ -121,8 +113,8 @@ const processNextUpload = async () => {
life: 3000
});
} else {
- // Proceed with upload
- await uploadFile(nextFile.file, md5Hash);
+ // Proceed with upload using pre-signed URL
+ await uploadFile(nextFile.file, md5Hash, checkResult.data.pre_sign);
uploadQueue.value.shift();
addToHistory(nextFile.file, 'completed');
}
@@ -175,34 +167,15 @@ const calculateMD5 = (file) => {
});
};
-// Modify uploadFile function
-const uploadFile = async (file, md5Hash) => {
+// Modify uploadFile function to use pre-signed URL
+const uploadFile = async (file, md5Hash, preSign) => {
try {
currentFile.value = file;
isUploading.value = true;
uploadProgress.value = 0;
- if (!ossConfig.value) {
- await getOssToken();
- }
-
- const fileExt = file.name.split('.').pop();
- const newFileName = `${md5Hash}.${fileExt}`;
-
await new Promise((resolve, reject) => {
const xhr = new XMLHttpRequest();
- const formData = new FormData();
-
- formData.append('success_action_status', '200');
- formData.append('policy', ossConfig.value.policy);
- formData.append('x-oss-signature', ossConfig.value.signature);
- formData.append('x-oss-signature-version', 'OSS4-HMAC-SHA256');
- formData.append('x-oss-credential', ossConfig.value.x_oss_credential);
- formData.append('x-oss-date', ossConfig.value.x_oss_date);
- formData.append('key', ossConfig.value.dir + newFileName);
- formData.append('x-oss-security-token', ossConfig.value.security_token);
- formData.append('callback', ossConfig.value.callback);
- formData.append('file', file);
xhr.upload.onprogress = (e) => {
if (e.lengthComputable) {
@@ -230,8 +203,16 @@ const uploadFile = async (file, md5Hash) => {
}
};
- xhr.open('POST', ossConfig.value.host, true);
- xhr.send(formData);
+ xhr.open(preSign.Method, preSign.URL, true);
+
+ // Add signed headers if provided
+ if (preSign.SignedHeaders) {
+ Object.entries(preSign.SignedHeaders).forEach(([key, value]) => {
+ xhr.setRequestHeader(key, value);
+ });
+ }
+
+ xhr.send(file);
});
toast.add({ severity: 'success', summary: '成功', detail: '文件上传成功', life: 3000 });
@@ -346,8 +327,7 @@ onMounted(() => {
上传历史
-
+