2012-06-08 31 views
4

我知道我可以使用多部分/表單POST請求一次將1個文件上傳到AppEngine。 AppEngine也支持uploading multiple files,但你必須做一些hokey JSP的東西來使它工作。從1個請求中將多個文件從Android上傳到AppEngine

我有一個應用程序需要我上傳一些表單數據,2個圖像和3個字段的文本。這可能通過AppEngine完成嗎?我一直在試圖找到有關這方面的信息,但它很難與我需要的靈活性一起工作。我將把數據存儲在blob存儲/數據存儲中。

我需要一個Java解決方案。

這是我的POST方法的簽名:

import javax.ws.rs.Consumes; 
import javax.ws.rs.POST; 

@POST 
@Consumes(MediaType.MULTIPART_FORM_DATA) 
public void post(
     @Context HttpServletRequest request, 
     @Context HttpServletResponse response) 
     throws FileUploadException, IOException {} 

複製了Java Servlet的貼,如果你真的需要它。以上是問題和相關的servlet片段。

import java.io.BufferedReader; 
import java.io.IOException; 
import java.nio.ByteBuffer; 
import java.nio.channels.Channels; 
import java.util.Iterator; 

import javax.servlet.http.HttpServletRequest; 
import javax.servlet.http.HttpServletResponse; 
import javax.ws.rs.Consumes; 
import javax.ws.rs.POST; 
import javax.ws.rs.Path; 
import javax.ws.rs.core.Context; 
import javax.ws.rs.core.MediaType; 

import org.apache.commons.fileupload.FileItemHeaders; 
import org.apache.commons.fileupload.FileItemIterator; 
import org.apache.commons.fileupload.FileItemStream; 
import org.apache.commons.fileupload.FileUploadException; 
import org.apache.commons.fileupload.servlet.ServletFileUpload; 

import com.google.appengine.api.blobstore.BlobstoreService; 
import com.google.appengine.api.blobstore.BlobstoreServiceFactory; 
import com.google.appengine.api.files.AppEngineFile; 
import com.google.appengine.api.files.FileReadChannel; 
import com.google.appengine.api.files.FileService; 
import com.google.appengine.api.files.FileServiceFactory; 
import com.google.appengine.api.files.FileWriteChannel; 

@Path("/upload") 
public class FileUploadServlet { 

    private BlobstoreService blobstoreService = BlobstoreServiceFactory 
      .getBlobstoreService(); 

    @POST 
    @Consumes(MediaType.MULTIPART_FORM_DATA) 
    public void post(@Context HttpServletRequest request, 
      @Context HttpServletResponse response) throws FileUploadException, 
      IOException { 

     final ServletFileUpload upload = new ServletFileUpload(); 
     final FileItemIterator fileIter = upload.getItemIterator(request); 

     while (fileIter.hasNext()) { 
      final FileItemStream item = fileIter.next(); 
      String name = item.getName(); 
      String fieldName = item.getFieldName(); 
      String contentType = item.getContentType(); 
      Log.d("Name = " + name); 
      Log.d("Field-Name = " + fieldName); 
      Log.d("Content-Type = " + contentType); 
      FileItemHeaders headers = item.getHeaders(); 
      if(headers != null) { 
       Iterator<String> it = (Iterator<String>)headers.getHeaderNames(); 
       while(it.hasNext()) { 
        String h = it.next(); 
        Log.d(h + " = " + headers.getHeader(h)); 
       } 
      } 
      if (item.isFormField()) { 
       // Nothing 
      } else { 
       RawImageData data = new RawImageData(); 
       data.load(item.openStream()); 
          // RawImageData reads the stream and stores it into a large byte[] called data.imageData 
       ByteBuffer bb = ByteBuffer.wrap(data.imageData); 
       FileService fs = FileServiceFactory.getFileService(); 
       AppEngineFile file = fs.createNewBlobFile(contentType); 
       FileWriteChannel write = fs.openWriteChannel(file, true); 

       write.write(bb); 
       write.closeFinally(); 
       String path = file.getFullPath(); 
       Log.d(path); 

       // Later, read from the file using the file API 
       boolean lock = false; // Let other people read at the same time 
       FileReadChannel readChannel = fs.openReadChannel(file, 
         false); 
          // CRASHES WITH java.nio.charset.IllegalCharsetNameException: image/jpeg 
          // contentType = "image/jpeg" 
       // Again, different standard Java ways of reading from the 
       // channel. 
       BufferedReader reader = new BufferedReader(Channels.newReader(readChannel, contentType)); 

       readChannel.close(); 
      } 
     } 

     response.setContentType("text/html"); 
     response.getOutputStream().write("success".getBytes()); 
    } 
} 

完全例外:

WARNING: /api/upload 
java.nio.charset.IllegalCharsetNameException: image/jpeg 
    at java.nio.charset.Charset.checkName(Charset.java:284) 
    at java.nio.charset.Charset.lookup2(Charset.java:458) 
    at java.nio.charset.Charset.lookup(Charset.java:437) 
    at java.nio.charset.Charset.forName(Charset.java:502) 
    at java.nio.channels.Channels.newReader(Channels.java:381) 
    at com.futonredemption.starstarstar.FileUploadServlet.post(FileUploadServlet.java:96) 
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) 
    blah blah blah 
+0

你需要做什麼才能一次上傳多個文件? –

+0

」method =「post」enctype =「multipart/form-data」>對我來說很可笑 –

回答

2

你可以創建你自己的multipart file upload handler,然後通過Blobstore FileService API保存文件。

+0

謝謝我認爲這是對的跟蹤。將圖像數據寫入Blobstore時,我的應用程序仍然崩潰。它崩潰java.nio.charset.IllegalCharsetNameException:image/jpeg。我把contentType放到頻道中。它不喜歡它。 NIO對我來說看起來很奇怪。 –

+0

圖像是一個字節流,然而你試圖把它作爲字符流讀取('Reader'用於讀取字符流 - 它需要一個字節流並將其解碼爲具有給定編碼的字符流)。你應該使用'Channels.newInputStream(..)'。 –

相關問題