通过appengine将文件上传到Google云端存储
我试图将文件上传到Google云端存储。我的servlet代码是通过appengine将文件上传到Google云端存储
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.");
}
}
的web.xml
<servlet>
<servlet-name>UploadFile</servlet-name>
<servlet-class>XXXXXXXXXX.UploadFile</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>UploadFile</servlet-name>
<url-pattern>/uploadManager/UploadFile</url-pattern> //Based on your original URL
</servlet-mapping>
文件上传功能,文件保存到GCS
public static String uploadFile (String name, String contentType, File file, String bucketName)
throws IOException, GeneralSecurityException
{
InputStreamContent contentStream = new InputStreamContent (contentType, new FileInputStream (file));
// Setting the length improves upload performance
contentStream.setLength (file.length());
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 + "/" + file.getName();
}
但是当我尝试了一些API测试客户端来测试这个提示错误
org.apache.commons.fileupload.FileUploadException: the request was rejected because no multipart boundary was found
Furt她与UI这是在角整合,并在本地测试之后,我面临这个问题
Cross-Origin Request Blocked Reason: CORS header 'Access-Control-Allow-Origin' missing
我试图解决这个问题,但发现相当于谷歌AppEngine上无解。
最初我试图通过这个代码,但在不久的将来,同样的代码上传图像将被用来.pdf和.html文件上传到GCS。
仅供参考: 我正在使用Google Endpoints来满足客户端的其他数据通信需求。客户端是一个在Angular中构建的webapp,但它将被扩展到android和ios。
任何帮助将不胜感激。
谢谢
UPDATE 2016年1月8日
现在我得到的服务器上的文件,但我不知道我要的文件临时保存它发送到谷歌云存储前。在
war\WEB-INI\
和我面临的例外存储文件
java.security.AccessControlException: access denied ("java.io.FilePermission" "\war\WEB-INI\profile.png" "read")
最后我能够通过AppEngine上上传从客户端文件到谷歌云存储。
我认为在执行这些步骤之前,你有以下的东西准备好
- JSON文件从您的服务帐户。
- 创建一个默认的水桶。
第1步:制作这样
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.");
}
}
第二步一个Servlet:存储厂
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();
}
}
第3步:更新你web.xml
<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>
首先,你需要在飞行前请求处理解决CORS问题,你需要做的是在后端:在谷歌应用程序引擎它通过增加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");
}
,那么你需要确保你发送你喜欢Content-Type: multipart/form-data
头请求,否则你的文件的Wi会被错误地编码。在angular2请求头在你的岗位要求如设置为第三个参数(可选):
let headers = new Headers();
headers.append('content-type', 'multipart/form-data');
http.post(url, body, {
headers:headers
})
这里是根据上传到存储的正确方法
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()));
}
,你会发现完整的代码here
这是100%正确的方式做到这一点,原来的问题说他的应用程序运行在'谷歌应用程序引擎!“ –
我张贴另一个选项https://stackoverflow.com/questions/38590971/ upload-file-to-google-cloud-storage-via-appengine/47546249?s = 4 | 31.2540#47546249 com.google.cloud.storage库比'com.google.appengine' – dina
- AppEngine上运行时 - 无需认证
-
在本地运行时运行
gcloud auth application-default login
命令 看到authenticationimport 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); }
“这里是你的服务帐户JSON的URL - 我使用GOOGLE DRIVE直接下载链接到我的JSON文件”如何生成服务帐户JSON?你能举一个结构的例子吗? – dina
@ user5980143你必须从谷歌控制台下载它。 –
如果我已经在谷歌应用程序引擎中运行,我不需要“GoogleCreditial”权限? –