如何使用Java App Engine将文件正确上传到Google Cloud Storage? [英] How to properly upload (image) file to Google Cloud Storage using Java App Engine?
问题描述
我有一个Google应用程序引擎实例,使用java(sdk 1.9.7),并且连接到Google Cloud Storage。我能够成功接收请求的输入并将其输出到我的谷歌云存储存储桶中的文件/对象。这里是我的servlet的代码:
$ b $ pre $ public void doPost(HttpServletRequest req,HttpServletResponse resp)throws IOException {
//读取输入流
byte [] buffer = new byte [1024];
列表< byte []> allBytes = new LinkedList< byte []>();
InputStream reader = req.getInputStream();
while(true){
int bytesRead = reader.read(buffer);
if(bytesRead == -1){
break; //与循环分离。
} else if(bytesRead< 1024){
byte [] temp = Arrays.copyOf(buffer,bytesRead);
allBytes.add(temp);
} else {
allBytes.add(buffer);
//初始化桶访问
GcsService gcsService = GcsServiceFactory.createGcsService(RetryParams.getDefaultInstance());
GcsFilename filename = new GcsFilename(my-bucket,my-file);
Builder fileOptionsBuilder = new GcsFileOptions.Builder();
fileOptionsBuilder.mimeType(text / html); //或image / jpeg用于图像文件
GcsFileOptions fileOptions = fileOptionsBuilder.build();
GcsOutputChannel outputChannel = gcsService.createOrReplace(filename,fileOptions);
//将文件写出
BufferedOutputStream outStream = new BufferedOutputStream(Channels.newOutputStream(outputChannel));
for(byte [] b:allBytes){
outStream.write(b);
}
outStream.close();
outputChannel.close();
}
当我做一个像curl POST命令的东西时,直接提供数据,如下所示:
curl --datasomeContentToBeReadhttp://myAppEngineProj.appspot.com/ myServlet
我可以看到我输入的字符串someContentToBeRead。
然而,当我放置一个文件时,像这样:
curl -F file = @picture.jpghttp://myAppEngineProj.appspot.com/myServlet
文件是完全损坏。如果我上传了一个文本文件,它在文件的开头有一行废话,最后是一行废话,比如:
------------------------------ 266cb0e18eba
Content-Disposition:form-data; NAME = 文件;文件名=blah.txt
内容类型:文本/纯文本
您好,您好吗
------------ ------------------ 266cb0e18eba--
如何告诉云存储我想将数据存储为文件?
据我所知,没有Google云端存储或API问题;问题是在阅读HttpServletRequest中的内容时更早。
包含------ 266cb0e18eba的行实际上是MIME编码的一部分,并标志着开始您可以通过以下两种方式之一来解决问题。
选项A:保持代码相同,但改变上传数据的方式
替换:
$ curl -F file = @picture.jpghttp://myAppEngineProj.appspot.com/myServlet
$
$ curl -X POST -d @picture.jpghttp:// myAppEngineProj .appspot.com / myServlet
选项B:修正Java代码并继续使用curl它取代: java.io.InputStream is = request
.getInputStream();
java.io.InputStream is = request
.getInputStream();
与:
javax.servlet.http.Part filePart = request.getPart(file);
java.io.InputStream is = filePart.getInputStream()
打开输入流在curl构建的multipart MIME消息的正确部分。
这里记录在这里:
http://docs.oracle.com/javaee/6/tutorial/doc/gmhba .html
选项B可能是更好的选择,因为它可以处理表单和表单上传。
I have a Google app engine instance, using java (sdk 1.9.7), and it is connected to Google Cloud Storage. I'm able to successfully take a request's input and output it to a file/object in my google cloud storage bucket. here's my code for my servlet:
public void doPost(HttpServletRequest req, HttpServletResponse resp) throws IOException {
// read the input stream
byte[] buffer = new byte[1024];
List<byte[]> allBytes = new LinkedList<byte[]>();
InputStream reader = req.getInputStream();
while(true) {
int bytesRead = reader.read(buffer);
if (bytesRead == -1) {
break; // have a break up with the loop.
} else if (bytesRead < 1024) {
byte[] temp = Arrays.copyOf(buffer, bytesRead);
allBytes.add(temp);
} else {
allBytes.add(buffer);
}
}
// init the bucket access
GcsService gcsService = GcsServiceFactory.createGcsService(RetryParams.getDefaultInstance());
GcsFilename filename = new GcsFilename("my-bucket", "my-file");
Builder fileOptionsBuilder = new GcsFileOptions.Builder();
fileOptionsBuilder.mimeType("text/html"); // or "image/jpeg" for image files
GcsFileOptions fileOptions = fileOptionsBuilder.build();
GcsOutputChannel outputChannel = gcsService.createOrReplace(filename, fileOptions);
// write file out
BufferedOutputStream outStream = new BufferedOutputStream(Channels.newOutputStream(outputChannel));
for (byte[] b : allBytes) {
outStream.write(b);
}
outStream.close();
outputChannel.close();
}
and when i do something like a curl POST command, this works perfectly if i just feed it data directly, like so:
curl --data "someContentToBeRead" http://myAppEngineProj.appspot.com/myServlet
and i can see the exactly string that i put in, "someContentToBeRead".
HOWEVER, when i put a file, like so:
curl -F file=@"picture.jpg" http://myAppEngineProj.appspot.com/myServlet
the file is completely corrupted. if i upload a text file, it has a line of crap in the beginning of the file, and a line of crap at the end, like:
------------------------------266cb0e18eba
Content-Disposition: form-data; name="file"; filename="blah.txt"
Content-Type: text/plain
hi how are you
------------------------------266cb0e18eba--
how do i tell cloud storage i want to store the data as file?
As far as I can tell, there is no problem with Google Cloud Storage or the APIs; the problem is earlier, in the reading of the content from HttpServletRequest.
The lines containing ------266cb0e18eba are actually part of the MIME encoding and marks the beginning and end of a part.
You can resolve the issue in one of two ways.
Option A: Keep the code the same, but change the way you upload data
Replace:
$ curl -F file=@"picture.jpg" http://myAppEngineProj.appspot.com/myServlet
With:
$ curl -X POST -d @"picture.jpg" http://myAppEngineProj.appspot.com/myServlet
Option B: Fix the Java code and continue using curl as you are using it
Replace:
java.io.InputStream is = request.getInputStream();
With:
javax.servlet.http.Part filePart = request.getPart("file");
java.io.InputStream is = filePart.getInputStream()
Which opens an input stream on the correct part in the multipart MIME message which curl constructed.
This is documented here:
http://docs.oracle.com/javaee/6/tutorial/doc/gmhba.html
Option B is probably the better option because it will work with forms and form uploads.
这篇关于如何使用Java App Engine将文件正确上传到Google Cloud Storage?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!