GAE上传文件POST请求(URLConnection) - 错误:上传的文件仅部分上传

时间:2013-02-26 17:17:09

标签: java google-app-engine google-cloud-storage

我尝试使用GAE从blobstore上传文件到服务器(127.0.0.1),但接收服务器给我错误“上传的文件只是部分上传”。 我还在请求中发送了一个参数,服务器正确接收了该参数。

String url = "http://127.0.0.1/";
String charset = "UTF-8";

FileService fileService = FileServiceFactory.getFileService();
AppEngineFile appEngineFile = fileService.getBlobFile(new BlobKey("blob key"));

String param = "my param";
File binaryFile = new File(appEngineFile.getFullPath());
String boundary = Long.toHexString(System.currentTimeMillis()); // Just generate some unique random value.
String CRLF = "\r\n"; // Line separator required by multipart/form-data.

URLConnection connection = new URL(url).openConnection();
connection.setDoOutput(true);
connection.setRequestProperty("Content-Type", "multipart/form-data; boundary=" + boundary);
PrintWriter writer = null;
try {
    OutputStream output = connection.getOutputStream();
    writer = new PrintWriter(new OutputStreamWriter(output, charset), true); // true = autoFlush, important!

    // Send normal param.
    writer.append("--" + boundary).append(CRLF);
    writer.append("Content-Disposition: form-data; name=\"api_password\"").append(CRLF);
    writer.append("Content-Type: text/plain; charset=" + charset).append(CRLF);
    writer.append(CRLF);
    writer.append(param).append(CRLF).flush();

    // Send binary file.
    writer.append("--" + boundary).append(CRLF);
    writer.append("Content-Disposition: form-data; name=\"file\"; filename=\"" + binaryFile.getName() + "\"").append(CRLF);
    writer.append("Content-Type: application/octet-stream").append(CRLF);
    writer.append("Content-Transfer-Encoding: binary").append(CRLF);
    writer.append(CRLF).flush();
    InputStream input = null;
    try {

    BlobInfoFactory blobInfoFactory = new BlobInfoFactory();
    BlobInfo blobInfo = blobInfoFactory.loadBlobInfo(new BlobKey("blob key"));
    Long blobSize = blobInfo.getSize();
    ByteArrayOutputStream buffer = new ByteArrayOutputStream();

    //max read on fetch
    long maxReadFetch = 1015807;

    //read the file in one time temporary
    long i = 0;
    long start = 0;
    long end = 0;
    while(i < blobSize) {

    start = i;
    end = i + maxReadFetch;
    //determine end
    if(end > blobSize) {
    end = blobSize;
    }
    buffer.write(blobstoreService.fetchData(new BlobKey("blob key"), start, end));
    i += maxReadFetch;

    }

    output.write(buffer.toByteArray());

        output.flush(); // Important! Output cannot be closed. Close of writer will close output as well.

    } finally {
        if (input != null) try { input.close(); } catch (IOException logOrIgnore) {}
    }
    writer.append(CRLF).flush(); // CRLF is important! It indicates end of binary boundary.

    // End of multipart/form-data.
    writer.append("--" + boundary + "--").append(CRLF);


    //resp part
InputStream responseStream = new BufferedInputStream(connection.getInputStream());

BufferedReader responseStreamReader = new BufferedReader(new InputStreamReader(responseStream));

StringBuilder stringBuilder = new StringBuilder();
String line2;
while ((line2 = responseStreamReader.readLine()) != null)
{
    stringBuilder.append(line2).append("\n");
}
responseStreamReader.close();

String response = stringBuilder.toString();
resp.getWriter().write(response);
} finally {
    if (writer != null) writer.close();
}

2 个答案:

答案 0 :(得分:0)

由于错误“上传的文件只是部分上传”是取消上传的结果,我认为您的GAE请求会在writer.append("--" + boundary + "--").append(CRLF);发生之前从30秒的执行限制或异常中止。可能输出日志语句以查看代码停止的位置。

答案 1 :(得分:0)

所以我在这里修复它是我的解决方案

FileService fileService = FileServiceFactory.getFileService();
AppEngineFile appEngineFile = fileService.getBlobFile(new BlobKey(video.getBlobkey()));

String param = "4166764c675120921f348e64ca10148e8ff6d5df";
File binaryFile = new File(appEngineFile.getFullPath());
String boundary = Long.toHexString(System.currentTimeMillis()); // Just generate some unique random value.
String CRLF = "\r\n"; // Line separator required by multipart/form-data.

URLConnection connection = new URL(url).openConnection();
connection.setDoOutput(true);
connection.setRequestProperty("Content-Type", "multipart/form-data; boundary=" + boundary);
BufferedOutputStream writer = null;

OutputStream output = connection.getOutputStream();
writer = new BufferedOutputStream(output); // true = autoFlush, important!

// Send normal param.
writer.write(("--" + boundary + CRLF).getBytes());
writer.write(("Content-Disposition: form-data; name=\"api_password\"" + CRLF).getBytes());
writer.write(("Content-Type: text/plain; charset=" + charset + CRLF).getBytes());
writer.write((CRLF).getBytes());
writer.write((param + CRLF).getBytes());
writer.flush();

// Send binary file.
writer.write(("--" + boundary + CRLF).getBytes());
writer.write(("Content-Disposition: form-data; name=\"file\"; filename=\"" + binaryFile.getName() + "\"" + CRLF).getBytes());
writer.write(("Content-Type: application/octet-stream" + CRLF).getBytes());
writer.write(("Content-Transfer-Encoding: binary" + CRLF).getBytes());
writer.write((CRLF).getBytes());
writer.flush();
InputStream input = null;
try {

    BlobInfoFactory blobInfoFactory = new BlobInfoFactory();
    BlobInfo blobInfo = blobInfoFactory.loadBlobInfo(new BlobKey(video.getBlobkey()));
    Long blobSize = blobInfo.getSize();

    //max read on fetch
    long maxReadFetch = 1015807;

    //read the file in one time temporary
    long i = 0;
    long start = 0;
    long end = 0;
    while(i < blobSize) {

        start = i;
        end = i + maxReadFetch;
        //determine end
        if(end > blobSize) {
            end = blobSize;
        } else {
            end--;
        }
        writer.write(blobstoreService.fetchData(new BlobKey(video.getBlobkey()), start, end));
        i += maxReadFetch;

    }

    writer.flush(); // Important! Output cannot be closed. Close of writer will close output as well.

} finally {
    if (input != null) try { input.close(); } catch (IOException logOrIgnore) {}
}
writer.write((CRLF).getBytes());
writer.flush(); // CRLF is important! It indicates end of binary boundary.

// End of multipart/form-data.
writer.write(("--" + boundary + "--" + CRLF).getBytes());
writer.flush();

//response part
InputStream responseStream = new BufferedInputStream(connection.getInputStream());

BufferedReader responseStreamReader = new BufferedReader(new InputStreamReader(responseStream));

StringBuilder stringBuilder = new StringBuilder();
String line2;
while ((line2 = responseStreamReader.readLine()) != null)
{
    stringBuilder.append(line2).append("\n");
}
responseStreamReader.close();

String response = stringBuilder.toString(); //JSON data
return response;