Java 通过appengine将文件上载到Google云存储

Java 通过appengine将文件上载到Google云存储,java,google-app-engine,google-cloud-storage,google-cloud-endpoints,Java,Google App Engine,Google Cloud Storage,Google Cloud Endpoints,我正试图上传一个文件到谷歌云存储。我的Servlet代码是 public class UploadFile extends HttpServlet { private final String BUCKET = "XXXXXXXXX"; private boolean isMultipart; private String filePath; private int maxFileSize = 5 * 1024 * 1024; p

我正试图上传一个文件到谷歌云存储。我的Servlet代码是

public class UploadFile extends HttpServlet {

    private final String BUCKET = "XXXXXXXXX";
       private boolean isMultipart;
       private String filePath;
       private int maxFileSize = 5 * 1024 * 1024;
       private int maxMemSize = 5 * 1024 * 1024;
       private File file ;

       public void init( ){
          // Get the file location where it would be stored.
          filePath = 
                 getServletContext().getInitParameter("file-upload"); 
       }
       public void doPost(HttpServletRequest request, 
                   HttpServletResponse response)
                  throws ServletException, java.io.IOException {
          // Check that we have a file upload request
          isMultipart = ServletFileUpload.isMultipartContent(request);
          response.setContentType("text/html");
          java.io.PrintWriter out = response.getWriter( );
          if( !isMultipart ){
             out.println("<html>");
             out.println("<head>");
             out.println("<title>Servlet upload</title>");  
             out.println("</head>");
             out.println("<body>");
             out.println("<p>No file uploaded</p>"); 
             out.println("</body>");
             out.println("</html>");
             return;
          }
          DiskFileItemFactory factory = new DiskFileItemFactory();
          // maximum size that will be stored in memory
          factory.setSizeThreshold(maxMemSize);
          // Location to save data that is larger than maxMemSize.
          factory.setRepository(new File("/temp/image/"));

          // Create a new file upload handler
          ServletFileUpload upload = new ServletFileUpload(factory);
          // maximum file size to be uploaded.
          upload.setSizeMax( maxFileSize );

          try{ 
          // Parse the request to get file items.
          List fileItems = upload.parseRequest(request);

          // Process the uploaded file items
          Iterator i = fileItems.iterator();

          out.println("<html>");
          out.println("<head>");
          out.println("<title>Servlet upload</title>");  
          out.println("</head>");
          out.println("<body>");
          while ( i.hasNext () ) 
          {
             FileItem fi = (FileItem)i.next();
             if ( !fi.isFormField () )  
             {
                // Get the uploaded file parameters
                String fieldName = fi.getFieldName();
                String fileName = fi.getName();
                String contentType = fi.getContentType();
                boolean isInMemory = fi.isInMemory();
                long sizeInBytes = fi.getSize();
                // Write the file
                if( fileName.lastIndexOf("\\") >= 0 ){
                   file = new File( filePath + 
                   fileName.substring( fileName.lastIndexOf("\\"))) ;
                }else{
                   file = new File( filePath + 
                   fileName.substring(fileName.lastIndexOf("\\")+1)) ;
                }

               String path = Events.uploadFile ( fileName, "image/*", file, BUCKET );

                // fi.write( file ) ;
                out.println("Uploaded Filename: " + fileName + "<br>"+ " File Path:"+ path);
             }
          }
          out.println("</body>");
          out.println("</html>");
       }catch(Exception ex) {
           System.out.println(ex);
       }
       }
       public void doGet(HttpServletRequest request, 
                           HttpServletResponse response)
            throws ServletException, java.io.IOException {

            throw new ServletException("GET method used with " +
                    getClass( ).getName( )+": POST method required.");
       } 
    }
但当我尝试用一些API测试客户机测试时,它给出了错误

org.apache.commons.fileupload.FileUploadException: the request was rejected because no multipart boundary was found
在将它与处于Angular模式的UI集成并在本地对其进行测试之后,我面临着这个问题

Cross-Origin Request Blocked Reason: CORS header 'Access-Control-Allow-Origin' missing
我试图解决这个问题,但没有找到与谷歌appengine对应的解决方案


最初,我试图通过这段代码上传一张图片,但在不久的将来,同样的代码将被用来上传.pdf和.html文件到GCS

供参考: 我正在使用Google端点来满足与客户端的其他数据通信需求。客户端是一个内置的webapp,但它将扩展到android和ios

任何帮助都将不胜感激

多谢各位

更新日期:2016年1月8日

现在我正在服务器上获取文件,但我不知道在将文件发送到谷歌云存储之前,我必须在哪里临时保存该文件。论文件的存储

war\WEB-INI\
我面临的例外是

 java.security.AccessControlException: access denied ("java.io.FilePermission" "\war\WEB-INI\profile.png" "read")

首先,您需要解决飞行前请求处理中的CORS问题,您需要在后端执行此操作:在Google App Engine上,通过添加
doOptions
方法执行此操作,如:

@Override
protected void doOptions(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException 
{ 
    resp.setHeader("Access-Control-Allow-Origin", "*");
    resp.setHeader("Access-Control-Allow-Methods", "*");
    resp.setHeader("Access-Control-Allow-Headers", "Origin, X-Requested-With, Content-Type, Accept");
}
然后,您需要确保发送的请求带有标题,如
内容类型:multipart/form data
,否则您的文件将被错误编码。在angular2中,请求头被设置为post请求中的第三个(可选)参数,如:

let headers = new Headers();
headers.append('content-type', 'multipart/form-data');
http.post(url, body, {
                  headers:headers
                })

很抱歉,这并没有直接解决你的问题,但我还是想指出这一点。我建议您使用一个普通端点生成一个临时上传URL,您的Angular客户端可以使用该URL将文件直接发送到云存储,而无需通过您的应用程序。实现这一点的一种方法是通过blobstoreapi,如前所述。您可以通过该API上传到云存储,如前所述(在同一页的后面)


这减少了您在服务器上需要的上传代码量,不受GAE请求32MB限制的限制,并且符合Google的建议(如上面的文档链接所示)。

最后,我可以通过appengine将文件从客户端上传到Google云存储

我假设在执行这些步骤之前,您已经准备好了以下内容

  • 服务帐户中的JSON文件
  • 创建了一个默认的bucket
第1步:制作一个如下的Servlet

package XXXXXXXXX;

import java.io.IOException;
import java.io.InputStream;
import java.security.GeneralSecurityException;
import java.util.Arrays;

import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import com.google.api.client.http.InputStreamContent;
import com.google.api.services.storage.Storage;
import com.google.api.services.storage.model.ObjectAccessControl;
import com.google.api.services.storage.model.StorageObject;

import XXXXXXXXXXXXX.StorageFactory;

//@author Umesh Chauhan

/**
 * Save File to GCS
 *
 * @param fileName        File Name with format
 * @header Content-Type   "*/*"
 * @return file path
 * @throws Exception      Any Error during upload
 */
public class UploadFile extends HttpServlet
{

    private static final long serialVersionUID = 1L;
    private final String BUCKET = "YOUR BUCKET NAME";
    private int maxFileSize = 6 * 1024 * 1024;

    @Override
    protected void doOptions ( HttpServletRequest req, HttpServletResponse resp ) throws ServletException, IOException
    {
        // pre-flight request processing
        resp.setHeader ( "Access-Control-Allow-Origin", "*" );
        resp.setHeader ( "Access-Control-Allow-Methods", "*" );
        resp.setHeader ( "Access-Control-Allow-Headers", "Origin, X-Requested-With, Content-Type, Accept" );
    }

    @Override
    public void doPost ( HttpServletRequest request, HttpServletResponse response )
            throws ServletException, java.io.IOException
    {

        try
        {
            String path = uploadFile ( request.getParameter ( "fileName" ), request.getContentType (),
                    request.getInputStream (), BUCKET, request.getInputStream ().available () );
            // Sending Response
            response.setStatus ( HttpServletResponse.SC_OK );
            response.getWriter ().write ( path );
            response.getWriter ().flush ();
            response.getWriter ().close ();

        }
        catch ( GeneralSecurityException e )
        {
            e.printStackTrace ();
        }
    }

    public String uploadFile ( String name, String contentType, InputStream input, String bucketName,
            int contentLength ) throws IOException, GeneralSecurityException
    {

        InputStreamContent contentStream = new InputStreamContent ( contentType, input );

        if ( contentLength < maxFileSize )
        {

            // It is done Automatically.
            /*
             * // Setting the length improves upload performance
             * contentStream.setLength ( contentLength );
             */

            StorageObject objectMetadata = new StorageObject ()
                    // Set the destination object name
                    .setName ( name )
                    // Set the access control list to publicly read-only
                    .setAcl ( Arrays.asList (
                            new ObjectAccessControl ().setEntity ( "allUsers" ).setRole ( "READER" ) ) );

            // Do the insert
            Storage client = StorageFactory.getService ();

            Storage.Objects.Insert insertRequest = client.objects ()
                    .insert ( bucketName, objectMetadata, contentStream );

            insertRequest.execute ();

            return "https://storage.cloud.google.com/" + BUCKET + "/" + name;
        }
        else
        {
            throw new GeneralSecurityException ( "File size canot be more then 6 MB !" );
        }
    }

    public void doGet ( HttpServletRequest request, HttpServletResponse response )
            throws ServletException, java.io.IOException
    {
        throw new ServletException ( "GET method used with " + getClass ().getName () + ": POST method required." );
    }

}

下面是根据

您将找到完整的代码

使用

  • 在appengine上运行时-无需身份验证
  • 在本地运行时,运行
    gcloud auth应用程序默认登录
    命令 看


“这里是您的服务帐户JSON的URL-我使用了指向我的JSON文件的GOOGLE DRIVE直接下载链接”我如何生成服务帐户JSON?你能举一个结构的例子吗?@user5980143你必须从谷歌控制台下载它。如果我已经在谷歌应用程序引擎中运行,我不需要“GoogleCreditial”对吗?这是100%正确的方法,最初的问题说他的应用程序正在“谷歌应用程序引擎”中运行!“我发布了另一个选项,
com.google.cloud.storage
库比
com.google.appengine
let headers = new Headers();
headers.append('content-type', 'multipart/form-data');
http.post(url, body, {
                  headers:headers
                })
package XXXXXXXXX;

import java.io.IOException;
import java.io.InputStream;
import java.security.GeneralSecurityException;
import java.util.Arrays;

import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import com.google.api.client.http.InputStreamContent;
import com.google.api.services.storage.Storage;
import com.google.api.services.storage.model.ObjectAccessControl;
import com.google.api.services.storage.model.StorageObject;

import XXXXXXXXXXXXX.StorageFactory;

//@author Umesh Chauhan

/**
 * Save File to GCS
 *
 * @param fileName        File Name with format
 * @header Content-Type   "*/*"
 * @return file path
 * @throws Exception      Any Error during upload
 */
public class UploadFile extends HttpServlet
{

    private static final long serialVersionUID = 1L;
    private final String BUCKET = "YOUR BUCKET NAME";
    private int maxFileSize = 6 * 1024 * 1024;

    @Override
    protected void doOptions ( HttpServletRequest req, HttpServletResponse resp ) throws ServletException, IOException
    {
        // pre-flight request processing
        resp.setHeader ( "Access-Control-Allow-Origin", "*" );
        resp.setHeader ( "Access-Control-Allow-Methods", "*" );
        resp.setHeader ( "Access-Control-Allow-Headers", "Origin, X-Requested-With, Content-Type, Accept" );
    }

    @Override
    public void doPost ( HttpServletRequest request, HttpServletResponse response )
            throws ServletException, java.io.IOException
    {

        try
        {
            String path = uploadFile ( request.getParameter ( "fileName" ), request.getContentType (),
                    request.getInputStream (), BUCKET, request.getInputStream ().available () );
            // Sending Response
            response.setStatus ( HttpServletResponse.SC_OK );
            response.getWriter ().write ( path );
            response.getWriter ().flush ();
            response.getWriter ().close ();

        }
        catch ( GeneralSecurityException e )
        {
            e.printStackTrace ();
        }
    }

    public String uploadFile ( String name, String contentType, InputStream input, String bucketName,
            int contentLength ) throws IOException, GeneralSecurityException
    {

        InputStreamContent contentStream = new InputStreamContent ( contentType, input );

        if ( contentLength < maxFileSize )
        {

            // It is done Automatically.
            /*
             * // Setting the length improves upload performance
             * contentStream.setLength ( contentLength );
             */

            StorageObject objectMetadata = new StorageObject ()
                    // Set the destination object name
                    .setName ( name )
                    // Set the access control list to publicly read-only
                    .setAcl ( Arrays.asList (
                            new ObjectAccessControl ().setEntity ( "allUsers" ).setRole ( "READER" ) ) );

            // Do the insert
            Storage client = StorageFactory.getService ();

            Storage.Objects.Insert insertRequest = client.objects ()
                    .insert ( bucketName, objectMetadata, contentStream );

            insertRequest.execute ();

            return "https://storage.cloud.google.com/" + BUCKET + "/" + name;
        }
        else
        {
            throw new GeneralSecurityException ( "File size canot be more then 6 MB !" );
        }
    }

    public void doGet ( HttpServletRequest request, HttpServletResponse response )
            throws ServletException, java.io.IOException
    {
        throw new ServletException ( "GET method used with " + getClass ().getName () + ": POST method required." );
    }

}
package XXXXXXXXXXXX;

import java.io.IOException;
import java.net.URL;
import java.security.GeneralSecurityException;
import java.util.Collection;

import com.google.api.client.googleapis.auth.oauth2.GoogleCredential;
import com.google.api.client.googleapis.javanet.GoogleNetHttpTransport;
import com.google.api.client.http.HttpTransport;
import com.google.api.client.json.JsonFactory;
import com.google.api.client.json.jackson2.JacksonFactory;
import com.google.api.services.storage.Storage;
import com.google.api.services.storage.StorageScopes;

//@author Umesh Chauhan 

public class StorageFactory
{

    private static Storage instance = null;

    public static synchronized Storage getService () throws IOException, GeneralSecurityException
    {
        if ( instance == null )
        {
            instance = buildService ();
        }
        return instance;
    }

    private static Storage buildService () throws IOException, GeneralSecurityException
    {

        HttpTransport transport = GoogleNetHttpTransport.newTrustedTransport ();
        JsonFactory jsonFactory = new JacksonFactory ();

        GoogleCredential credential = GoogleCredential.fromStream (
                new URL ( "HERE GOES THE URL FOR YOUR SERVICE ACCOUNT JSON - I USED GOOGLE DRIVE DIRECT DOWNLOAD LINK TO MY JSON FILE" )
                        .openStream () );

        // Depending on the environment that provides the default credentials
        // (for
        // example: Compute Engine, App Engine), the credentials may require us
        // to
        // specify the scopes we need explicitly. Check for this case, and
        // inject
        // the Cloud Storage scope if required.
        if ( credential.createScopedRequired () )
        {
            Collection<String> scopes = StorageScopes.all ();
            credential = credential.createScoped ( scopes );
        }

        return new Storage.Builder ( transport, jsonFactory, credential ).setApplicationName ( "YOUR PROJECT NAME" ).build ();
    }
}
    <servlet>
        <servlet-name>UploadFile</servlet-name>
        <servlet-class>PACKAGE.UploadFile</servlet-class>
    </servlet>

    <servlet-mapping>
        <servlet-name>UploadFile</servlet-name>
        <url-pattern>/uploadManager/UploadFile</url-pattern>  //Based on your original URL
    </servlet-mapping>
import com.google.appengine.tools.cloudstorage.*;

public void doPost(HttpServletRequest req, HttpServletResponse resp) throws IOException {
  String buffer = "the data to be saved in GCS bla bla";
  GcsFileOptions instance = GcsFileOptions.getDefaultInstance();
  GcsFilename fileName = new GcsFilename("bucketName", "fileName");
  GcsOutputChannel outputChannel;
  gcsService.createOrReplace(fileName, instance, ByteBuffer.wrap(buffer.getBytes()));
}
import com.google.cloud.storage.*;


public static void upload(String bucketName, String fileId, String content) throws IOException {
    Storage storage = StorageOptions.newBuilder().build().getService();

    BlobInfo fileInfo = BlobInfo.newBuilder(bucketName, fileId)
            .build();

    InputStream fileIS = IOUtils.toInputStream(content, "UTF-8");
    storage.create(fileInfo, fileIS);

}