Android Firebase 上传图片错误 URL(问题:缺少 X-Goog-Upload-Comment header)
Android Firebase uploading images wrong URL (PROBLEM: X-Goog-Upload-Comment header is missing)
我正在尝试从具有 URL link 的 Firabase 数据库上传和下载图像到 Firebase 存储。问题是奇怪的 URL 被保存到数据库(见底部的 link)。我应该怎么做才能获得正常的 URL,我可以使用它来将图像下载到我的 Android 应用程序中?提前致谢!
我在这里 post 我使用的一些代码:
上传到 Firebase 数据库和存储:
mStorageRef = FirebaseStorage.getInstance().getReference();
mDataBaseRef = FirebaseDatabase.getInstance().getReference();
if (mImageUri != null)
{
final StorageReference fileReference = mStorageRef.child(nameimage + "." + getFileExtension(mImageUri));
fileReference.putFile(mImageUri).addOnSuccessListener(new OnSuccessListener<UploadTask.TaskSnapshot>() {
@Override
public void onSuccess(UploadTask.TaskSnapshot taskSnapshot) {
Toast.makeText(AddAdvertisement.this, "Upload successful!", Toast.LENGTH_LONG).show();
Upload upload = new Upload(et_localization, taskSnapshot.getUploadSessionUri().toString());
String uploadId = mDataBaseRef.push().getKey();
mDataBaseRef.child(uploadId).setValue(upload);
}
}).addOnFailureListener(new OnFailureListener() {
@Override
public void onFailure(@NonNull Exception e) {
Toast.makeText(AddAdvertisement.this, e.getMessage(), Toast.LENGTH_SHORT).show();
}
});
并从 Firebase 下载:
databaseReference = FirebaseDatabase.getInstance().getReference();
databaseReference.addValueEventListener(new ValueEventListener() {
@Override
public void onDataChange(@NonNull DataSnapshot dataSnapshot) {
for (DataSnapshot postSnapshot : dataSnapshot.getChildren())
{
Upload upload = postSnapshot.getValue(Upload.class);
mUploads.add(upload);
}
mAdapter = new AdverisementAdapter(getContext(),mUploads);
mrecyclerView.setAdapter(mAdapter);
}
和毕加索要检索图像:
@Override
public void onBindViewHolder(@NonNull ImageViewHolder imageViewHolder, int i) {
Upload uploadCurrent = mUploads.get(i);
imageViewHolder.textViewName.setText(uploadCurrent.getName());
Picasso.get().load(uploadCurrent.getUrl()).into(imageViewHolder.imageView);
}
Picasso 工作正常,因为除了形成图像外,我还从 Firebase 字符串中获得了名称,该名称已正确下载。所以,我认为问题就出在这个错误 url:
当我尝试输入这个 link 时,我收到这样的错误:
请求无效。 X-Goog-Upload-Command header 缺失。
根据关于 UploadTask.TaskSnapshot 的 getUploadSessionUri() 方法的官方文档:
Returns the session Uri, valid for approximately one week, which can be used to resume an upload later by passing this value into putFile(Uri, StorageMetadata, Uri)
.
恐怕这不是您要找的Uri
。要获得正确的 uri,请从 post.
中查看我的回答
您正在将此值写入数据库:
taskSnapshot.getUploadSessionUri().toString()
这是上传会话的 URI,如果上传被中止,您可以使用它来恢复上传。
由于您想存储下载内容 URL,此调用对您来说毫无用处。相反,您应该调用 getDownloadUrl()
以(异步地)获取新上传文件的下载 URL:
fileReference.putFile(mImageUri).addOnSuccessListener(new OnSuccessListener<UploadTask.TaskSnapshot>() {
@Override
public void onSuccess(UploadTask.TaskSnapshot taskSnapshot) {
Toast.makeText(AddAdvertisement.this, "Upload successful!", Toast.LENGTH_LONG).show();
fileReference.getDownloadUrl().addOnSuccessListener(new OnSuccessListener<Uri>() {
@Override
public void onSuccess(Uri uri) {
String url = uri.toString();
Upload upload = new Upload(et_localization, url);
String uploadId = mDataBaseRef.push().getKey();
mDataBaseRef.child(uploadId).setValue(upload);
}
});
}
})...
请注意,这在 Firebase documentation on getting a download URL after uploading a file 中有很好的描述,该事件包括一个通过使用 continueWithTask
而不是嵌套回调(我在上面所做的)来完成相同的示例。
这对我不起作用(使用 Expo),但使用 XMLHttpRequest 可以。我在这里找到了这个解决方案:https://github.com/expo/expo/issues/2402#issuecomment-443726662
下面是我的代码,希望对您有所帮助。
_uploadImageAsync = async (uri) => {
try {
const blob = await new Promise((resolve, reject) => {
const xhr = new XMLHttpRequest();
xhr.onload = function () {
resolve(xhr.response);
};
xhr.onerror = function (e) {
console.log(e);
reject(new TypeError('Network request failed'));
};
xhr.responseType = 'blob';
xhr.open('GET', uri, true);
xhr.send(null);
});
const ref = firebase
.storage()
.ref()
.child('images/usersPicture/test');
const snapshot = await ref.put(blob);
blob.close();
return await snapshot.ref.getDownloadURL();
} catch(error) {
console.log(error)
}
}
fileReference.putFile(mImageUri).addOnSuccessListener(new OnSuccessListener<UploadTask.TaskSnapshot>() {
@Override
public void onSuccess(UploadTask.TaskSnapshot taskSnapshot) {
Toast.makeText(AddAdvertisement.this, "Upload successful!", Toast.LENGTH_LONG).show();
fileReference.getDownloadUrl().addOnSuccessListener(new OnSuccessListener<Uri>() {
@Override
public void onSuccess(Uri uri) {
// just do your task //like hashmaps to put in
}
});
}
})
我正在尝试从具有 URL link 的 Firabase 数据库上传和下载图像到 Firebase 存储。问题是奇怪的 URL 被保存到数据库(见底部的 link)。我应该怎么做才能获得正常的 URL,我可以使用它来将图像下载到我的 Android 应用程序中?提前致谢!
我在这里 post 我使用的一些代码:
上传到 Firebase 数据库和存储:
mStorageRef = FirebaseStorage.getInstance().getReference();
mDataBaseRef = FirebaseDatabase.getInstance().getReference();
if (mImageUri != null)
{
final StorageReference fileReference = mStorageRef.child(nameimage + "." + getFileExtension(mImageUri));
fileReference.putFile(mImageUri).addOnSuccessListener(new OnSuccessListener<UploadTask.TaskSnapshot>() {
@Override
public void onSuccess(UploadTask.TaskSnapshot taskSnapshot) {
Toast.makeText(AddAdvertisement.this, "Upload successful!", Toast.LENGTH_LONG).show();
Upload upload = new Upload(et_localization, taskSnapshot.getUploadSessionUri().toString());
String uploadId = mDataBaseRef.push().getKey();
mDataBaseRef.child(uploadId).setValue(upload);
}
}).addOnFailureListener(new OnFailureListener() {
@Override
public void onFailure(@NonNull Exception e) {
Toast.makeText(AddAdvertisement.this, e.getMessage(), Toast.LENGTH_SHORT).show();
}
});
并从 Firebase 下载:
databaseReference = FirebaseDatabase.getInstance().getReference();
databaseReference.addValueEventListener(new ValueEventListener() {
@Override
public void onDataChange(@NonNull DataSnapshot dataSnapshot) {
for (DataSnapshot postSnapshot : dataSnapshot.getChildren())
{
Upload upload = postSnapshot.getValue(Upload.class);
mUploads.add(upload);
}
mAdapter = new AdverisementAdapter(getContext(),mUploads);
mrecyclerView.setAdapter(mAdapter);
}
和毕加索要检索图像:
@Override
public void onBindViewHolder(@NonNull ImageViewHolder imageViewHolder, int i) {
Upload uploadCurrent = mUploads.get(i);
imageViewHolder.textViewName.setText(uploadCurrent.getName());
Picasso.get().load(uploadCurrent.getUrl()).into(imageViewHolder.imageView);
}
Picasso 工作正常,因为除了形成图像外,我还从 Firebase 字符串中获得了名称,该名称已正确下载。所以,我认为问题就出在这个错误 url:
当我尝试输入这个 link 时,我收到这样的错误:
请求无效。 X-Goog-Upload-Command header 缺失。
根据关于 UploadTask.TaskSnapshot 的 getUploadSessionUri() 方法的官方文档:
Returns the session Uri, valid for approximately one week, which can be used to resume an upload later by passing this value into
putFile(Uri, StorageMetadata, Uri)
.
恐怕这不是您要找的Uri
。要获得正确的 uri,请从 post.
您正在将此值写入数据库:
taskSnapshot.getUploadSessionUri().toString()
这是上传会话的 URI,如果上传被中止,您可以使用它来恢复上传。
由于您想存储下载内容 URL,此调用对您来说毫无用处。相反,您应该调用 getDownloadUrl()
以(异步地)获取新上传文件的下载 URL:
fileReference.putFile(mImageUri).addOnSuccessListener(new OnSuccessListener<UploadTask.TaskSnapshot>() {
@Override
public void onSuccess(UploadTask.TaskSnapshot taskSnapshot) {
Toast.makeText(AddAdvertisement.this, "Upload successful!", Toast.LENGTH_LONG).show();
fileReference.getDownloadUrl().addOnSuccessListener(new OnSuccessListener<Uri>() {
@Override
public void onSuccess(Uri uri) {
String url = uri.toString();
Upload upload = new Upload(et_localization, url);
String uploadId = mDataBaseRef.push().getKey();
mDataBaseRef.child(uploadId).setValue(upload);
}
});
}
})...
请注意,这在 Firebase documentation on getting a download URL after uploading a file 中有很好的描述,该事件包括一个通过使用 continueWithTask
而不是嵌套回调(我在上面所做的)来完成相同的示例。
这对我不起作用(使用 Expo),但使用 XMLHttpRequest 可以。我在这里找到了这个解决方案:https://github.com/expo/expo/issues/2402#issuecomment-443726662
下面是我的代码,希望对您有所帮助。
_uploadImageAsync = async (uri) => {
try {
const blob = await new Promise((resolve, reject) => {
const xhr = new XMLHttpRequest();
xhr.onload = function () {
resolve(xhr.response);
};
xhr.onerror = function (e) {
console.log(e);
reject(new TypeError('Network request failed'));
};
xhr.responseType = 'blob';
xhr.open('GET', uri, true);
xhr.send(null);
});
const ref = firebase
.storage()
.ref()
.child('images/usersPicture/test');
const snapshot = await ref.put(blob);
blob.close();
return await snapshot.ref.getDownloadURL();
} catch(error) {
console.log(error)
}
}
fileReference.putFile(mImageUri).addOnSuccessListener(new OnSuccessListener<UploadTask.TaskSnapshot>() {
@Override
public void onSuccess(UploadTask.TaskSnapshot taskSnapshot) {
Toast.makeText(AddAdvertisement.this, "Upload successful!", Toast.LENGTH_LONG).show();
fileReference.getDownloadUrl().addOnSuccessListener(new OnSuccessListener<Uri>() {
@Override
public void onSuccess(Uri uri) {
// just do your task //like hashmaps to put in
}
});
}
})