小程序前端上傳文件不建議直接引用minio的js npm包,一來是這個包本身較大,會影響小程序的體積,二來是ak sk需要放到前端存儲,不夠安全,因此建議通過請求后端拿到簽名數據后上傳。
由於小程序的uploadFile僅支持POST請求(估計以后也不會支持PUT了),因此只能使用minio的PresignedPostPolicy方法返回簽名后的formData,然后再放到小程序的uploadFile方法的formData參數中
后端 .net
安裝minio nuget包
接口返回dto
public class UploadInfo { public string Key { get; set; } public string Url { get; set; } public Dictionary<string, string> FormData { get; set; } }
多個key進行預簽名, 注意new MinioClient的第一個參數是minio的服務器地址,不能有http://或https://, 如果是https則需要new 之后再調用.WithSSL(),參見官方文檔。 當然最佳實踐還是要將minioClient對象通過依賴注入管理,minio相關配置通過IConfiguration(appsettings.json)來管理。
public async Task<UploadInfo[]> PresignedPostPolicyAsync(string[] keys) { string bucket = "myBucket"; var minioClient = new MinioClient("myminio.com:9000", "ak", "sk" ); var result = new UploadInfo[keys.Length]; for (int i = 0; i < keys.Length; i++) { var policy = new PostPolicy(); policy.SetKey(keys[i]); policy.SetBucket(bucket); policy.SetExpires(DateTime.UtcNow.AddHours(2));//設置策略過期時間 Tuple<string, Dictionary<string, string>> data = await minioClient.PresignedPostPolicyAsync(policy); result[i] = new UploadInfo { Key = keys[i], Url = $"{data.Item1}{bucket}/{keys[i]}", FormData = data.Item2, }; } return result; }
后端 java
dto
import java.util.Map; import lombok.Data; @Data public class Upload { private String key; private String url; private Map<String, String> formData; }
多個key進行預簽名, 和.net sdk不一樣的地方在於minio 服務器地址需要加上http, 還有可以設置上傳條件,如 addEqualsCondition("key", key),表示key必須為對應的值, addStartsWithCondition("content-type","image/") 表示content-type必須以image/開頭,也就是只能上傳圖片。
public List<Upload> uploadFiles(String[] keys) throws IOException, NoSuchAlgorithmException, InvalidKeyException { List<Upload> uploads = new ArrayList<>(); String bucket = "myBucket"; String endPoint = "http://myminio.com:9000"; try { MinioClient minioClient = MinioClient.builder() .endpoint(endPoint) .credentials("ak", "sk") .build();for (int i = 0; i < jsonArray.size(); i++) { Upload upload = new Upload(); String key = keys[i]; PostPolicy policy = new PostPolicy(bucket, ZonedDateTime.now().plusHours(2)); policy.addEqualsCondition("key", key); Map<String, String> formData = minioClient.getPresignedPostFormData(policy); String url = endPoint + "/" + bucket +"/" + key; upload.setKey(key); upload.setUrl(url); upload.setFormData(formData); uploads.add(upload); } }catch (MinioException e) { System.out.println("Error occurred: " + e); } return uploads; }
小程序
Taro代碼如下,如果是原生微信小程序則把Taro換為wx即可(如原生小程序沒有擴展支持async await,則需要更換為wx.request({url:xxx, data:xxx, success=>{ //后續處理 }}))的形式,通過傳入success回調來處理拿到預簽名數據的情況。 注意uploadFile參數里 name需要設置為file, formData里設置key為policy簽名的key。 上傳成功minio會返回204
1 let minioUrl = 'https://myminio.com:9000' 2 let minioPresignUrl = 'https://myminio.com:8000/files/presign'; 3 Taro.chooseImage({ 4 count: 1, 5 sizeType: ["original", "compressed"], 6 sourceType: ["album", "camera"], 7 success: async res=>{ 8 let result = await Taro.request({url: minioPresignUrl, data: {keys:[res.tempFilePaths[0]]}}); 9 result.data.data.forEach(f => { 10 f.formData.key = f.key; 11 Taro.uploadFile({ 12 filePath:res.tempFilePaths[0] , 13 name: "file", 14 url: minioUrl, 15 formData: f.formData, 16 success: r => { 17 if (r.statusCode === 204) { 18 console.log('上傳成功'); 19 } 20 } 21 }); 22 }) 23 } 24 })