【问题标题】:How to upload a file more that 32Mb to google cloud storage using Java API如何使用 Java API 将超过 32Mb 的文件上传到谷歌云存储
【发布时间】:2013-10-22 06:53:57
【问题描述】:

我正在努力创建一个应用程序,该应用程序将使用 java API 将苍蝇从本地机器上传到谷歌云存储。但我面临的问题是 API 不允许我上传超过 32 Mb 的文件,而我要上传的文件超过 100 Mb 或者可能是 200 Mb。 我非常感谢这方面的帮助,并想知道将文件上传到 Google Cloud Storage 的最佳做法或 API。

我正在使用以下代码。

上传文件Servlet.java

import java.io.BufferedInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.ObjectOutputStream;
import java.io.OutputStream;
import java.nio.channels.Channels;

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

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

import com.google.appengine.api.blobstore.BlobKey;
import com.google.appengine.api.users.User;
import com.google.appengine.api.users.UserService;
import com.google.appengine.api.users.UserServiceFactory;
import com.google.appengine.tools.cloudstorage.GcsFileOptions;
import com.google.appengine.tools.cloudstorage.GcsFilename;
import com.google.appengine.tools.cloudstorage.GcsOutputChannel;
import com.google.appengine.tools.cloudstorage.GcsService;
import com.google.appengine.tools.cloudstorage.GcsServiceFactory;
import com.google.appengine.tools.cloudstorage.RetryParams;
import com.igt.service.StorageService;

public class UploadFileServlet extends HttpServlet {

private static final long serialVersionUID = 1L;
private StorageService storage = new StorageService();
private static int BUFFER_SIZE = 1024 * 1024 * 10;
public static final String BUCKET_NAME = "my-bucket-test";
private final GcsService gcsService =  GcsServiceFactory.createGcsService(RetryParams.getDefaultInstance());

@Override
public void doPost(HttpServletRequest req, HttpServletResponse resp)
        throws IOException {

    UserService userService = UserServiceFactory.getUserService();
    User user = userService.getCurrentUser();

    if (user != null) {
        resp.setContentType("text/plain");
        resp.getWriter().println("Now see here your file content, that you have uploaded on storage..");

        ServletFileUpload upload = new ServletFileUpload();
        FileItemIterator iter;
        try {
            iter = upload.getItemIterator(req);
            while (iter.hasNext()) {
                FileItemStream item = iter.next();
                String fileName = item.getName();
                String mime = item.getContentType();

                GcsFileOptions options = new GcsFileOptions.Builder()
                .acl("public_read")
                .mimeType(mime)
                .build();

                GcsFilename filename = new GcsFilename(BUCKET_NAME, fileName);

                GcsOutputChannel outputChannel = gcsService.createOrReplace(filename, options);                 

                // Writing the file to input stream
                InputStream is = new BufferedInputStream(item.openStream());

                // Copying InputStream to GcsOutputChannel
                try {
                    copy(is, Channels.newOutputStream(outputChannel));
                } finally {
                    outputChannel.close();
                    is.close();
                }                                           

                resp.getWriter().println("File uploading done");
                System.out.println("File uploading done");

                // resp.getWriter().println("READ:" +
                // storage.readTextFileOnly(fileName));
                BlobKey key = storage.getBlobkey(fileName);
                if (key != null) {
                    resp.sendRedirect("/serve?blob-key=" + key.getKeyString());
                } else {
                    resp.sendRedirect("/login");
                }
                resp.sendRedirect("/login");
            }
        } catch (Exception e) {
            e.printStackTrace(resp.getWriter());
            System.out.println("Exception::" + e.getMessage());
            e.printStackTrace();
        }
    } else {
        resp.sendRedirect(userService.createLoginURL(req.getRequestURI()));
    }
}

private void copy(InputStream input, OutputStream output) throws IOException {
    byte[] buffer = new byte[BUFFER_SIZE];
    int bytesRead = input.read(buffer);
    while (bytesRead != -1) {
        output.write(buffer, 0, bytesRead);
        bytesRead = input.read(buffer);
    }
}

}

StorageService.java

import java.io.BufferedOutputStream;
import java.nio.channels.Channels;
import java.util.logging.Logger;

import com.google.appengine.api.blobstore.BlobKey;
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.FileService;
import com.google.appengine.api.files.FileServiceFactory;
import com.google.appengine.api.files.FileWriteChannel;
import com.google.appengine.api.files.GSFileOptions.GSFileOptionsBuilder;

@SuppressWarnings("deprecation")

public class StorageService {

private static final Logger log = Logger.getLogger(StorageService.class.getName());
private BlobstoreService blobstoreService = BlobstoreServiceFactory.getBlobstoreService();  


public BlobKey getBlobkey(String filename) {
    BlobKey bk = blobstoreService.createGsBlobKey("/gs/sample-bucket/"  + filename);
    return bk;
}

}

login.jsp

 <form action="/upload" method="post" enctype="multipart/form-data">

    <div><input name = "file" type="file" value="Upload" /></div>    
    <div><input type="submit" value="Upload File" /></div>
  </form>

【问题讨论】:

  • Google 云存储没有对象大小限制。我怀疑您可能遇到了每次调用 32MB 的 Blobstore 问题。您可能会发现让用户直接将对象上传到 Cloud Storage 而不是通过您的应用程序路由它很有用。请参阅stackoverflow.com/questions/11364878/… 了解更多信息。
  • @BrandonYarbrough - 感谢您的帮助。但是,认为该解决方案适用于 python,而我正在使用 java API。你能帮我解决这个问题吗?
  • 您是否尝试过使用谷歌云存储客户端? developers.google.com/appengine/docs/java/…
  • @BrandonYarbrough - 是的,我现在正在使用 Google 云存储客户端库。我面临同样的问题,无法上传超过 32 Mb 的文件。我上传了超过 32 Mb 的文件,我收到此错误:错误 413:请求实体太大您的客户端发出的请求太大。
  • @BrandonYarbrough - 根据我现在使用的 Google Cloud Storage Client 库更新代码。

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


【解决方案1】:

来自用户的单个 AppEngine 连接不能传输超过 32 MB。相反,您应该让您的用户将文件直接上传到 Google Cloud Storage。 Google Cloud Storage 支持标准 HTML 表单上传。此处提供了完整的文档:https://developers.google.com/storage/docs/reference-methods#postobject

让用户页面提交一个表单帖子,其中包含指定存储桶和对象名称的所有适当表单字段。存储桶需要可公开写入,或者您需要包含适当的签名字段。

将“success_action_redirect”字段设置为 AppEngine URL。上传成功后,浏览器会重定向到这个网址。

【讨论】:

  • 是的,如果您需要直接从表单将文件上传到 GCS,这是唯一的方法,除了在另一个没有 32MB 传输限制的服务上构建 servlet。
猜你喜欢
  • 1970-01-01
  • 2014-08-03
  • 1970-01-01
  • 2019-03-19
  • 2018-08-01
  • 2014-07-11
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多