Java 上载到Google驱动器文件未找到异常
我想以编程方式访问特定的Excel电子表格,该电子表格将包含在我的项目文件夹中,并将其上载到Google Drive。我将电子表格包含在我的src文件夹中,并使用以下代码:Java 上载到Google驱动器文件未找到异常,java,android,file,Java,Android,File,我想以编程方式访问特定的Excel电子表格,该电子表格将包含在我的项目文件夹中,并将其上载到Google Drive。我将电子表格包含在我的src文件夹中,并使用以下代码: private void saveFileToDrive() { Thread t = new Thread(new Runnable() { @Override public void run() { try {
private void saveFileToDrive() {
Thread t = new Thread(new Runnable() {
@Override
public void run() {
try {
URL fileURL = getClass().getClassLoader().getResource("Untitled spreadsheet.xlsx");
String filePath2 = fileURL.getPath();
java.io.File fileContent = new java.io.File(filePath2);
FileContent mediaContent = new FileContent("application/vnd.ms-excel", fileContent);
File body = new File();
body.setTitle(fileContent.getName());
body.setMimeType("application/vnd.ms-excel");
File file = service.files().insert(body, mediaContent).setConvert(true).execute();
if (file != null) {
showToast("File uploaded: " + file.getTitle());
}
else
;
} catch (UserRecoverableAuthIOException e) {
startActivityForResult(e.getIntent(), REQUEST_AUTHORIZATION);
} catch (IOException e) {
e.printStackTrace();
}
}
});
t.start();
}
但是,我不断得到以下FileNotFoundException:
11-29 14:43:45.189: W/System.err(21133): java.io.FileNotFoundException: /file:/data/app/com.example.drivequickstart-2.apk!/Untitled spreadsheet.xlsx: open failed: ENOENT (No such file or directory)
有人知道这是什么原因吗
编辑:
我已尝试根据以下建议修改我的代码,如下所示:
private void saveFileToDrive() {
Thread t = new Thread(new Runnable() {
@Override
public void run() {
try {
String mime = "application/vnd.ms-excel";
InputStream in = getApplicationContext().getAssets().open("Untitled spreadsheet.xlsx");
InputStreamContent content = new InputStreamContent(mime, in);;
File body = new File();
body.setTitle("Untitled spreadsheet");
body.setMimeType("application/vnd.ms-excel");
File file = service.files().insert(body, content).setConvert(true).execute();
if (file != null) {
showToast("File uploaded: " + file.getTitle());
}
else
;
} catch (UserRecoverableAuthIOException e) {
startActivityForResult(e.getIntent(), REQUEST_AUTHORIZATION);
} catch (IOException e) {
e.printStackTrace();
}
}
});
t.start();
}
但是,这给了我以下错误:
11-29 20:31:08.118: E/AndroidRuntime(9833): java.lang.IllegalArgumentException
11-29 20:31:08.118: E/AndroidRuntime(9833): at com.google.common.base.Preconditions.checkArgument(Preconditions.java:76)
11-29 20:31:08.118: E/AndroidRuntime(9833): at com.google.api.client.googleapis.media.MediaHttpUploader.getMediaContentLength(MediaHttpUploader.java:328)
11-29 20:31:08.118: E/AndroidRuntime(9833): at com.google.api.client.googleapis.media.MediaHttpUploader.executeUploadInitiation(MediaHttpUploader.java:347)
11-29 20:31:08.118: E/AndroidRuntime(9833): at com.google.api.client.googleapis.media.MediaHttpUploader.upload(MediaHttpUploader.java:266)
11-29 20:31:08.118: E/AndroidRuntime(9833): at com.google.api.client.googleapis.services.AbstractGoogleClientRequest.executeUnparsed(AbstractGoogleClientRequest.java:408)
11-29 20:31:08.118: E/AndroidRuntime(9833): at com.google.api.client.googleapis.services.AbstractGoogleClientRequest.executeUnparsed(AbstractGoogleClientRequest.java:328)
11-29 20:31:08.118: E/AndroidRuntime(9833): at com.google.api.client.googleapis.services.AbstractGoogleClientRequest.execute(AbstractGoogleClientRequest.java:449)
11-29 20:31:08.118: E/AndroidRuntime(9833): at com.example.drivequickstart.MainActivity$3.run(MainActivity.java:303)
11-29 20:31:08.118: E/AndroidRuntime(9833): at java.lang.Thread.run(Thread.java:864)
并指向以下行:
File File=service.files().insert(body,content).setConvert(true).execute()
仔细检查后,我发现InputStreamContent的长度是-1,因此问题可能源自于此。您使用Java惯用语ClassLoader.getResource()
从类路径
加载资源。然而,这不是我们在Android上的做法
您将把文件放在assets/
目录或res/raw/
中,然后使用或类似R.raw.untitled\u spreadsheet.xlsx的标识符检索它
见:
虽然不常见,但您可能需要访问原始文件和
目录。如果这样做,那么将文件保存在res/中对
因为从res/读取资源的唯一方法是使用
资源ID。相反,您可以将资源保存在资产中/
目录
保存在资产/目录中的文件没有资源ID,因此
不能通过R类或从XML资源引用它们。
相反,您可以像普通用户一样查询资产/目录中的文件
并使用AssetManager读取原始数据
但是,如果您只需要能够读取原始数据(例如
视频或音频文件),然后将文件保存在res/raw/目录中,然后
使用openRawResource()读取字节流
用代码来说,如果将文件放入assets/sheet.xlsx
:
String mime = "application/vnd.ms-excel";
InputStream in = ctx.getAssets().open("sheet.xlsx");
InputStreamContent content = new InputStreamContent(mime, in);
其中,ctx
是一个。由于活动
是一个上下文
,如果您碰巧在活动
中编写此代码,可以跳过ctx
,直接调用getAssets()
注意,我没有使用FileContent
:而是选择了InputStreamContent
,因为您实际上没有java.io.File
对象,但是
基本上,您要求驱动器客户机:“从本地流读取字节,上载它们,并使它们可以在$name名称下访问”。名称$name
是通过com.google.api.services.drive.model.File
对象的标题
字段提供给服务的,该字段可以是您喜欢的任何字段-我认为它也可以包括目录分隔符
这是一个到的链接,要解决您关于“这是什么造成的?”的问题,请参阅讨论(围绕评论13)
这是一个简单的原因,您没有给它一个有效的文件路径。你
正在从类加载器获取资源,并且该资源是
来自一个罐子(实际上它从来没有被打开到盒子里)
文件系统)
因此,当您向资源的URL询问路径时
getPath()返回一个
(在您的情况下)文件:/data/app/com.example.drivequickstart-2.apk/无标题电子表格.xlsx
这不是合法的“文件:”url字符串
他还提出了一个非常恰当的解决方法:
您应该做的只是将字符串提供给构造函数
由URL.toString()返回。你应该得到的是某种
仍然指向jar文件的已注册url类型,但
VM中的url解析器知道如何处理
但是如何从InputStreamContent获取文件路径?什么文件路径?InputStreamContent
就是一个围绕输入流的包装器,它表示apkt中的本地资源。驱动器的File
对象表示存储在云中的文件的元数据。要上传文件(新文件或更新文件),您不需要任何元数据:只需要一个字节数组和一个MIME类型,这就是InputStreamContent
的用途。然后,您需要一个文件
对象来告诉如何在云中调用这个字节流。请注意,这不是一个java.io.File
,而是一个驱动器。你可以用任何你喜欢的名字调用setTitle()
。你的上一个建议非常有效。尽管我不得不手动设置这个长度属性,但我确实发现这很不寻常。@JohnRoberts确实如此。HTTP并不严格地需要它,必须有一种方法来跳过该度量,但是很难说是如何做到的-似乎当传输编码
设置为分块
时,您可以跳过内容长度
标题。这应该是默认行为,但可能我没有很好地读取文档…传入URL.toString()而不是文件路径会产生相同的错误。因此,如果您(正确地)认为问题在于InputStreamContent的长度,为什么不尝试设置它呢?因为资源是一项资产,您可以在您的开发机器上计算长度——否则您可以从输入流中一次读取一个字节(或者使用缓冲区),直到EOS,然后设置内容长度