huhx / flutter_oss_aliyun

阿里云oss sdk的flutter版本
MIT License
61 stars 22 forks source link

上传相册图片该用putobjectfile还是putobject #46

Closed zzy080615 closed 11 months ago

zzy080615 commented 11 months ago

低级问题 上传文件和上传本地文件有什么区别么,比如苹果选择文件应用里面的文件是用文件上传还是本地文件上传合适,麻烦解答下

huhx commented 11 months ago

上传苹果选择文件应用里面的文件,你能够得到文件的信息,比如文件路径。

  1. putobjectfile这个方法接收的是本地文件的路径
    final Response<dynamic> resp = await Client().putObjectFile(
      "$home/Downloads/journal_bg-min.png",
      fileKey: "aaa.png",
      option: PutRequestOption(
        onSendProgress: (count, total) {
          print("send: count = $count, and total = $total");
        },
        onReceiveProgress: (count, total) {
          print("receive: count = $count, and total = $total");
        },
        aclModel: AclMode.private,
        callback: Callback(
          callbackUrl: callbackUrl,
          callbackBody:
              "{\"mimeType\":\${mimeType}, \"filepath\":\${object},\"size\":\${size},\"bucket\":\${bucket},\"phone\":\${x:phone}}",
          callbackVar: {"x:phone": "android"},
          calbackBodyType: CalbackBodyType.json,
        ),
      ),
    );
  2. putobject这个方法接收的是文件的bytes数组

    final File file = File("$home/Downloads/idiom.csv");
    final String string = await file.readAsString();
    
    final Response<dynamic> resp = await Client().putObject(
      Uint8List.fromList(utf8.encode(string)),
      "test.csv",
      option: PutRequestOption(
        onSendProgress: (count, total) {
          print("send: count = $count, and total = $total");
        },
        onReceiveProgress: (count, total) {
          print("receive: count = $count, and total = $total");
        },
        override: true,
        aclModel: AclMode.publicRead,
        storageType: StorageType.ia,
        headers: {"content-type": "text/csv"},
        callback: Callback(
          callbackUrl: callbackUrl,
          callbackBody:
              "{\"mimeType\":\${mimeType}, \"filepath\":\${object},\"size\":\${size},\"bucket\":\${bucket},\"phone\":\${x:phone}}",
          callbackVar: {"x:phone": "android"},
          calbackBodyType: CalbackBodyType.json,
        ),
      ),
    );

结论:两种都可以使用。如果知道本地文件路径,推荐使用putobjectfile

zzy080615 commented 11 months ago

我在模拟器中选择了相册图片用putobjectfile方式上传,但是报错,我无法理解报错的意思。 路径和filekey和callbackurl是不是定义的有问题

截屏2023-10-06 20 18 42 截屏2023-10-06 20 14 49
zzy080615 commented 11 months ago

定位在这步报错
auth.sign(request, bucket, filename); 打印了 request bucket 和filename信息 然后下一步 auth.sign方法报错

截屏2023-10-07 22 54 50
zzy080615 commented 11 months ago

secureToken为null导致的

Client.init( stsUrl: "http://36.137.218.216:48081/app-api/oss/policy?exn", ossEndpoint: "oss-cn-nanjing.aliyuncs.com", bucketName: "im-hh-t0", );

{"code":0,"data":{"OSSAccessKeyId":"LTAI5tRexhtd4xC1KWcrB6YA","signature":"CbndvzHYFr8x9tajVfuP3072H9Y=","expire":"1696690744","host":"https://im-hh-t0.oss-cn-nanjing.aliyuncs.com","key":"null/2023-10-07/9e8f2f1b8a734e8f85ec5ebd199726ee","policy":"eyJleHBpcmF0aW9uIjoiMjAyMy0xMC0wN1QxNDo1OTowNC4xMDdaIiwiY29uZGl0aW9ucyI6W1siY29udGVudC1sZW5ndGgtcmFuZ2UiLDAsMTA0ODU3NjAwMF0sWyJzdGFydHMtd2l0aCIsIiRrZXkiLCJudWxsLzIwMjMtMTAtMDcvOWU4ZjJmMWI4YTczNGU4Zjg1ZWM1ZWJkMTk5NzI2ZWUiXV19"},"msg":""}

为什么我的返回值里面没有secureToken字段

huhx commented 11 months ago

定位在这步报错

auth.sign(request, bucket, filename);

打印了 request bucket 和filename信息 然后下一步 auth.sign方法报错

截屏2023-10-07 22 54 50

好的,我明天试下。你用的是最新版本6.29吗。有没有在真机上测试过呢

zzy080615 commented 11 months ago

是不是因为我们后端返回的结构和你的auth模型不一致导致的吧

zzy080615 commented 11 months ago

定位在这步报错 auth.sign(request, bucket, filename); 打印了 request bucket 和filename信息 然后下一步 auth.sign方法报错

截屏2023-10-07 22 54 50

好的,我明天试下。你用的是最新版本6.29吗。有没有在真机上测试过呢

我怀疑是我们后端请求替我们做的步骤太多了,导致和你cli en t.init方法里面的auth模型匹配不上了,是不是这个问题呢。后端已经生成了signature了

截屏2023-10-07 23 43 50
huhx commented 11 months ago

定位在这步报错 auth.sign(request, bucket, filename); 打印了 request bucket 和filename信息 然后下一步 auth.sign方法报错

截屏2023-10-07 22 54 50

好的,我明天试下。你用的是最新版本6.29吗。有没有在真机上测试过呢

我怀疑是我们后端请求替我们做的步骤太多了,导致和你cli en t.init方法里面的auth模型匹配不上了,是不是这个问题呢。后端已经生成了signature了 截屏2023-10-07 23 43 50

返回的凭证信息结构大概如下:

    return Map.of(
        "StatusCode", 200,
        "AccessKeyId", credentials.getAccessKeyId(),
        "AccessKeySecret", credentials.getAccessKeySecret(),
        "SecurityToken", credentials.getSecurityToken(),
        "Expiration", credentials.getExpiration()
    );

我是按照aliyun oss官方规范来的。你这个好像签名是后端给做了

huhx commented 11 months ago
image

后端我是用的java

@Service
@RequiredArgsConstructor
public class AliyunOssService {

  private final OssProperties ossProperties;
  private final IAcsClient client;
  private final AssumeRoleRequest request;
  private final RedisService redisService;

  public Map<String, Object> getAuthCredentials() throws ClientException {
    var credentials = redisService.getAuthCredentials();
    if (Objects.isNull(credentials)) {
      credentials = client.getAcsResponse(request).getCredentials();
      redisService.saveAuthCredential(credentials);
    }
    return Map.of(
        "StatusCode", 200,
        "AccessKeyId", credentials.getAccessKeyId(),
        "AccessKeySecret", credentials.getAccessKeySecret(),
        "SecurityToken", credentials.getSecurityToken(),
        "Expiration", credentials.getExpiration()
    );
  }
}

这是一个大概的实现,后端使用了aliyun 的sdk。

  implementation 'com.aliyun:aliyun-java-sdk-core:4.6.4'
  implementation 'com.aliyun:aliyun-java-sdk-sts:3.1.1'