如何从Android发送图像数据到服务器

mst*_*ath 4 google-app-engine android

我正在尝试编写一个Android应用程序,它将拍摄照片,将数据(byte [])与一些元数据放在一个对象中,并将其发布到AppEngine服务器,在那里它将作为blob保存在数据存储区中.我真的不想将图像保存为Android上的文件(除非绝对必要).我四处寻找解决方案,但没有任何明确或具体的解决方案.我的问题是:

  1. 如何将对象发布到我的servlet?具体来说,如何正确序列化对象并获取序列化输出到HttpPost或类似的东西.
  2. 一旦我将blob保留在数据存储区中,我将如何将其作为要在网页上显示的图像进行检索?

代码示例非常有用.此外,如果我采取的方法太复杂或有问题,请建议其他方法(例如将图像保存为文件,发布到服务器,然后删除).

ste*_*ert 8

您只需要在POST的特殊情况下执行Http-FileUpload.无需对文件进行uuencode.无需使用特殊的lib/jar无需将对象保存到磁盘(无论以下示例是这样做的)

您可以找到关于Http-Command的非常好的解释,并作为您特别关注的"文件上传"

使用java.net.URLConnection来触发和处理HTTP请求

随后是文件上传样本(观看"发送二进制文件"),也可以添加一些伴随数据


String param = "value";
File textFile = new File("/path/to/file.txt");
File binaryFile = new File("/path/to/file.bin");
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=\"param\"").append(CRLF);
    writer.append("Content-Type: text/plain; charset=" + charset).append(CRLF);
    writer.append(CRLF);
    writer.append(param).append(CRLF).flush();

    // Send text file.
    writer.append("--" + boundary).append(CRLF);
    writer.append("Content-Disposition: form-data; name=\"textFile\"; filename=\"" + textFile.getName() + "\"").append(CRLF);
    writer.append("Content-Type: text/plain; charset=" + charset).append(CRLF);
    writer.append(CRLF).flush();
    BufferedReader reader = null;
    try {
        reader = new BufferedReader(new InputStreamReader(new FileInputStream(textFile), charset));
        for (String line; (line = reader.readLine()) != null;) {
            writer.append(line).append(CRLF);
        }
    } finally {
        if (reader != null) try { reader.close(); } catch (IOException logOrIgnore) {}
    }
    writer.flush();

    // Send binary file.
    writer.append("--" + boundary).append(CRLF);
    writer.append("Content-Disposition: form-data; name=\"binaryFile\"; filename=\"" + binaryFile.getName() + "\"").append(CRLF);
    writer.append("Content-Type: " +     URLConnection.guessContentTypeFromName(binaryFile.getName()).append(CRLF);
    writer.append("Content-Transfer-Encoding: binary").append(CRLF);
    writer.append(CRLF).flush();
    InputStream input = null;
    try {
        input = new FileInputStream(binaryFile);
        byte[] buffer = new byte[1024];
        for (int length = 0; (length = input.read(buffer)) > 0;) {
            output.write(buffer, 0, length);
        }
        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);
} finally {
    if (writer != null) writer.close();
}
Run Code Online (Sandbox Code Playgroud)

关于你问题的第二部分.成功上传文件(我使用apache常用文件)后,将blob作为图像传递并不是什么大问题.

这是如何接受servlet中的文件

public void doPost(HttpServletRequest pRequest, HttpServletResponse pResponse)
        throws ServletException, IOException {
    ServletFileUpload upload = new ServletFileUpload();

    try {
        FileItemIterator iter = upload.getItemIterator (pRequest);

        while (iter.hasNext()) {
            FileItemStream item = iter.next();

            String fieldName = item.getFieldName();

                InputStream stream = item.openStream();
            ....
                stream.close();
            }
    ...
Run Code Online (Sandbox Code Playgroud)

这段代码提供了一个图像

public void doGet (HttpServletRequest pRequest, HttpServletResponse pResponse)  throws IOException {

    try {
        Blob img = (Blob) entity.getProperty(propImg);

        pResponse.addHeader ("Content-Disposition", "attachment; filename=abc.png");
        pResponse.addHeader ("Cache-Control", "max-age=120");

        String enc = "image/png";
        pResponse.setContentType (enc);
        pResponse.setContentLength (img.getBytes().length);
        OutputStream out = pResponse.getOutputStream ();
        out.write (img.getBytes());
        out.close();
Run Code Online (Sandbox Code Playgroud)

我希望这段代码片段有助于回答您的问题


Roh*_*han 6

1.您可以使用以下方法将byte []编码为base64:

http://commons.apache.org/codec/apidocs/org/apache/commons/codec/binary/Base64.html

2.使用HTTP POST请求向AppEngine servlet发送该数据.

3.配置AppEngine以接受servlet.

4.然后您可以选择将其保存到数据存储区或Blobstore. - 我喜欢blobstore这些东西.

5.解码base64字符串服务器端.

6.从那里你需要将你的字符串剪成更小的片段并将每个片段写入blobstore.

这是将其写入blobstore的一些代码.

byte[] finalImageArray = null;

    try {
        finalImageArray = Base64.decode(finalImageData.getBytes()); //finalImageData is the string retrieved from the HTTP POST
    } catch (Base64DecoderException e1) {
        // TODO Auto-generated catch block
        e1.printStackTrace();
    }


    try{
        FileService fileService = FileServiceFactory.getFileService();

        AppEngineFile file = fileService.createNewBlobFile("image/png");

        FileWriteChannel writeChannel = fileService.openWriteChannel(file, true);

        int steps = (int) Math.floor(finalImageArray.length/1000);
        int current = 0;
        for(int i = 0; i < 1000; i++){
            writeChannel.write(ByteBuffer.wrap(Arrays.copyOfRange(finalImageArray, current, steps+current)));
            current = current + steps;
        }
        writeChannel.write(ByteBuffer.wrap(Arrays.copyOfRange(finalImageArray, current, finalImageArray.length)));  //The reason it's cut up like this is because you can't write the complete string in one go.

        writeChannel.closeFinally();

        blobKey = fileService.getBlobKey(file);

        if(blobKey == null)
            blobKey = retryBloBKey(file); //My own method, AppEngine tends to not return the blobKey once a while.

    }
    catch(Exception e){
        logger.log(Level.SEVERE,e.getMessage());
    }


            return blobKey.getKeyString();
Run Code Online (Sandbox Code Playgroud)
  1. 编写一个servlet,使用提供的密钥检索图像数据.

  2. 享受你美丽的代码:)

//我将其保存为二进制文件的原因是因为它为我提供了使用图像api的选项,您还可以选择将其保存为base64格式.

  • 没有理由在base64中对数据进行编码,除非你真的想浪费空间并让事情变慢.您可以直接将二进制文件(例如图像)上传到blobstore或您的应用程序代码. (2认同)