gpt4 book ai didi

java - 用于 block Blob 的 Azure 存储服务 REST API : Content Length Issue

转载 作者:太空宇宙 更新时间:2023-11-04 10:20:14 24 4
gpt4 key购买 nike

我正在尝试使用 azure storage Rest api 来推送 block blob 类型,但问题是要事先了解内容长度以便上传。

对于需要在没有可用长度信息的情况下中继 inputStream 的情况,我们是否有解决方法。

String accesskey = "accesskey";
String storageAccount = "storageAccount";
String containerName = "containerName";
String workgroupId = UUID.randomUUID().toString();
String objectId = "1." + UUID.randomUUID().toString();
String blobName = getAzureAccessKey(containerName, workgroupId, objectId);
String version = "2018-03-28";
String putData = "testData";

SimpleDateFormat fmt = new SimpleDateFormat("EEE, dd MMM yyyy HH:mm:ss");
fmt.setTimeZone(TimeZone.getTimeZone("GMT"));
String currentDate = fmt.format(Calendar.getInstance().getTime()) + " GMT";

String urlResource = "/"+ Paths.get(storageAccount, containerName, blobName).toString();
String headerResource = "x-ms-blob-type:BlockBlob\nx-ms-date:" + currentDate + "\nx-ms-version:" + version;
String putUrl = "https://" + storageAccount + ".blob.core.windows.net/" + containerName + "/" + blobName;
System.out.println(putUrl);
String newline = "\n";

List listToSign = Lists.newArrayList();
listToSign.add("PUT");
listToSign.add("");
listToSign.add("");
listToSign.add("");
listToSign.add("");
listToSign.add("application/octet-stream");
listToSign.add("");
listToSign.add("");
listToSign.add("");
listToSign.add("");
listToSign.add("");
listToSign.add("");
listToSign.add(headerResource);
listToSign.add(urlResource);

String stringToSign = String.join(newline, listToSign);
Base64 base64 = new Base64();


System.out.println(stringToSign);
Mac mac = Mac.getInstance("HmacSHA256");
mac.init(new SecretKeySpec(base64.decode(accesskey), "HmacSHA256"));
String authKey = new String(base64.encode(mac.doFinal(stringToSign.getBytes("UTF-8"))));

String authHeader = "SharedKey " + storageAccount + ":"+ authKey;

System.out.println(authHeader);

InputStreamEntity entity = new InputStreamEntity(
new ByteArrayInputStream(putData.getBytes(StandardCharsets.UTF_8)), -1,
ContentType.APPLICATION_OCTET_STREAM);

// set chunked transfer encoding ie. no Content-length
entity.setChunked(true);
HttpPut httpPut = null;
try {

DefaultHttpClient httpClient = new DefaultHttpClient();
httpClient.removeRequestInterceptorByClass(org.apache.http.protocol.RequestContent.class);

httpPut = new HttpPut(putUrl);
httpPut.setHeader("Host", storageAccount + ".blob.core.windows.net");
httpPut.setHeader("Transfer-Encoding","chunked");
//httpPut.setHeader("Content-Length","0");
httpPut.setHeader("Content-Type","application/octet-stream");
httpPut.addHeader("x-ms-blob-type", "BlockBlob");
httpPut.addHeader("x-ms-date", currentDate);
httpPut.addHeader("x-ms-version", version);
httpPut.addHeader("Authorization",authHeader);


httpPut.setEntity(entity);

System.out.println("Request Headers");

for (Header header : httpPut.getAllHeaders()) {
System.out.println(header.getName() + ":" + header.getValue());
}
HttpResponse response = httpClient.execute(httpPut);
System.out.println(response.getStatusLine());


for (Header header: response.getAllHeaders()) {
System.out.println(header.getName()+":"+ header.getValue());
}
// Read the contents of an entity and return it as a String.
String content = EntityUtils.toString(response.getEntity());
System.out.println(content);

} finally {

if(httpPut != null ){
httpPut.releaseConnection();
}
}

服务器响应

HTTP Error 400. There is an invalid content length or chunk length in the request.

如果我将内容长度设置为签名和 header 信息的一部分,则上述代码有效。

最佳答案

我们可以使用ByteArrayEntity来获取内容长度,而不是使用InputStreamEntity

这是一个简单的演示供您引用:

        FileInputStream fileInputStream=null;
ByteArrayOutputStream bos = null ;
try {
fileInputStream=new FileInputStream("D:/Test/Test.txt");
bos = new ByteArrayOutputStream();
byte[] bytes=new byte[102400];
int x=0;
while ((x=fileInputStream.read(bytes))!= -1){
bos.write(bytes,0,x);
}
byte[] data = bos.toByteArray();

org.apache.http.entity.ByteArrayEntity byteArrayEntity=new ByteArrayEntity(data);
int contentLength=data.length;

} catch (Exception e) {
e.printStackTrace();
}

正如卢兆兴上面所说,我们可以使用Java SDK来实现这一点,这里有使用Java SDK的demo供大家引用:

import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.net.URISyntaxException;
import java.security.InvalidKeyException;
import com.microsoft.azure.storage.CloudStorageAccount;
import com.microsoft.azure.storage.blob.CloudBlobClient;
import com.microsoft.azure.storage.blob.CloudBlobContainer;
import com.microsoft.azure.storage.blob.CloudBlockBlob;
import com.microsoft.azure.storage.blob.ListBlobItem;

public class Main {

public static final String ConnString="DefaultEndpointsProtocol=https;AccountName=xxxxxxxxb;AccountKey=O7xxxx8e86XQSy2vkvSi/x/e9l9FhLqxxxxjkly1DsQPYY5dF2JrAVxxxxo29ZrrGJA==;EndpointSuffix=core.windows.net";
public static void main(String[] args) {
// TODO Auto-generated method stub
uploadBlob("mycontainer","TechTalk.pptx","E:\\Test\\TechTalk.pptx");
System.out.println("Success");

}

public static void uploadBlob(String containerName, String blobName,String filePath) {
CloudStorageAccount account = null;
CloudBlobContainer container = null;
try {
account = CloudStorageAccount.parse(ConnString);
CloudBlobClient client = account.createCloudBlobClient();
container = client.getContainerReference(containerName);
container.createIfNotExists();
CloudBlockBlob cloudBlockBlob = container.getBlockBlobReference(blobName);
FileInputStream fileinputStream=new FileInputStream(filePath);
cloudBlockBlob.upload(fileinputStream, fileinputStream.available());
}catch(Exception ex) {
ex.printStackTrace();
}
}
}

我们可以通过以下地址获取 Java SDK:Java SDK

关于java - 用于 block Blob 的 Azure 存储服务 REST API : Content Length Issue,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/51256040/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com