Codename One上传图片至S3 Bucket失败:遇301错误与空指针异常
问题背景
参考Stack Overflow帖子在Codename One项目中上传图片到S3 Bucket,操作失败,出现301连接错误码和java.lang.NullPointerException异常。已通过Postman和JavaScript SDK成功上传,确认Bucket配置无问题,想知道是否需要AccessKey、SecretKey、AWS Region这类额外凭证。
代码示例
try { String strImage = Capture.capturePhoto(300, -1); String s3Bucket = "https://s3.amazonaws.com/mybucketname/"; String fileName = "testimg1.jpg"; MultipartRequest request = new MultipartRequest(); request.setUrl(s3Bucket); request.addRequestHeader("Content-Type", "image/jpeg"); request.addArgumentNoEncoding("key", fileName); request.addArgument("acl", "bucket-owner-full-control"); request.addData("file", strImage, "image/jpeg"); NetworkManager.getInstance().addToQueueAndWait(request); int http_code = request.getResponseCode(); Dialog.show("Ok", String.valueOf(http_code), "Ok", null); } catch (Exception ex) { String err = ex.toString(); Dialog.show("Err", err, "Ok", null); }
控制台报错信息
java.lang.NullPointerException at com.codename1.io.ConnectionRequest.performOperationComplete(ConnectionRequest.java:935) at com.codename1.io.NetworkManager$NetworkThread.runCurrentRequest(NetworkManager.java:314) at com.codename1.io.NetworkManager$NetworkThread.run(NetworkManager.java:390) at com.codename1.impl.CodenameOneThread.run(CodenameOneThread.java:176) [Network Thread] 0:0:6,656 - Exception: java.io.IOException - Stream closed java.io.IOException: Stream closed at com.codename1.io.BufferedInputStream.getInIfOpen(BufferedInputStream.java:140) at com.codename1.io.BufferedInputStream.read1(BufferedInputStream.java:338) at com.codename1.io.BufferedInputStream.read(BufferedInputStream.java:445) at com.codename1.io.BufferedInputStream.read(BufferedInputStream.java:668) at com.codename1.io.Util.copyNoClose(Util.java:149) at com.codename1.io.Util.copyNoClose(Util.java:135) at com.codename1.io.Util.copy(Util.java:170) at com.codename1.io.Util.copy(Util.java:124) at com.codename1.io.Util.readInputStream(Util.java:303) at com.codename1.io.ConnectionRequest.readResponse(ConnectionRequest.java:1543) at com.codename1.io.ConnectionRequest.performOperationComplete(ConnectionRequest.java:1003) at com.codename1.io.NetworkManager$NetworkThread.runCurrentRequest(NetworkManager.java:314) at com.codename1.io.NetworkManager$NetworkThread.run(NetworkManager.java:390) at com.codename1.impl.CodenameOneThread.run(CodenameOneThread.java:176)
问题分析与解决
1. 301错误的根源
你使用的S3全局端点https://s3.amazonaws.com/mybucketname/已被AWS逐步淘汰,现在要求使用区域专属端点(如https://mybucketname.s3.us-east-1.amazonaws.com),全局端点会返回301重定向。而Codename One的MultipartRequest默认不自动处理重定向,导致请求中断,进而引发后续的空指针和流关闭异常。
2. 凭证的必要性
必须提供AccessKey、SecretKey和AWS Region,除非你的Bucket配置了完全公开的匿名上传(生产环境不建议)。Postman和JS SDK能成功上传,是因为它们自动处理了AWS签名和重定向逻辑,而你的Codename One代码缺少签名步骤。
3. 修复步骤
步骤1:修正S3端点URL
将Bucket URL改为区域专属格式,例如Bucket在us-east-1区域时:
String s3Bucket = "https://mybucketname.s3.us-east-1.amazonaws.com/";
步骤2:添加AWS签名逻辑
S3要求请求携带AWS v4签名,你需要在请求头中添加Authorization字段(包含签名后的凭证信息),同时添加X-Amz-Date等必要头信息。可以手动实现签名,或使用Codename One第三方AWS集成库简化开发。
步骤3:处理重定向(可选)
若坚持使用旧端点,可开启请求的重定向支持:
request.setFollowRedirects(true);
但优先推荐使用区域端点,避免重定向带来的额外异常。
步骤4:空指针异常排查
空指针是重定向后流未正确处理导致的,修复端点和签名后该异常会自动消失。也可添加错误监听获取更详细日志:
NetworkManager.getInstance().addErrorListener((e) -> { Log.p("Request error: " + e.getError()); });
内容的提问来源于stack exchange,提问作者user22676753

