我正在尝试使用Google App Engine Blobstore上传文件。
它应该是这样工作的:您调用BlobstoreService以获得一个上传URL,并提供一个回调URL。客户端将重定向到上载URL,发送数据,然后在完成操作后,将使用两个代表blobstore密钥的参数将其重定向到回调URL。
我们将看到,开发服务器的行为与生产服务器不同。
针对生产,我的代码可以完成上传,然后得到一个400错误响应(暗示我的请求有问题),而不是重定向回我的回调URL。如何在生产中调试?我不知道如何打开Blobstore的日志记录。
因此,我尝试在开发服务器上本地运行它。这次,如果我未设置'content-length'属性,则会得到411(未设置内容长度)。但是,如果尝试设置该属性,则会收到“ IllegalStateException:已连接”。这些例外都不会针对生产发生。
所以我不知道下一步要去哪里。我需要让它与开发人员合作,以希望可以在本地调试blobstore,或者弄清楚为什么它不能在生产环境中的blobstore上运行。
public void upload(String uri, File file) throws IOException {
HttpURLConnection conn=null;
HttpURLConnection conn2=null;
FileInputStream fileInputStream = null;
DataOutputStream dos=null;
try {
String lineEnd = "\r\n";
String twoHyphens = "--";
String boundary = "*****";
int bytesRead, bytesAvailable, bufferSize;
byte[] buffer;
int maxBufferSize = 1 * 1024 * 1024;
// open a URL connection to the Servlet
fileInputStream = new FileInputStream(file);
URL url = new URL(uri);
// Open a HTTP connection to the URL
conn = (HttpURLConnection) url.openConnection();
conn.setDoInput(true); // Allow Inputs
conn.setDoOutput(true); // Allow Outputs
conn.setUseCaches(false); // Don't use a Cached Copy
conn.setInstanceFollowRedirects(false);
conn.setRequestMethod("POST");
conn.setRequestProperty("Connection", "Keep-Alive");
conn.setRequestProperty("ENCTYPE", "multipart/form-data");
conn.setRequestProperty("Content-Type", "multipart/form-data;boundary=" + boundary);
// conn.setChunkedStreamingMode(1024);
conn.setRequestProperty("content-length", String.valueOf(file.length())); //caused IllegalStateException "Already connected" locally, but not remotely
log("Orignal URL: " + conn.getURL());
//conn.connect(); //TODO duplicates url.openConnection() above?
conn.getInputStream(); //so we can follow the redirect
String redirectedUrl = conn.getHeaderField("Location");
log("Redirected URL: " + redirectedUrl);
//this is horrible and messy but let's get it working then clean it up later
conn.disconnect();
url = new URL(redirectedUrl);
// Open a new HTTP connection to the URL
conn2 = (HttpURLConnection) url.openConnection();
conn2.setDoInput(true); // Allow Inputs
conn2.setDoOutput(true); // Allow Outputs
conn2.setUseCaches(false); // Don't use a Cached Copy
conn2.setInstanceFollowRedirects(false);
conn2.setRequestMethod("POST");
conn2.setRequestProperty("Connection", "Keep-Alive");
conn2.setRequestProperty("ENCTYPE", "multipart/form-data");
conn2.setRequestProperty("Content-Type", "multipart/form-data;boundary=" + boundary);
conn2.setChunkedStreamingMode(maxBufferSize);
conn2.setRequestProperty("Content-Length", String.valueOf(file.length()));
conn2.connect();
dos = new DataOutputStream(conn2.getOutputStream());
dos.writeBytes(twoHyphens + boundary + lineEnd);
dos.writeBytes("Content-Disposition: form-data; name=\"myFile\";filename=\""+file.getName()+"\"" + lineEnd);
dos.writeBytes(lineEnd);
// create a buffer of maximum size
bytesAvailable = fileInputStream.available();
bufferSize = Math.min(bytesAvailable, maxBufferSize);
buffer = new byte[bufferSize];
// read file and write it into form...
bytesRead = fileInputStream.read(buffer, 0, bufferSize);
while (bytesRead > 0) {
dos.write(buffer, 0, bufferSize);
bytesAvailable = fileInputStream.available();
bufferSize = Math.min(bytesAvailable, maxBufferSize);
bytesRead = fileInputStream.read(buffer, 0, bufferSize);
}
// send multipart form data necesssary after file data...
dos.writeBytes(lineEnd);
dos.writeBytes(twoHyphens + boundary + twoHyphens + lineEnd);
// Responses from the server (code and message)
int serverResponseCode = conn2.getResponseCode();
String serverResponseMessage = conn2.getResponseMessage();
//we are expecting another redirect here
log("aaaargh! 400 instead of 302! "+serverResponseCode+" to "+conn2.getHeaderField("Location"));
}catch (IOException e) {
log(e.getMessage());
throw e;
}catch(Exception e) {
log(e.getMessage());
throw new IOException(e);
} finally {
//close the streams //
if (dos!=null) {
try {
dos.flush();
dos.close();
}catch(IOException ioe){}
}
if (fileInputStream!=null)
try {
fileInputStream.close();
}catch(IOException ioe){}
if (conn!=null )
try {
conn.disconnect();
}catch(Exception ioe){}
if (conn2!=null)
try {
conn2.disconnect();
}catch(Exception ioe){}
}
}
注意,上面的serverResponseMessage字符串从生产blobstore作为“错误请求”返回
我通过使用更高级别的API而不是我尝试使用的低级别HttpConnection代码解决了这一问题。
public String uploadFile(String url, File f) throws Exception {
HttpClient httpClient = new DefaultHttpClient();
String str = "";
HttpPost first = new HttpPost(url); //a GET should work but I was getting 405
HttpResponse firstResponse = httpClient.execute(first);
str = firstResponse.getFirstHeader("Location").getValue();
//Post image to generated url
HttpPost second = new HttpPost(str);
FileBody fileBody = new FileBody(f);
MultipartEntity reqEntity = new MultipartEntity();
reqEntity.addPart("file", fileBody);
second.setEntity(reqEntity);
httpClient = new DefaultHttpClient();
HttpResponse secondResponse = httpClient.execute(second);
str = secondResponse.getFirstHeader("Location").getValue();
log(str);
return str;
}
此方法返回上载图像的服务URL。
本文收集自互联网,转载请注明来源。
如有侵权,请联系[email protected] 删除。
我来说两句